Submission #553296

#TimeUsernameProblemLanguageResultExecution timeMemory
553296RaresFelixCollapse (JOI18_collapse)C++17
100 / 100
5305 ms459620 KiB
#include "collapse.h" #include <bits/stdc++.h> #pragma GCC optimize("O3,unroll-loops") #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") using namespace std; using Edge = tuple<int, int, int, int>; //from, to, begin, end using vEd = vector<Edge>; using vi = vector<int>; struct RollbackUF { vi e; vector<pair<int, int> > st; RollbackUF(int n) : e(n, -1) {} int size(int x) { return -e[find(x)]; } int find(int x) { return e[x] < 0 ? x : find(e[x]); } int time() { return int(st.size()); } void rollback(int t) { for (int i = time(); i --> t;) e[st[i].first] = st[i].second; st.resize(t); } bool join(int a, int b) { a = find(a), b = find(b); if (a == b) return false; if (e[a] > e[b]) swap(a, b); st.push_back({a, e[a]}); st.push_back({b, e[b]}); e[a] += e[b]; e[b] = a; return true; } }; struct Bucket { RollbackUF Simu; int begin, end; Bucket(int n, int begin, int end) : Simu(n), begin(begin), end(end) {} vector<Edge> idk; void add_edge(Edge nou) { auto &[f, t, b, e] = nou; if(e < begin || end < b) return; if(b <= begin && end <= e) { //complet Simu.join(f, t); return; } idk.push_back(nou); } int query(int timp) { int count0 = Simu.time(); for(auto &it : idk) { auto &[f, t, b, e] = it; if(b <= timp && timp <= e) Simu.join(f, t); } int re = Simu.st.size() >> 1; Simu.rollback(count0); return re; } }; void solve(int n, int c, int q, vEd &edges, vi &W, vi &P, vi &R) { R.assign(q, 0); vector<vi> Queries(n + 2); for(int i = 0; i < q; ++i) Queries[P[i]].push_back(i); vector<vEd> Add(n + 1); for(auto &[f, t, b, e] : edges) Add[t].push_back({f, t, b, e}); int bucketSize = int(sqrt(c + 1)); vector<Bucket> Sol; for(int lp = 0; lp <= c + 1; lp += bucketSize) Sol.emplace_back(n, lp, lp + bucketSize - 1); for(int i = 0; i < n; ++i) { for(auto &it : Add[i]) for(auto &seg : Sol) seg.add_edge(it); for(auto &qid : Queries[i]) { int w = W[qid]; int re = 0; for(auto &seg : Sol) { if(seg.begin <= w && w <= seg.end) { re = seg.query(w); break; } } R[qid] = i + 1 - re; } } } vector<int> simulateCollapse( int n, vector<int> T, vector<int> X, vector<int> Y, vector<int> W, vector<int> P ) { vEd edges; int c = T.size(), q = W.size(); map<pair<int, int>, int> enabled; for(int i = 0 ; i < c; ++i) if(X[i] > Y[i]) swap(X[i], Y[i]); for(int i = 0 ; i < c; ++i) { if(!T[i]) enabled[{X[i], Y[i]}] = i; else { edges.push_back({X[i], Y[i], enabled[{X[i], Y[i]}], i - 1}); enabled[{X[i], Y[i]}] = -1; } } for(auto [p, e] : enabled) if(e != -1) { auto [f, t] = p; edges.push_back({f, t, e, c + 1}); } vector<int> R, R1, R2; solve(n, c, q, edges, W, P, R1); for(auto &it : P) it = n - 2 - it; for(auto &[a, b, c, d] : edges) a = n - 1 - a, b = n - 1 - b, a ^= b, b ^= a, a ^= b; solve(n, c, q, edges, W, P, R2); for(int i = 0; i < q; ++i) R.push_back(R1[i] + R2[i]); return R; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...