Submission #209827

#TimeUsernameProblemLanguageResultExecution timeMemory
209827stefdascaPort Facility (JOI17_port_facility)C++14
0 / 100
5 ms376 KiB
/* JOISC 17-port_facility Let's define a graph where each container is a vertex and we draw edges between two containers which can't be put in the same area. Therefore, the answer will be 2^(number of connected components) or 0 if the graph isn't bipartite(this can be checked beforehand with some simulation). Since the number of edges can be really big, we need segment tree to reduce the number of edges we are going to use. */ #include<bits/stdc++.h> #define god dimasi5eks #pragma GCC optimize("O3") #define fi first #define se second #define pb push_back #define pf push_front #define mod 1000000007 #define dancila 3.14159265359 #define eps 1e-9 // #define fisier 1 using namespace std; typedef long long ll; int n; pair<int, int> bk[1000002]; int poz[2000002]; void chk() { vector<int> d[2]; for(int i = 1; i <= n; ++i) { for(int j = 0; j <= 1; ++j) while(!d[j].empty() && d[j].back() < bk[i].fi) d[j].pop_back(); if(d[0].empty() && d[1].empty()) d[0].pb(bk[i].se); else if(d[1].empty()) { if(bk[i].se < d[0].back()) d[0].pb(bk[i].se); else d[1].pb(bk[i].se); } else if(d[0].empty()) { if(bk[i].se < d[1].back()) d[1].pb(bk[i].se); else d[0].pb(bk[i].se); } else { if(bk[i].se > max((int) d[0].back(), (int) d[1].back())) { cout << 0 << '\n'; exit(0); } if(d[0].back() < d[1].back()) { if(bk[i].se < d[0].back()) d[0].pb(bk[i].se); else d[1].pb(bk[i].se); } else { if(bk[i].se < d[1].back()) d[1].pb(bk[i].se); else d[0].pb(bk[i].se); } } } } int aint[8000002], aint2[8000002]; void upd(int nod, int st, int dr, int poz, int val) { if(st == dr) { aint[nod] = val; return; } int mid = (st + dr) / 2; if(poz <= mid) upd(nod << 1, st, mid, poz, val); else upd(nod << 1|1, mid+1, dr, poz, val); aint[nod] = max(aint[nod << 1], aint[nod << 1|1]); } int query(int nod, int st, int dr, int L, int R) { if(dr < L || st > R) return -(1<<30); if(L <= st && dr <= R) return aint[nod]; int mid = (st + dr) / 2; return max(query(nod << 1, st, mid, L, R), query(nod << 1|1, mid+1, dr, L, R)); } void upd2(int nod, int st, int dr, int poz, int val) { if(st == dr) { aint2[nod] = val; return; } int mid = (st + dr) / 2; if(poz <= mid) upd2(nod << 1, st, mid, poz, val); else upd2(nod << 1|1, mid+1, dr, poz, val); aint2[nod] = min(aint2[nod << 1], aint2[nod << 1|1]); } int query2(int nod, int st, int dr, int L, int R) { if(dr < L || st > R) return (1<<30); if(L <= st && dr <= R) return aint2[nod]; int mid = (st + dr) / 2; return min(query2(nod << 1, st, mid, L, R), query2(nod << 1|1, mid+1, dr, L, R)); } bool viz[1000002]; void dfs(int nod) { viz[nod] = 1; upd(1, 1, n+n, bk[nod].fi, -(1<<30)); upd2(1, 1, n+n, bk[nod].se, (1<<30)); while(1) { int val = (1<<30); if(bk[nod].fi + 1 <= bk[nod].se - 1) val = query2(1, 1, n+n, bk[nod].fi + 1, bk[nod].se - 1); // cout << "A " << nod << " " << val << '\n'; if(val < bk[nod].fi) dfs(poz[val]); else break; } while(1) { int val = -(1<<30); if(bk[nod].fi + 1 <= bk[nod].se - 1) val = query(1, 1, n+n, bk[nod].fi + 1, bk[nod].se - 1); // cout << "B " << nod << " " << val << '\n'; if(val > bk[nod].se) dfs(poz[val]); else break; } } int main() { #ifdef fisier ifstream f("input.in"); ofstream g("output.out"); #endif ios_base::sync_with_stdio(false); cin.tie(NULL); cin >> n; for(int i = 1; i <= n+n; ++i) { upd(1, 1, n+n, i, -(1<<30)); upd2(1, 1, n+n, i, (1<<30)); } for(int i = 1; i <= n; ++i) { cin >> bk[i].fi >> bk[i].se; poz[bk[i].fi] = poz[bk[i].se] = i; upd(1, 1, n+n, bk[i].fi, bk[i].se); upd2(1, 1, n+n, bk[i].se, bk[i].fi); } chk(); int ans = 1; for(int i = 1; i <= n; ++i) if(!viz[i]) { ans = (ans * 2) % mod; dfs(i); } cout << ans << '\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...