Submission #373423

#TimeUsernameProblemLanguageResultExecution timeMemory
373423pit4hComparing Plants (IOI20_plants)C++14
100 / 100
1682 ms89964 KiB
#include "plants.h" #include<bits/stdc++.h> #define st first #define nd second #define mp make_pair using namespace std; using pii = pair<int, int>; const int MAXN = 2e5+1, base = (1<<18); int n, k, when[MAXN], nr; int ptr[MAXN], ptrr[MAXN]; vector<int> R; pii tree_max[2*base+1]; void upd(int x) { pii val = mp(when[x], x); x+=base; while(x) { tree_max[x] = max(tree_max[x], val); x/=2; } } pii find_max(int l, int r) { if(l>r) { return max(find_max(l, n-1), find_max(0, r)); } l+=base, r+=base; pii res = tree_max[l]; if(l!=r) res = max(res, tree_max[r]); while(l/2 != r/2) { if(l%2==0) res = max(res, tree_max[l+1]); if(r%2==1) res = max(res, tree_max[r-1]); l /= 2; r /= 2; } return res; } int tree[2*base+1], push[2*base+1]; void ADD(int id, int val) { tree[id] += val; push[id] += val; } void add(int l, int r, int val, int id=1, int rl=0, int rr=base-1) { if(l>r) { add(l, n-1, val), add(0, r, val); return; } if(l>rr || r<rl) return; if(l<=rl && r>=rr) { ADD(id, val); return; } ADD(id*2, push[id]), ADD(id*2+1, push[id]); push[id] = 0; add(l, r, val, id*2, rl, (rl+rr)/2), add(l, r, val, id*2+1, (rl+rr)/2+1, rr); tree[id] = min(tree[id*2], tree[id*2+1]); } int find_closest_zero(int l, int r, int id=1, int rl=0, int rr=base-1) { if(l>rr || r<rl || tree[id]>0) return -1; if(rl==rr) { return rl; } ADD(id*2, push[id]), ADD(id*2+1, push[id]); push[id] = 0; int rs = find_closest_zero(l, r, id*2+1, (rl+rr)/2+1, rr); if(rs!=-1) return rs; return find_closest_zero(l, r, id*2, rl, (rl+rr)/2); } int clw_dist(int x, int y) { return (x<=y)? y-x: n-(x-y); } void solve(int x) { //cerr<<"solve("<<x<<")\n"; while(true) { int prv = -1; if(x>0) { prv = find_closest_zero(0, x-1); } if(x<n-1 && prv==-1) { prv = find_closest_zero(x+1, n-1); } if(prv != -1 && clw_dist(prv, x) < k) { //cerr<<"->"; solve(prv); } else { break; } } when[x] = ++nr; ptr[x] = find_max((x+1)%n, (x+k-1)%n).second; ptrr[x] = find_max((x-(k-1)+n)%n, (x-1+n)%n).second; add((x-(k-1)+n)%n, (x-1+n)%n, -1); add(x, x, n); upd(x); } void prep_jumps(); void init(int _k, vector<int> _r) { k = _k, R = _r, n = R.size(); for(int i=0; i<2*base; ++i) { tree_max[i] = mp(-1, -1); } for(int i=0; i<n; ++i) { tree[i+base] = R[i]; } for(int i=base-1; i>=1; --i) { tree[i] = min(tree[i*2], tree[i*2+1]); } while(nr < n) { int cur = find_closest_zero(0, n-1); assert(cur != -1); solve(cur); } prep_jumps(); } const int L = 19; pii jump[L][MAXN], jumpr[L][MAXN]; void prep_jumps() { for(int i=0; i<n; ++i) { jump[0][i] = mp(ptr[i], clw_dist(i, ptr[i])); jumpr[0][i] = mp(ptrr[i], clw_dist(ptrr[i], i)); } for(int l=1; l<L; ++l) { for(int i=0; i<n; ++i) { if(jump[l-1][i].st != -1) { jump[l][i] = jump[l-1][jump[l-1][i].st]; jump[l][i].nd += jump[l-1][i].nd; jump[l][i].nd = min(n, jump[l][i].nd); } else { jump[l][i] = mp(-1, 1); } if(jumpr[l-1][i].st != -1) { jumpr[l][i] = jumpr[l-1][jumpr[l-1][i].st]; jumpr[l][i].nd += jumpr[l-1][i].nd; jumpr[l][i].nd = min(n, jumpr[l][i].nd); } else { jumpr[l][i] = mp(-1, 1); } } } } bool is_bigger(int _x, int y) { int x = _x; for(int l=L-1; l>=0; --l) { if(jump[l][x].st!=-1 && jump[l][x].nd <= clw_dist(x, y)) { x = jump[l][x].st; } } if(clw_dist(x, y)<k && when[x] >= when[y]) return true; x = _x; for(int l=L-1; l>=0; --l) { if(jumpr[l][x].st!=-1 && jumpr[l][x].nd <= clw_dist(y, x)) { x = jumpr[l][x].st; } } if(clw_dist(y, x)<k && when[x] >= when[y]) return true; return false; } int compare_plants(int x, int y) { if(is_bigger(x, y)) return -1; if(is_bigger(y, x)) return 1; return 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...