Submission #1079569

#TimeUsernameProblemLanguageResultExecution timeMemory
1079569bleahbleahComparing Plants (IOI20_plants)C++17
5 / 100
449 ms70792 KiB
#include "plants.h" #include <bits/stdc++.h> #define all(x) (x).begin(),(x).end() using namespace std; using ll = long long; #define sz(x) ((int)(x).size()) int K, N; const int nmax = 2e5 + 5; template<typename T> struct AINT { vector<T> aint; int n; void init(int n_) { n = n_; aint.assign(2 * n + 5, T()); } template<int dir = 0, class CB> void walk(CB&& cb) { walk(cb, 0, n - 1); } template<int dir = 0, class CB> void walk(CB&& cb, int l, int r) { walk(cb, l, r, 1, 0, n - 1); } template<int dir = 0, class CB> void walk(CB&& cb, int l, int r, int node, int cl, int cr) { if(cr < l || r < cl) return; if(l <= cl && cr <= r && !cb(aint[node], cl, cr)) return; int mid = (cl + cr) >> 1, L = node + 1, R = node + (mid - cl + 1) * 2; aint[node].push(aint[L], aint[R]); if(dir == 0) { walk(cb, l, r, L, cl, mid); walk(cb, l, r, R, mid + 1, cr); } if(dir == 1) { walk(cb, l, r, R, mid + 1, cr); walk(cb, l, r, L, cl, mid); } aint[node].pull(aint[L], aint[R]); } }; struct MinFindUnit { int mn; int lazy = 0; void push(MinFindUnit& L, MinFindUnit& R) { if(lazy == 0) return; L.lazy += lazy; R.lazy += lazy; R.mn += lazy; L.mn += lazy; lazy = 0; return; } void pull(MinFindUnit& L, MinFindUnit& R) { mn = min(L.mn, R.mn); return; } }; struct MinFind : AINT<MinFindUnit> { int query_next(int t, int limit) { if(aint[1].mn > limit) return -1; for(int itt = 0; itt < 2; itt++) { walk([&](auto& a, int cl, int cr) { if(t < cl) return 0; if(cr < t) return 0; if(a.mn > limit) { t = cr + 1; return 0; } if(cl == cr) { return 0; } return 1; }, t, n - 1); if(t == n) t = 0; } return t; } int query_prev(int t, int limit) { if(aint[1].mn > limit) return -1; for(int itt = 0; itt < 2; itt++) { walk<1>([&](auto& a, int cl, int cr) { if(t < cl) return 0; if(cr < t) return 0; if(a.mn > limit) { t = cl - 1; return 0; } if(cl == cr) { return 0; } return 1; }, 0, t); if(t == -1) t = n - 1; } return t; } void add(int l, int r, int x) { walk([&](auto& a, int cl, int cr) { a.mn += x; a.lazy += x; return 0; }, l, r); } void set(int p, int x) { walk([&](auto& a, int cl, int cr) { if(cl != cr) return 1; a.mn = x; a.lazy = 0; return 0; }, p, p); } void set(int l, int r, int x) { walk([&](auto& a, int cl, int cr) { if(cl != cr) return 1; a.mn = x; a.lazy = 0; return 0; }, l, r); } }; namespace Queue { int next[nmax]; MinFind inside; auto rdist = [](int x, int d) { return d < x? N - x + d : d - x; }; auto ldist = [](int x, int d) { return d <= x? x - d : x + N - d; }; set<int> heads; void init() { inside.init(N); inside.set(0, N - 1, 1); //for(int i = 0; i < N; i++) //inside.walk([&](auto& a, int cl, int cr) { cerr << a.mn << ' '; return 0; }, i, i); cerr << '\n'; } void insert(int node) { //for(int i = 0; i < N; i++) //inside.walk([&](auto& a, int cl, int cr) { cerr << a.mn << ' '; return 0; }, i, i); cerr << '\n'; heads.emplace(node); inside.set(node, 0); next[node] = -1; //for(int i = 0; i < N; i++) //inside.walk([&](auto& a, int cl, int cr) { cerr << a.mn << ' '; return 0; }, i, i); cerr << '\n'; //cerr << "insert " << node << '\n'; int nx = inside.query_next((node + 1) % N, 0); int pr = inside.query_prev((node - 1 + N) % N, 0); //cerr << nx << ' ' << pr << '\n'; //inside.walk([&](auto& a, int cl, int cr) { cerr << a.mn << '\n'; return 0; }, nx, nx); //inside.walk([&](auto& a, int cl, int cr) { cerr << a.mn << '\n'; return 0; }, pr, pr); //cerr << '\n'; if(nx != node && rdist(node, nx) < K) { next[node] = nx; if(heads.count(nx)) heads.erase(nx); } if(pr != node && ldist(node, pr) < K) { heads.erase(node); next[pr] = node; } } vector<int> prune() { vector<int> rez; for(auto x : heads) rez.emplace_back(x), inside.set(x, 1); heads.clear(); for(auto x : rez) if(next[x] != -1) heads.emplace(next[x]); return rez; } } vector<int> topsort; #define left ofia #define right goa int left[nmax][18], jumpl[nmax][18]; int right[nmax][18], jumpr[nmax][18]; void init(int k__, std::vector<int> r) { auto T = r; K = k__; N = sz(r); topsort.resize(N); Queue::init(); vector<int> erased(N, 0); for(int i = 0; i < sz(r); i++) if(r[i] == 0) erased[i] = 1, Queue::insert(i); int color = 0; while(sz(Queue::heads)) { auto rem = Queue::prune(); ++color; for(auto x : rem) topsort[x] = color; for(auto x : rem) { for(int i = (x - 1 + N) % N, d = 1; d < K; d++, i = (i - 1 + N) % N) { if(erased[i]) continue; r[i]--; if(r[i] == 0) erased[i] = 1, Queue::insert(i); } } } for(int x = 0; x < sz(r); x++) { int mn = -1; jumpl[x][0] = 0; for(int i = (x - 1 + N) % N, d = 1; d < K; d++, i = (i - 1 + N) % N) { if(topsort[i] > topsort[x]) mn = (mn == -1? i : topsort[mn] < topsort[i]? mn : i); } left[x][0] = mn == -1? x : mn; jumpl[x][0] = left[x][0] <= x? x - left[x][0] : x + N - left[x][0]; mn = -1; jumpr[x][0] = 0; for(int i = (x + 1 + N) % N, d = 1; d < K; d++, i = (i + 1 + N) % N) { if(topsort[i] > topsort[x]) mn = (mn == -1? i : topsort[mn] < topsort[i]? mn : i); } right[x][0] = mn == -1? x : mn; jumpr[x][0] = (right[x][0] >= x? right[x][0] - x : N - x + right[x][0]); } for(int step = 1; step < 18; step++) for(int i = 0; i < N; i++) left[i][step] = left[left[i][step - 1]][step - 1], jumpl[i][step] = jumpl[i][step - 1] + jumpl[left[i][step - 1]][step - 1], right[i][step] = right[right[i][step - 1]][step - 1], jumpr[i][step] = jumpr[i][step - 1] + jumpr[right[i][step - 1]][step - 1]; return; } bool compare_smaller(int x, int y) { auto rdist = [&](int d) { return d < x? N - x + d : d - x; }; auto ldist = [&](int d) { return d <= x? x - d : x + N - d; }; int st = x, buffer = rdist(y); for(int i = 17; i >= 0; i--) { if(buffer < jumpr[st][i]) continue; buffer -= jumpr[st][i]; st = right[st][i]; } if(st == y) return 1; if(rdist(y) - rdist(st) < K && topsort[y] > topsort[st]) return 1; st = x; buffer = ldist(y); for(int i = 17; i >= 0; i--) { if(buffer < jumpl[st][i]) continue; buffer -= jumpl[st][i]; st = left[st][i]; } if(st == y) return 1; if(ldist(y) - ldist(st) < K && topsort[y] > topsort[st]) return 1; return 0; } int compare_plants(int x, int y) { return compare_smaller(x, y)? 1 : compare_smaller(y, x)? -1 : 0; }
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...