Submission #1063629

#TimeUsernameProblemLanguageResultExecution timeMemory
1063629jamjanekComparing Plants (IOI20_plants)C++14
27 / 100
820 ms134996 KiB
#include "plants.h" #include<bits/stdc++.h> using namespace std; int perm[200010]; queue<int>kolejka; set<int>zera; int n, k; bool dodane[200010]; int nast(int val){ if(zera.size()==0)return -1; if(zera.upper_bound(val)==zera.end()){ return *zera.begin(); } return *zera.upper_bound(val); } void rozpatrz(int val){ if(val==-1)return; if(dodane[val])return; if(zera.lower_bound(val)==zera.begin()){ int pom = *zera.rbegin(); if(val - pom+n > k-1){ kolejka.push(val); dodane[val] = 1; } return; } else{ auto it = zera.lower_bound(val); it--; int pom =*it; if(val-pom > k-1){ kolejka.push(val); dodane[val] = 1; } } } const int base = 1<<18; int mini[2*base]; int lazy[2*base]; void push(int w){ if(!lazy[w])return; mini[w*2]+=lazy[w]; lazy[w*2]+=lazy[w]; mini[w*2+1]+=lazy[w]; lazy[w*2+1]+=lazy[w]; mini[w] = min(mini[w*2], mini[w*2+1]); lazy[w] = 0; } void dodaj(int w, int l, int p, int a, int b, int val){ if(b<l || p<a)return; if(a<=l && p<=b){ mini[w]+=val; lazy[w]+=val; return; } push(w); dodaj(w*2, l, (l+p)/2, a, b, val); dodaj(w*2+1, (l+p)/2+1, p, a, b, val); mini[w] = min(mini[w*2], mini[w*2+1]); } void odejmij(int l, int p){ l = (l+n)%n, p = (p+n)%n; if(l<=p) dodaj(1, 0, base-1, l, p, -1); else{ dodaj(1, 0, base-1, l, n-1, -1); dodaj(1, 0, base-1, 0, p, -1); } } int znajdz(int w){ if(w>=base){ if(mini[w]==0)return w-base; else return -1; } if(mini[w]>0)return -1; push(w); int pom = znajdz(w*2); if(pom==-1)pom = znajdz(w*2+1); else znajdz(w*2+1); mini[w] = min(mini[w*2], mini[w*2+1]); return pom; } pair<int, long long> prawo[200010][18], lewo[200010][18]; int skacz_prawo(int start, int odl){ for(int j = 17;j>=0;j--) if(odl>=prawo[start][j].second){ odl-=prawo[start][j].second; start = prawo[start][j].first; } return start; } int skacz_lewo(int start, int odl){ for(int j = 17;j>=0;j--) if(odl>=lewo[start][j].second){ odl-=lewo[start][j].second; start = lewo[start][j].first; } return start; } void init(int K, std::vector<int> r) { n = r.size(); int i; k = K; //odzyskaj permutacje for(i=0;i<n;i++) if(r[i]==0) zera.insert(i); for(auto j: zera){ rozpatrz(j); } for(i=0;i<base;i++){ if(i>=n || r[i]==0) dodaj(1, 0, base-1, i, i, 1000000000); else dodaj(1, 0, base-1, i, i, r[i]); } int numer = n-1; while(kolejka.size()){ auto x = kolejka.front(); // printf("%d:\n", x); kolejka.pop(); perm[x] = numer--; zera.erase(x); odejmij(x-k+1, x-1); vector<int>nowe_zera; while(mini[1]==0){ int j = znajdz(1); // printf("%d\n", j); dodaj(1, 0, base-1, j, j, 1000000000); // for(i=1;i<2*base;i++)printf("%d-%d ", mini[i], lazy[i]);printf("\n"); // printf("drzewo\n"); // exit(0); zera.insert(j); nowe_zera.push_back(j); } for(auto j: nowe_zera) rozpatrz(j); rozpatrz(nast(x)); // for(auto j: nowe_zera)printf("%d ", j); // printf("\nKONIEC %d\n", x); } // for(i=0;i<n;i++)printf("%d ", perm[i]);printf("\n"); //skok w prawo set<pair<int,int>>sasiedzi; for(i=0;i<k-1;i++) sasiedzi.insert({perm[i], i}); for(i=n-1;i>=0;i--){ if(sasiedzi.lower_bound({perm[i], i})==sasiedzi.begin()) prawo[i][0] = {i,0}; else{ auto it = sasiedzi.lower_bound({perm[i], i}); it--; prawo[i][0] = {(*it).second, (n+(*it).second-i)%n}; } sasiedzi.erase({perm[(i+k-1)%n], (i+k-1)%n}); sasiedzi.insert({perm[i], i}); } //lewo sasiedzi.clear(); for(i=0;i<k-1;i++) sasiedzi.insert({perm[n-i-1], n-i-1}); for(i=0;i<n;i++){ if(sasiedzi.lower_bound({perm[i], i})==sasiedzi.begin()) lewo[i][0] = {i,0}; else{ auto it = sasiedzi.lower_bound({perm[i], i}); it--; lewo[i][0] = {(*it).second, (n+(*it).second-i)%n}; } sasiedzi.erase({perm[(n+i-(k-1))%n], (n+i-(k-1))%n}); sasiedzi.insert({perm[i], i}); } for(int j = 1;j<18;j++) for(i=0;i<n;i++){ prawo[i][j] = {prawo[prawo[i][j-1].first][j-1].first, prawo[i][j-1].second+ prawo[prawo[i][j-1].first][j-1].second}; lewo[i][j] = {lewo[lewo[i][j-1].first][j-1].first, lewo[i][j-1].second+ lewo[lewo[i][j-1].first][j-1].second}; } /* for(i=0;i<n;i++)printf("%d ", perm[i]);printf("\n"); printf("PRAWO: ");for(i=0;i<n;i++) printf("%d-%d " ,prawo[i][0].first,prawo[i][0].second);printf("\n"); printf("LEWO: ");for(i=0;i<n;i++) printf("%d-%d " ,lewo[i][0].first,lewo[i][0].second);printf("\n"); */ return; } int compare_plants(int x, int y) { // printf("%d %d\n", x, y); int odl, z; //w prawo od x odl = (n+y-x)%n; // printf("odl: %d\n", odl); z = skacz_prawo(x, odl); // printf("%d %d %d\n", x, y, z); if((n+y-z)%n<k && perm[z]>=perm[y])return 1; //w lowe od x odl = (n+x-y)%n; z = skacz_lewo(x, odl); // printf("odl: %d\n", odl); // printf("%d %d %d\n", x, y, z); if((n+z-y)%n<k && perm[z]>=perm[y])return 1; swap(x, y); //w prawo od x odl = (n+y-x)%n; // printf("odl: %d\n", odl); // for(int i=0;i<n;i++)printf("%d ", skacz_prawo[i]); z = skacz_prawo(x, odl); // exit(0); if((n+y-z)%n<k && perm[z]>=perm[y])return -1; //w lowe od x odl = (n+x-y)%n; // printf("odl: %d\n", odl); z = skacz_lewo(x, odl); if((n+z-y)%n<k && perm[z]>=perm[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...