Submission #475779

#TimeUsernameProblemLanguageResultExecution timeMemory
475779blueJoker (BOI20_joker)C++17
0 / 100
1 ms2636 KiB
#include <iostream> #include <vector> #include <stack> #include <cassert> using namespace std; struct disjoint_set { int N; vector<int> parent; vector<int> parent_edge; vector<int> subtree; stack<int> ops; stack<bool> bipartite; 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 join(int u, int v) { int opp = 1; 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() { int u = ops.top(); ops.pop(); bipartite.pop(); subtree[ parent[u] ] -= subtree[u]; parent[u] = u; parent_edge[u] = 0; } 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); //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]); } void solve(int l1, int l2, int r1, int r2) // [L, R] == [l1, r2] at the beginning { assert(L == l1); assert(R == r2); int lmid = (l1+l2)/2; int rmid; if(!DSU.is_bipartite()) { for(int i = lmid; i <= l2; i++) minR[i] = M+1; if(l1 <= lmid-1) { solve(l1, lmid-1, r1, r2); //ADJUST L AND R!!!!! -> not necessary } } while(L < lmid) contract_left(); rmid = r2; while(DSU.is_bipartite()) { rmid = min(rmid, R); contract_right(); } minR[lmid] = rmid; while(R < r2) expand_right(); while(l1 < L) expand_left(); assert(L == l1 && R == r2); if(l1 <= lmid-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) { 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() { 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 <= 2*Q; u++) cin >> x; for(int u = 1; u <= Q; u++) cout << "NO\n"; } L = 1; R = M; solve(1, M, 1, M); 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 } }
#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...