Submission #475858

#TimeUsernameProblemLanguageResultExecution timeMemory
475858blueJoker (BOI20_joker)C++17
0 / 100
2085 ms262148 KiB
#include <iostream> #include <vector> #include <stack> #include <cassert> using namespace std; bool DBG = 1; void asrt(bool b) { if(!b) { cerr << "failed!\n"; while(1); } } struct disjoint_set { int N; vector<int> parent; vector<int> parent_edge; //xor vector<int> subtree; stack<int> ops; stack<bool> bipartite; stack< stack<int> > compress_node; stack< stack<int> > prev_parent; stack< stack<int> > prev_toggle; disjoint_set() { ; } disjoint_set(int N_) { N = N_; parent = vector<int>(1+N); parent_edge = vector<int>(1+N); subtree = vector<int>(1+N); for(int i = 0; i <= N; i++) { parent[i] = i; parent_edge[i] = 0; subtree[i] = 1; } ops.push(0); bipartite.push(1); } void compress(int u) { bool toggle = 0; int v = u; for(v = u; parent[v] != v; v = parent[v]) { toggle ^= parent_edge[v]; } if(v == parent[u] || v == u) { compress_node.top().push(-1); prev_parent.top().push(-1); prev_toggle.top().push(-1); } else { compress_node.top().push(u); prev_parent.top().push(parent[u]); prev_toggle.top().push(parent_edge[u]); parent[u] = v; parent_edge[u] = toggle; } } void decompress() { int u = compress_node.top().top(); int v = prev_parent.top().top(); int t = prev_toggle.top().top(); asrt(!compress_node.empty()); asrt(!prev_parent.empty()); asrt(!prev_toggle.empty()); asrt(!compress_node.top().empty()); asrt(!prev_parent.top().empty()); asrt(!prev_toggle.top().empty()); compress_node.top().pop(); prev_parent.top().pop(); prev_toggle.top().pop(); if(t != -1) { parent[u] = v; parent_edge[u] = t; } } int root(int u) { while(parent[u] != u) u = parent[u]; return u; } void join(int u, int v) { // cerr << "join " << u << ' ' << v << '\n'; int opp = 1; compress_node.push(stack<int>{}); prev_parent.push(stack<int>{}); prev_toggle.push(stack<int>{}); compress(u); compress(v); while(u != parent[u]) { opp ^= parent_edge[u]; u = parent[u]; } while(v != parent[v]) { opp ^= parent_edge[v]; v = parent[v]; } if(u == v) { ops.push(0); if(bipartite.top()) { if(opp == 0) bipartite.push(1); else bipartite.push(0); } else bipartite.push(0); } else { if(subtree[u] < subtree[v]) swap(u, v); parent[v] = u; parent_edge[v] = opp; subtree[u] += subtree[v]; ops.push(v); bipartite.push( bipartite.top() ); } } void rollback() { // cerr << "rollback\n"; int u = ops.top(); ops.pop(); bipartite.pop(); subtree[ parent[u] ] -= subtree[u]; parent[u] = u; parent_edge[u] = 0; while(!(compress_node.top()).empty()) { decompress(); } asrt(!compress_node.empty()); asrt(!prev_parent.empty()); asrt(!prev_toggle.empty()); compress_node.pop(); prev_parent.pop(); prev_toggle.pop(); } bool is_bipartite() { return bipartite.top(); } }; const int maxN = 200'000; const int maxM = 200'000; int N, M, Q; vector<int> u(1+maxM), v(1+maxM); vector<int> minR(1+maxN, 0); //the minimum value of R so that if the roads i, ... R are blocked the graph is bipartite disjoint_set DSU; int L; int R; void expand_right() { R++; DSU.rollback(); } void contract_right() { R--; DSU.join(u[R+1], v[R+1]); } void expand_left() { L--; DSU.rollback(); } void contract_left() { L++; DSU.join(u[L-1], v[L-1]); } bool flag = 0; void solve(int l1, int l2, int r1, int r2) // [L, R] == [l1, r2] at the beginning { // cerr << "solve " << l1 << ' ' << l2 << ' ' << r1 << ' ' << r2 << '\n'; bool F = 0; if(l1 <= 8 && 8 <= l2) F = 1; // assert(L == l1); // assert(R == r2); int lmid = (l1+l2)/2; int rmid; flag = 0; // dbg(lmid); // cerr << "hello\n"; // if(F) cerr << "special solve " << l1 << ' ' << l2 << ' ' << r1 << ' ' << r2 << '\n'; if(!DSU.is_bipartite()) { if(DBG) while(1); // if(F) cerr << "!!!!\n"; // if(!F) // { // cerr << L << ' ' << R << '\n'; // cerr << "???????\n"; // // // cerr << "###\n"; // // // cerr << "DSU: "; // for(int i = 1; i <= N; i++) cerr << DSU.root(i) << ' '; // cerr << '\n'; // } // cerr << "check\n"; // cerr << l1 << ' ' << l2 << " emergency\n"; // cerr << lmid << '\n'; // cerr << "M = " << M << '\n'; for(int i = lmid; i <= l2; i++) { minR[i] = M+1; // cerr << minR[i] << '\n'; } if(l1 <= lmid-1) { solve(l1, lmid-1, r1, r2); //ADJUST L AND R!!!!! -> not necessary } return; } // cerr << // for(int i = 1; i <= N; i++) dbg(to_string(i), DSU.root(i)); // dbg(DSU.is_bipartite()); while(L < lmid) { if(DBG) while(1); contract_left(); } // if(F)cerr<<"lmid="<<lmid<<"\n"; if(!DSU.is_bipartite()) { if(DBG) while(1); while(l1 < L) expand_left(); // cerr << "check\n"; // cerr << l1 << ' ' << l2 << " emergency\n"; // cerr << lmid << '\n'; // cerr << "M = " << M << '\n'; for(int i = lmid; i <= l2; i++) { minR[i] = M+1; // cerr << minR[i] << '\n'; } if(l1 <= lmid-1) { solve(l1, lmid-1, r1, r2); //ADJUST L AND R!!!!! -> not necessary } return; } // if(F) cerr << "check\n"; rmid = r2; while(DSU.is_bipartite()) { // cerr << "bipartite = yes\n"; rmid = min(rmid, R); contract_right(); } // cerr << "rmid = " << rmid << '\n'; minR[lmid] = rmid; while(R < r2) expand_right(); while(l1 < L) expand_left(); // assert(L == l1 && R == r2); if(l1 <= lmid-1) { if(DBG) while(1); while(rmid < R) contract_right(); // assert(L == l1 && R == rmid); solve(l1, lmid-1, r1, rmid); while(R < r2) expand_right(); } if(lmid+1 <= l2) { if(DBG) while(1); while(L < lmid+1) contract_left(); // assert(L == lmid+1 && R == r2); solve(lmid+1, l2, rmid, r2); while(l1 < L) expand_left(); } // assert(L == l1 && R == r2); } int main() { if(N+M+Q > 600) while(1); ios_base::sync_with_stdio(false); cin.tie(NULL); cin >> N >> M >> Q; for(int j = 1; j <= M; j++) cin >> u[j] >> v[j]; DSU = disjoint_set(N); disjoint_set temp(N); for(int j = 1; j <= M; j++) temp.join(u[j], v[j]); if(temp.is_bipartite()) { int x; for(int u = 1; u <= Q; u++) { cin >> x >> x; cout << "NO\n"; } return 0; } L = 1; R = M; solve(1, M, 1, M); // for(int j = 1; j <= M; j++) cerr << minR[j] << ' '; // cerr << '\n'; for(int q = 1; q <= Q; q++) { int l, r; cin >> l >> r; if(minR[l] <= r) cout << "NO\n"; //bipartite else cout << "YES\n"; //not bipartite } }

Compilation message (stderr)

Joker.cpp: In function 'void solve(int, int, int, int)':
Joker.cpp:235:10: warning: variable 'F' set but not used [-Wunused-but-set-variable]
  235 |     bool F = 0;
      |          ^
Joker.cpp: In function 'int main()':
Joker.cpp:366:1: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
  366 | if(N+M+Q > 600)
      | ^~
Joker.cpp:368:5: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
  368 |     ios_base::sync_with_stdio(false);
      |     ^~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...