Submission #1044638

#TimeUsernameProblemLanguageResultExecution timeMemory
1044638nightfalComparing Plants (IOI20_plants)C++17
19 / 100
1138 ms268520 KiB
// #include "plants.h" #include <iostream> #include <cstdio> #include <cassert> #include <vector> #include <utility> #include <tuple> #include <algorithm> // using namespace std; #define maxVal 1'000'000'001 static std:: vector<int> inc,dec,rank,lz,lzr,reach,reach2; static std:: vector<std::pair<int,int>> t,tr; static std:: vector<std::vector<int>> g, gt, rangeLR; static std:: vector<std::vector<std::vector<int>>> power; static int l,m,q2,subtask=6,rounds; void print(std::pair<int,int> p) {std::cout << "(" << p.first << "," << p.second << ") "; }; void print(std::vector<int> &v) {for(int elem: v) std::cout << elem << " "; std::cout << std::endl;} void print(std::vector<std::vector<int>> &v) {for (auto elem: v) print(elem); std::cout << std::endl;} void print(std::vector<std::pair<int,int>> &v) {for(auto [a,b]: v) std::cout << "(" << a << "," << b << ") ";std::cout << std::endl;} void print(std::vector<std::vector<std::vector<int>>> &v) {for (auto elem: v) print(elem); std::cout << std::endl;} std::pair<int,int> update(std::vector<std::pair<int,int>> &t, std::vector<int> &lz, int node,int start,int end,int left,int right,int diff) { if (left <= start and end <= right) lz[node] += diff; if (start!=end) { lz[2*node] += lz[node]; lz[2*node+1] += lz[node];} t[node].first += lz[node]; lz[node]=0; if (right < start or end < left) return {maxVal,m+1}; if (left <= start and end <= right) return t[node]; int mid=(start+end)/2; auto ans1 = update(t,lz,2*node,start,mid,left,right,diff); auto ans2 = update(t,lz,2*node+1,mid+1,end,left,right,diff); auto ans = std::min(ans1,ans2); t[node] = std::min(t[2*node],t[2*node+1]); return ans; } std::pair<int,int> findMin(std::vector<std::pair<int,int>> &t, std::vector<int> &lz, int node, int start, int end, int left, int right) { if (start!=end) {lz[2*node] += lz[node]; lz[2*node+1] += lz[node];} t[node].first += lz[node]; lz[node]=0; if (right < start or end < left) return {maxVal,m+1}; if (left <= start and end <= right) return t[node]; int mid=(start+end)/2; auto min1 = findMin(t,lz,2*node,start,mid,left,right); auto min2 = findMin(t,lz,2*node+1,mid+1,end,left,right); auto ans = std::min(min1,min2); t[node] = std::min(t[2*node],t[2*node+1]); return ans; } void segInit(std::vector<int> &r, std::vector<std::pair<int,int>> &t, int node, int start, int end) { if (start==end) {t[node]={r[start],start}; return;} int mid=(start+end)/2; segInit(r,t, 2*node,start,mid); segInit(r,t, 2*node+1,mid+1,end); t[node] = std::min(t[2*node],t[2*node+1]); return; } int findPreMinI(std::vector<std::pair<int,int>> &t, std::vector<int> &lz, int k,int minI1) { if (minI1>0) { auto[min2,minI2] = findMin(t,lz,1,0,m-1,std::max(0,minI1-k+1),minI1-1); if (min2==0) minI1 = minI2; } if (minI1-k+1<0) { auto[min2,minI2] = findMin(t,lz,1,0,m-1,minI1-k+1+m,m-1); if (min2==0) minI1 = minI2; } return minI1; } int computeRank(std::vector<std::pair<int,int>> &t, std::vector<int> &lz, int minI1, int k, int ranking) { if (rank[minI1]!=m) return ranking; int minI2 = findPreMinI(t,lz,k,minI1); while (minI2 != minI1) { ranking = computeRank(t,lz,minI2,k,ranking); minI2 = findPreMinI(t,lz,k,minI1); } rank[minI1] = ranking--; update(t,lz,1,0,m-1,minI1,minI1,m-1); update(t,lz,1,0,m-1,std::max(0,minI1-k+1),minI1-1,-1); if (minI1-k+1<0) update(t,lz,1,0,m-1,minI1-k+1+m,m-1,-1); return ranking; } void reachable(int node, std::vector<std::vector<int>> &g, std::vector<int> &reach) { if (node==-1 or reach[node]) return; reach[node] = 1; for(int elem: g[node]) reachable(elem,g,reach); return; } bool inRangeLeft(int z, int y, int left) {return y < z && (z < left || left <= y) || z < y && (z < left && left <= y);} int compare(int x, int y) { int left, i=0, z=x; while(true) { left = power[i][z][0]; if((left==-1) || inRangeLeft(z,y,left)) break; i++; } if (true or left!=-1) { for(int j=i-1; j>=0; j--) { left = power[j][z][0]; if (left!=-1 && !inRangeLeft(z,y,left)) z = left; } left = power[0][z][0]; if (left!=-1 && inRangeLeft(z,y,left) && -rank[z]>-rank[y]) return 1; } int right; i=0; z= x; while(true) { right = power[i][z][1]; if(right==-1) break; if(z < y && (right < z || y <= right) || y < z && (y <= right && right < z)) break; i++; } if(true or right!=-1) { for(int j=i-1; j>=0; j--) { right = power[j][z][1]; if(right!=-1 && !(z < y && (right < z || y <= right) || y < z && (y <= right && right < z))) z = right; } right = power[0][z][1]; if(right!=-1 && (z < y && (right < z || y <= right) || y < z && (y <= right && right < z))) { if (-rank[z]>-rank[y]) return 1; } } return 0; } int compare_plants7(int x, int y) { // std::cout<< std::endl << "x:" << x << " y:" << y << " " << std::endl; int ans = compare(x,y); if (ans) return ans; else return -compare(y,x); } void calPower() { int x = m-1, cnt=1; while (x) {x>>=1; cnt++;} power.resize(cnt,std::vector<std::vector<int>>(m,std::vector<int>(2,-1))); for(int j=0; j<m; j++) for(int x=0; x<2; x++) power[0][j][x] = g[j][x]; for (int i=1; i<cnt; i++) for(int j=0; j<m; j++) for(int x=0; x<2; x++) { if (power[i-1][j][x] == -1) power[i][j][x] = -1; else power[i][j][x] = power[i-1][power[i-1][j][x]][x]; } // std::cout << "rank: "<<std::endl; print(rank); // std::cout << "power: "<<std::endl; print(power); // std::cout << "rangeLR: "<<std::endl; print(rangeLR); } void calReachability(int k) { tr.resize(4*m); lzr.resize(4*m); std::vector<std::pair<int,int>> rankInv; for(int i=0; i<m; i++) {rank[i] = -rank[i]; rankInv.push_back({rank[i],i}); } sort(rankInv.begin(),rankInv.end()); segInit(rank,tr,1,0,m-1); g.resize(m,std::vector<int>(2,-1)); gt.resize(m); for(auto [val,i]: rankInv) { std::pair<int,int> temp1, temp2; temp1 = temp2 = findMin(tr,lzr,1,0,m-1,std::max(0,i-k+1),i-1); if (i-k+1<0) temp2 = findMin(tr,lzr,1,0,m-1,i-k+1+m,m-1); temp1 = std::min(temp1,temp2); if (temp1.first <=0) {g[i][0] = temp1.second;gt[temp1.second].push_back(i);} temp1 = temp2 = findMin(tr,lzr,1,0,m-1,i+1,std::min(m-1,i+k-1)); if (i+k-1>m-1) temp2 = findMin(tr,lzr,1,0,m-1,0,i+k-1-m); temp1 = std::min(temp1,temp2); if (temp1.first <= 0) {g[i][1] = temp1.second;gt[temp1.second].push_back(i);} update(tr,lzr,1,0,m-1,i,i,m); } calPower(); // subtask 6 // reach.resize(m); reach2.resize(m); // reachable(0,g,reach); // reachable(0,gt,reach2); return; } void init6(int k, std::vector<int> &r) { int n = r.size(); t.resize(4*n); lz.resize(4*n); segInit(r,t,1,0,n-1); rank.resize(n,n); int ranking = n-1; while (ranking >=0) { auto [min1,minI1] = findMin(t,lz,1,0,n-1,0,n-1); ranking = computeRank(t,lz,minI1,k,ranking); } calReachability(k); return; } void transClosure(int n, int k) { for (int i=0; i<n; i++) for(int j=i-k+1+n; j<=i+k-1+n; j++) if (rank[j%n]<rank[i%n]) g[i][j%n]=1; for(int x=0; x<n; x++) for (int i=0; i<n; i++) for(int j=0; j<n; j++) g[i][j] = g[i][j] or g[i][x] and g[x][j]; return; } void init5(int k, std::vector<int> &r) { int n = r.size(); t.resize(4*n); lz.resize(4*n); g.resize(n,std::vector<int>(n)); segInit(r,t,1,0,n-1); rank.resize(n,n); int ranking = n-1; while (ranking >=0) { auto [min1,minI1] = findMin(t,lz,1,0,n-1,0,n-1); ranking = computeRank(t,lz,minI1,k,ranking); } transClosure(n, k); return; } void init4(int k, std::vector<int> &r) { int n = r.size(); t.resize(4*n); lz.resize(4*n); segInit(r,t,1,0,n-1); rank.resize(n,n); int ranking = n-1; while (ranking >=0) { auto [min1,minI1] = findMin(t,lz,1,0,n-1,0,n-1); ranking = computeRank(t,lz,minI1,k,ranking); } return; } void init3(int k, std::vector<int> &r) { int n = r.size(); t.resize(4*n); lz.resize(4*n); segInit(r,t,1,0,n-1); rank.resize(n,n); for(int i=n-1; i>=0; i--) { auto [min1,minI1] = findMin(t,lz,1,0,n-1,0,n-1); int min2=1, minI2=minI1; int min3=1, minI3=minI1; if (minI1>0) std::tie(min2,minI2) = findMin(t,lz,1,0,n-1,std::max(0,minI1-(n-k)),minI1-1); if (minI1-(n-k)<0) std::tie(min3,minI3) = findMin(t,lz,1,0,n-1,minI1-(n-k)+n,n-1); if (min3==0) minI1=minI3; else if (min2==0) minI1=minI2; rank[minI1] = i; update(t,lz,1,0,n-1,minI1,minI1,n-1); update(t,lz,1,0,n-1,std::max(0,minI1-k+1),minI1-1,-1); if (minI1-k+1<0) update(t,lz,1,0,n-1,minI1-k+1+n,n-1,-1); } return; } int findMax(int k, std::vector<int> &r) { int i=2*m-1; while (r[i%m]!=0) {i--;} int j = i-1; while (j > i-k) { if (r[j%m]==0) i = j; j--; } for(int j=i; j>i-k; j--) r[j%m]--; return i%m; } void init2(int k, std::vector<int> &r) { int n = r.size(); rank.resize(n); for(int i=n-1; i>=0; i--) rank[findMax(k,r)] = i; return; } void init1(int k, std::vector<int> &r) { int n = r.size(); inc.resize(n); dec.resize(n); for(int i=0; i<n; i++) {inc[i] = dec[i] = i;} int s,incVal,decVal; for(s=2*n-1; s>=0; s--) { if (r[s%n]==0) incVal = s; else decVal = s; inc[s%n] = incVal; dec[s%n] = decVal; } return; } void init(int k, std::vector<int> r) { int n = r.size(); m=n; l=k; // for(int elem: x) // if (elem !=0) {subtask==-1; break;} init6(k,r); return; if(k==2) init1(k, r); else if(n<=5000 and 2*k>n) init2(k, r); else if(2*k>n) init3(k,r); else if (n<=300 and q2 <= n*(n-1)/2) init5(k,r); else if (subtask==6) init6(k,r); else init4(k,r); return; } int compare_plants6(int x, int y) { if (reach[y]) return 1; else if (reach2[y]) return -1; else return 0; } int compare_plants5(int x, int y) { if (g[x][y]) return 1; else if (g[y][x]) return -1; else return 0; } int compare_plants2(int x, int y) { if (rank[x]>rank[y]) return 1; else return -1; } int compare_plants1(int x, int y) { if (y <= dec[x] or x+m <= inc[y]) return 1; else if (y <= inc[x] or x+m <= dec[y]) return -1; return 0; } int compare_plants(int x, int y) { return compare_plants7(x,y); if(l==2) return compare_plants1(x,y); else if(m<=5000 and 2*l>m) return compare_plants2(x,y); else if(2*l>m) return compare_plants2(x,y); if (m<=300 and q2 <= m*(m-1)/2) return compare_plants5(x,y); else if (subtask==6) return compare_plants6(x,y); else return compare_plants2(x,y); return 0; }

Compilation message (stderr)

plants.cpp: In function 'bool inRangeLeft(int, int, int)':
plants.cpp:94:56: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
   94 | bool inRangeLeft(int z, int y, int left) {return y < z && (z < left || left <= y) || z < y && (z < left && left <= y);}
      |                                                  ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
plants.cpp: In function 'int compare(int, int)':
plants.cpp:117:18: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
  117 |         if(z < y && (right < z || y <= right) || y < z && (y <= right && right < z)) break;
      |            ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
plants.cpp:123:37: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
  123 |             if(right!=-1 && !(z < y && (right < z || y <= right) || y < z && (y <= right && right < z)))
      |                               ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
plants.cpp:127:32: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
  127 |         if(right!=-1 && (z < y && (right < z || y <= right) || y < z && (y <= right && right < z))) {
      |                          ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
plants.cpp: In function 'void transClosure(int, int)':
plants.cpp:202:5: warning: this 'for' clause does not guard... [-Wmisleading-indentation]
  202 |     for (int i=0; i<n; i++)
      |     ^~~
plants.cpp:205:9: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'for'
  205 |         for(int x=0; x<n; x++)
      |         ^~~
plants.cpp:208:46: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
  208 |                 g[i][j] = g[i][j] or g[i][x] and g[x][j];
plants.cpp: At global scope:
plants.cpp:18:29: warning: 'rounds' defined but not used [-Wunused-variable]
   18 | static int l,m,q2,subtask=6,rounds;
      |                             ^~~~~~
plants.cpp: In function 'void init1(int, std::vector<int>&)':
plants.cpp:285:37: warning: 'decVal' may be used uninitialized in this function [-Wmaybe-uninitialized]
  285 |         inc[s%n] = incVal; dec[s%n] = decVal;
plants.cpp:285:18: warning: 'incVal' may be used uninitialized in this function [-Wmaybe-uninitialized]
  285 |         inc[s%n] = incVal; dec[s%n] = decVal;
#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...