Submission #823906

#TimeUsernameProblemLanguageResultExecution timeMemory
823906tch1cherinJoker (BOI20_joker)C++17
100 / 100
561 ms50548 KiB
#include <bits/stdc++.h> using namespace std; struct dsu { int size; int _bipartite; vector<vector<pair<int*, int>>> updates; vector<int> parent, rank; dsu(int _size) : size(_size), _bipartite(1), parent(2 * _size, -1), rank(2 * _size, 1) {} int _get(int u) { return parent[u] == -1 ? u : _get(parent[u]); } void _unite(int u, int v) { u = _get(u), v = _get(v); if (u != v) { if (rank[u] < rank[v]) { swap(u, v); } updates.back().push_back(pair {&parent[v], parent[v]}); updates.back().push_back(pair {&rank[u], rank[u]}); parent[v] = u; rank[u] += rank[v]; } } void unite(int u, int v) { updates.push_back({}); updates.back().push_back(pair {&_bipartite, _bipartite}); _unite(u, v + size); _unite(v, u + size); if (_get(u) == _get(u + size)) { _bipartite = 0; } if (_get(v) == _get(v + size)) { _bipartite = 0; } } void undo() { for (auto &[x, y] : updates.back()) { *x = y; } updates.pop_back(); } bool is_bipartite() { return _bipartite > 0; } }; struct dsu_queue { struct update { int type; int u, v; }; int size; vector<update> updates; int sign; int cntA = 0, cntB = 0; dsu base; dsu_queue(int _size) : size(_size), sign(1), base(_size) {} void unite(int u, int v) { base.unite(u, v); (sign > 0 ? cntA : cntB)++; updates.push_back({sign, u, v}); } void undo() { if (sign == 1) { for (int i = 0; i < (int)updates.size(); i++) { base.undo(); } reverse(updates.begin(), updates.end()); for (auto [type, x, y] : updates) { base.unite(x, y); } sign = -1; swap(cntA, cntB); } vector<update> old_updates, new_updates; while (old_updates.size() < new_updates.size() || old_updates.empty()) { if (updates.empty()) { break; } if (updates.back().type > 0) { old_updates.push_back(updates.back()); } else { new_updates.push_back(updates.back()); } updates.pop_back(); base.undo(); } for (int i = (int)new_updates.size() - 1; i >= 0; i--) { auto [type, x, y] = new_updates[i]; base.unite(x, y); updates.push_back({type, x, y}); } for (int i = (int)old_updates.size() - 1; i > 0; i--) { auto [type, x, y] = old_updates[i]; base.unite(x, y); updates.push_back({type, x, y}); } cntA--; if (cntA == 0) { cntA = cntB; for (auto &[type, x, y] : updates) { type = 1; } sign = 1; } } bool is_bipartite() { return base.is_bipartite(); } }; int main() { cin.tie(nullptr)->sync_with_stdio(false); int N, M, Q; cin >> N >> M >> Q; vector<pair<int, int>> edges(M); dsu_queue q(N); for (auto &[u, v] : edges) { cin >> u >> v; u--, v--; q.unite(u, v); } vector<int> R(M); for (int i = 0, j = 0; i < M; i++) { while (j < M && !q.is_bipartite()) { q.undo(); j++; } if (q.is_bipartite()) { R[i] = j; } else { R[i] = M + 1; } if (j > i) { q.unite(edges[i].first, edges[i].second); } } for (int i = 0; i < Q; i++) { int l, r; cin >> l >> r; cout << (R[--l] > r ? "YES\n" : "NO\n"); } }
#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...