Submission #1244421

#TimeUsernameProblemLanguageResultExecution timeMemory
1244421Zbyszek99Comparing Plants (IOI20_plants)C++20
100 / 100
1193 ms131804 KiB
#include "plants.h" #include <bits/stdc++.h> #define ll long long #define ld long double #define ff first #define ss second #define pii pair<int,int> #define pll pair<long long, long long> #define vi vector<int> #define vl vector<long long> #define pb push_back #define rep(i, b) for(int i = 0; i < (b); ++i) #define rep2(i,a,b) for(int i = a; i <= (b); ++i) #define rep3(i,a,b,c) for(int i = a; i <= (b); i+=c) #define count_bits(x) __builtin_popcountll((x)) #define all(x) (x).begin(),(x).end() #define siz(x) (int)(x).size() #define forall(it,x) for(auto& it:(x)) using namespace std; const int INF = 1e9+50; const ll INF_L = 1e18+40; const ll MOD = 1e9+7; const int tree_siz = 1024*512-1; struct add_min_tree { pll drzewo[tree_siz+1]; ll oper[tree_siz+1]; add_min_tree() { rep2(i,tree_siz/2+1,tree_siz) { drzewo[i] = {0,i-(tree_siz/2+1)}; } for(int i = tree_siz/2; i >= 1; i--) { drzewo[i] = min(drzewo[i*2],drzewo[i*2+1]); } rep(i,tree_siz+1) { oper[i] = 0; } } void spych(int v) { drzewo[v*2].ff += oper[v]; oper[v*2] += oper[v]; drzewo[v*2+1].ff += oper[v]; oper[v*2+1] += oper[v]; oper[v] = 0; } void add_seg(int akt, int p1, int p2, int s1, int s2, int w) { if(p2 < s1 || p1 > s2) return; if(p1 >= s1 && p2 <= s2) { drzewo[akt].ff += w; oper[akt] += w; return; } spych(akt); add_seg(akt*2,p1,(p1+p2)/2,s1,s2,w); add_seg(akt*2+1,(p1+p2)/2+1,p2,s1,s2,w); drzewo[akt] = min(drzewo[akt*2],drzewo[akt*2+1]); } pii get_min(int akt, int p1, int p2, int s1, int s2) { if(p2 < s1 || p1 > s2) return {1e9,1}; if(p1 >= s1 && p2 <= s2) return drzewo[akt]; spych(akt); return min(get_min(akt*2,p1,(p1+p2)/2,s1,s2),get_min(akt*2+1,(p1+p2)/2+1,p2,s1,s2)); } }; add_min_tree RTree; add_min_tree distTree; add_min_tree nxtTree; set<int> zero; int n,k; vi r; vi h; void add_zero(int ind) { if(siz(zero) == 0) { zero.insert(ind); distTree.add_seg(1,0,tree_siz/2,ind,ind,-1e9); return; } auto prv = zero.lower_bound(ind); if(prv == zero.begin()) prv = zero.end(); prv--; int pv = *prv; prv++; if(prv == zero.end()) prv = zero.begin(); int nx = *prv; distTree.add_seg(1,0,tree_siz/2,nx,nx,-distTree.get_min(1,0,tree_siz/2,nx,nx).ff - ((nx - ind + n) % n)); distTree.add_seg(1,0,tree_siz/2,ind,ind,-(ind - pv + n) % n); zero.insert(ind); } void del_zero(int ind) { zero.erase(zero.find(ind)); distTree.add_seg(1,0,tree_siz/2,ind,ind,2e9); int l = (ind-k+1+n) % n; int r = (ind-1+n) % n; if(l <= r || ind == 0) { if(l > r) swap(l,r); RTree.add_seg(1,0,tree_siz/2,l,r,-1); } else { RTree.add_seg(1,0,tree_siz/2,0,r,-1); RTree.add_seg(1,0,tree_siz/2,l,n-1,-1); } if(siz(zero) > 0) { auto nxt = zero.lower_bound(ind); if(nxt == zero.end()) nxt = zero.begin(); int nxt_ = *nxt; if(nxt == zero.begin()) nxt = zero.end(); nxt--; int prv_ = *nxt; if(prv_ == nxt_) distTree.add_seg(1,0,tree_siz/2,nxt_,nxt_,-1e7); else distTree.add_seg(1,0,tree_siz/2,nxt_,nxt_,-distTree.get_min(1,0,tree_siz/2,nxt_,nxt_).ff - (nxt_-prv_+n) % n); } } void updRtree() { pii min_ = RTree.get_min(1,0,tree_siz/2,0,n-1); while(min_.ff == 0) { add_zero(min_.ss); RTree.add_seg(1,0,tree_siz/2,min_.ss,min_.ss,1e9); min_ = RTree.get_min(1,0,tree_siz/2,0,n-1); } } vi gen_any() { h.resize(n); rep(i,n) RTree.add_seg(1,0,tree_siz/2,i,i,r[i]); int cur = n-1; updRtree(); while(cur >= 0) { pii z = distTree.get_min(1,0,tree_siz/2,0,n-1); h[z.ss] = cur--; del_zero(z.ss); updRtree(); } return h; } int left_jump[200001][18]; ll left_dist[200001][18]; int right_jump[200001][18]; ll right_dist[200001][18]; void init(int K, vi R) { k = K; r = R; n = siz(r); gen_any(); vector<pii> v_sort; rep(i,n) v_sort.pb({h[i],i}); sort(all(v_sort)); reverse(all(v_sort)); rep(i,n) nxtTree.add_seg(1,0,tree_siz/2,i,i,1e9); forall(it,v_sort) { int v = it.ss; nxtTree.add_seg(1,0,tree_siz/2,v,v,-1e9+n); int l = (v-k+1 + n) % n; int r = (v+k-1 + n) % n; if(l <= v) left_jump[v][0] = nxtTree.get_min(1,0,tree_siz/2,l,v).ss; else left_jump[v][0] = min(nxtTree.get_min(1,0,tree_siz/2,0,v),nxtTree.get_min(1,0,tree_siz/2,l,n-1)).ss; if(r >= v) right_jump[v][0] = nxtTree.get_min(1,0,tree_siz/2,v,r).ss; else right_jump[v][0] = min(nxtTree.get_min(1,0,tree_siz/2,v,n-1),nxtTree.get_min(1,0,tree_siz/2,0,r)).ss; nxtTree.add_seg(1,0,tree_siz/2,v,v,h[v]-n); left_dist[v][0] = (v-left_jump[v][0] + n) % n; right_dist[v][0] = (right_jump[v][0]-v + n) % n; } rep2(bit,1,17) { rep(i,n) { left_jump[i][bit] = left_jump[left_jump[i][bit-1]][bit-1]; right_jump[i][bit] = right_jump[right_jump[i][bit-1]][bit-1]; right_dist[i][bit] = right_dist[i][bit-1] + right_dist[right_jump[i][bit-1]][bit-1]; left_dist[i][bit] = left_dist[i][bit-1] + left_dist[left_jump[i][bit-1]][bit-1]; } } return; } bool can_jump(int a, int b) { int a2 = a; ll cur_dist = 0; for(int bit = 17; bit >= 0; bit--) { int v = left_jump[a][bit]; if(cur_dist + left_dist[a][bit] >= n) continue; if(b < a && v >= b && v <= a) {cur_dist += left_dist[a][bit]; a = v;} else if(b > a && (v <= a || v >= b)) {cur_dist += left_dist[a][bit]; a = v;} } if(min((a-b+n)%n,(b-a+n)%n) <= k-1 && h[a] <= h[b]) return 1; a = a2; cur_dist = 0; for(int bit = 17; bit >= 0; bit--) { int v = right_jump[a][bit]; if(cur_dist + right_dist[a][bit] >= n) continue; if(b > a && v >= a && v <= b) {cur_dist += right_dist[a][bit]; a = v;} else if(b < a && (v >= a || v <= b)) {cur_dist += right_dist[a][bit]; a = v;} } if(min((a-b+n)%n,(b-a+n)%n) <= k-1 && h[a] <= h[b]) return 1; return 0; } int compare_plants(int x, int y) { if(h[x] > h[y]) { if(can_jump(y,x)) return 1; return 0; } if(can_jump(x,y)) 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...