Submission #1046810

#TimeUsernameProblemLanguageResultExecution timeMemory
1046810nightfalComparing Plants (IOI20_plants)C++17
100 / 100
1254 ms268484 KiB
// #include "plants.h" #include <iostream> #include <cstdio> #include <cassert> #include <vector> #include <utility> #include <algorithm> // using namespace std; #define maxVal 1'000'000'001 static std:: vector<int> rank,lz,lzr; static std:: vector<std::pair<int,int>> t,tr; static std:: vector<std::vector<int>> g; static std:: vector<std::vector<std::vector<int>>> power; static int l,m; 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) { int ans = 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) ans = 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) ans = minI2; } return ans; } 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); if(minI1>0) 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; } bool inRangeNext(int z, int y, int next, int dir) { if(dir==0) return y<z && (z<next || next<=y) || z<y && (z<next && next<=y); // next==left if(dir==1) return z<y && (next<z || y<=next) || y<z && (y<=next && next<z); // next==right } int reachable(int x, int y, int dir) { int next, i=0, z=x; while(true) { next = power[i][z][dir]; if(next==-1) break; if(next==z || inRangeNext(z,y,next,dir)) break; i++; } for(int j=i-1; j>=0; j--) { next = power[j][z][dir]; if(next==-1) continue; if(next==z || inRangeNext(z,y,next,dir)) continue; else z = next; } next = power[0][z][dir]; if (next!=-1 && inRangeNext(z,y,next,dir) && -rank[z]>-rank[y]) return 1; return 0; } void calPower() { int x = m-1, cnt=1; while (x) {x>>=1; cnt++;} 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++) { int prev = power[i-1][j][x]; int &next = power[i][j][x]; if (prev == -1 || prev == j) {next = prev; continue;} next = power[i-1][prev][x]; if (next == -1 or next == j) continue; if(x==0 && inRangeNext(j,next,prev,0) || x==1 && inRangeNext(j,next,prev,1)) // if(x==0 && inRangeLeft(j,next,prev) || x==1 && inRangeRight(j,next,prev)) next = j; } } 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)); for(auto [val,i]: rankInv) { std::pair<int,int> temp1 ={maxVal,m+1}, temp2={maxVal,m+1}; if (i>0) temp1 = 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; temp1 ={maxVal,m+1}, temp2={maxVal,m+1}; if (i+1<m) temp1 = 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; update(tr,lzr,1,0,m-1,i,i,m); } calPower(); return; } void init(int k, std::vector<int> r) { int n = r.size(); m=n; l=k; 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; } int compare_plants(int x, int y) { int left = 0, right = 1, ans; ans = reachable(x,y,left) || reachable(x,y,right); if (ans) return ans; ans = reachable(y,x,left) || reachable(y,x,right); if (ans) return -ans; return 0; }

Compilation message (stderr)

plants.cpp: In function 'bool inRangeNext(int, int, int, int)':
plants.cpp:88:27: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
   88 |     if(dir==0) return y<z && (z<next || next<=y) || z<y && (z<next && next<=y); // next==left
      |                       ~~~~^~~~~~~~~~~~~~~~~~~~~~
plants.cpp:89:28: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
   89 |     if(dir==1)  return z<y && (next<z || y<=next) || y<z && (y<=next && next<z); // next==right
      |                        ~~~~^~~~~~~~~~~~~~~~~~~~~~
plants.cpp: In function 'void calPower()':
plants.cpp:126:25: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
  126 |                 if(x==0 && inRangeNext(j,next,prev,0) || x==1 && inRangeNext(j,next,prev,1))
      |                    ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
plants.cpp: In function 'bool inRangeNext(int, int, int, int)':
plants.cpp:90:1: warning: control reaches end of non-void function [-Wreturn-type]
   90 | }
      | ^
#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...