제출 #440193

#제출 시각아이디문제언어결과실행 시간메모리
440193koioi.org-koosaga열쇠 (IOI21_keys)C++17
37 / 100
3082 ms120396 KiB
#include <bits/stdc++.h> #define sz(v) ((int)(v).size()) #define all(v) (v).begin(), (v).end() using namespace std; using lint = long long; using pi = pair<int, int>; const int MAXN = 600005; struct disj{ int pa[MAXN]; void init(){ iota(pa, pa + MAXN, 0); } int find(int x){ return pa[x] = (pa[x] == x ? x : find(pa[x])); } bool uni(int p, int q){ p = find(p); q = find(q); if(p == q) return 0; pa[q] = p; return 1; } }disj; set<int> keys[MAXN]; set<pi> gph[MAXN]; vector<int> canReach[MAXN]; int comp[MAXN], nxt[MAXN]; int idx[MAXN], sz[MAXN]; int find(int x){ return comp[x] = (comp[x] == x ? x : find(comp[x])); } int cnt = 0; void merge_to(int u, int v){ u = find(u); cnt++; if(cnt >= 2000000) assert(0); if(u == v) return; comp[u] = v; int ov = v; if(sz[u] > sz[v]) swap(u, v); sz[v] += sz[u]; for(auto &i : keys[idx[u]]){ if(keys[idx[v]].find(i) == keys[idx[v]].end()){ keys[idx[v]].insert(i); auto it = gph[idx[v]].lower_bound(pi(i, -1)); while(it != gph[idx[v]].end() && it->first == i){ canReach[idx[v]].push_back(it->second); it = gph[idx[v]].erase(it); } } } for(auto &i : canReach[idx[u]]) canReach[idx[v]].push_back(i); for(auto &[c, d] : gph[idx[u]]){ if(keys[idx[v]].find(c) != keys[idx[v]].end()){ canReach[idx[v]].push_back(d); } else gph[idx[v]].emplace(c, d); } keys[idx[u]].clear(); gph[idx[u]].clear(); canReach[idx[u]].clear(); idx[ov] = idx[v]; } std::vector<int> find_reachable(std::vector<int> r, std::vector<int> u, std::vector<int> v, std::vector<int> c) { int n = sz(r); for(int i = 0; i < n; i++) keys[i].insert(r[i]); for(int i = 0; i < sz(u); i++){ if(c[i] == r[u[i]]){ canReach[u[i]].push_back(v[i]); } else{ gph[u[i]].emplace(c[i], v[i]); } if(c[i] == r[v[i]]){ canReach[v[i]].push_back(u[i]); } else { gph[v[i]].emplace(c[i], u[i]); } } disj.init(); iota(idx, idx + MAXN, 0); fill(sz, sz + MAXN, 1); iota(comp, comp + MAXN, 0); vector<int> ans(n, 1e9); for(int i = 0; i < n; i++){ nxt[i] = i; if(sz(canReach[i])) nxt[i] = canReach[i][0]; } for(int i = 0; i < n; i++){ if(find(i) != i) continue; if(i == find(nxt[i])) continue; if(!disj.uni(i, nxt[i])){ for(int j = find(nxt[i]); find(j) != find(n); j = find(nxt[j])){ merge_to(j, n); } disj.uni(i, n); nxt[n] = n; while(sz(canReach[idx[n]]) && find(canReach[idx[n]].back()) == find(n)){ canReach[idx[n]].pop_back(); } if(sz(canReach[idx[n]])) nxt[n] = canReach[idx[n]].back(); n++; } } vector<int> cnt(n); for(int j = 0; j < sz(ans); j++){ cnt[find(j)]++; } fill(all(ans), 1e9); for(int i = 0; i < sz(ans); i++){ int r = find(i); if(find(r) == find(nxt[r])) ans[i] = cnt[r]; } int val = *min_element(all(ans)); for(auto &i : ans){ i = (i == val); } return ans; }
#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...