제출 #383891

#제출 시각아이디문제언어결과실행 시간메모리
383891rama_pangPort Facility (JOI17_port_facility)C++14
100 / 100
4871 ms312600 KiB
#include <bits/stdc++.h> using namespace std; // Assume there is only 1 stack. // Then all containers' intervals in the stack must be nonintersecting. // We need to count number of ways to split A[] into 2 subsequences, // s.t. each subsequence has nonintersecting intervals. // // Create an ede (u, v) if interval u and interval v intersects (not overlaps). // Then, this graph must be bipartite. For each connected component, there are // 2 ways to put it into A or B. So the answer = 2^{connected components}. // (0 if the graph is not bipartite). // // We can simulate edges with a segment tree and do a DFS. Since we only traverse // each node once, this runs in O(N log N). template<typename T> class SegmentTree { public: int n; T init; vector<T> tree; function<T(T, T)> f; SegmentTree() {} SegmentTree(int n, T init, function<T(T, T)> f) : n(n), init(init), tree(2 * n, init), f(f) {} void Modify(int p, T x) { tree[p += n] = x; for (p /= 2; p > 0; p /= 2) { tree[p] = f(tree[p * 2], tree[p * 2 + 1]); } } T Query(int l, int r) { T res = init; for (l += n, r += n + 1; l < r; l /= 2, r /= 2) { if (l & 1) res = f(res, tree[l++]); if (r & 1) res = f(res, tree[--r]); } return res; } }; const int MOD = 1e9 + 7; int N; vector<pair<int, int>> A; SegmentTree<pair<int, int>> L; // query maximum, element at L[i] is R[i] SegmentTree<pair<int, int>> R; // query minimum, element at R[i] is L[i] void Dfs(int u, int c, vector<int> &colors) { if (colors[u] != -1) { return; } colors[u] = c; while (true) { auto q = L.Query(A[u].first + 1, A[u].second - 1); if (A[u].second < q.first) { L.Modify(A[q.second].first, L.init); Dfs(q.second, 1 - c, colors); } else { break; } } while (true) { auto q = R.Query(A[u].first + 1, A[u].second - 1); if (q.first < A[u].first) { R.Modify(A[q.second].second, R.init); Dfs(q.second, 1 - c, colors); } else { break; } } } bool NotIntersect(vector<pair<int, int>> ints) { vector<int> st; sort(begin(ints), end(ints)); for (auto p : ints) { while (!st.empty() && st.back() < p.first) { st.pop_back(); } if (!st.empty() && st.back() < p.second) { return false; } st.emplace_back(p.second); } return true; } int main() { ios::sync_with_stdio(0); cin.tie(0); cin >> N; L = SegmentTree<pair<int, int>>(2 * N, {-MOD, -MOD}, [&](pair<int, int> a, pair<int, int> b) { return max(a, b); }); R = SegmentTree<pair<int, int>>(2 * N, {+MOD, +MOD}, [&](pair<int, int> a, pair<int, int> b) { return min(a, b); }); A.resize(N); for (int i = 0; i < N; i++) { cin >> A[i].first >> A[i].second; A[i].first--, A[i].second--; L.Modify(A[i].first, {A[i].second, i}); R.Modify(A[i].second, {A[i].first, i}); } int ans = 1; vector<int> colors(N, -1); vector<pair<int, int>> C1, C2; for (int i = 0; i < N; i++) { if (colors[i] == -1) { ans = 2ll * ans % MOD; L.Modify(A[i].first, L.init); R.Modify(A[i].second, R.init); Dfs(i, 0, colors); } } for (int i = 0; i < N; i++) { (colors[i] ? C1 : C2).emplace_back(A[i]); } cout << (NotIntersect(C1) && NotIntersect(C2) ? ans : 0) << '\n'; return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...