Submission #364741

#TimeUsernameProblemLanguageResultExecution timeMemory
364741rqiAncient Books (IOI17_books)C++14
100 / 100
276 ms26908 KiB
#include "books.h" #include <bits/stdc++.h> using namespace std; typedef vector<int> vi; typedef long long ll; #define sz(x) (int)(x).size() #define pb push_back #define bk back() const int MOD = 1e9+7; const int mx = 1000005; vi p; int s; int cycL[mx]; //leftmost of a cycle int cycR[mx]; //rightmost of a cycle void popLRSingles(){ int L = 0; for(int i = 0; i < s; i++){ if(p[i] == i){ L = i+1; } else{ break; } } vi newp; for(int i = L; i < sz(p); i++){ newp.pb(p[i]-L); } p = newp; s = s-L; // for(int i = 0; i < sz(p); i++){ // cout << i << " " << p[i] << "\n"; // } while(true){ if(sz(p)-1 == s) break; if(p[sz(p)-1] == sz(p)-1){ //cout << sz(p)-1 << "\n"; p.pop_back(); } else{ break; } } } int curL, curR; int Lfrees, Rfrees; void getFrees(){ while(true){ bool updated = false; while(Lfrees >= 0){ cout.flush(); int node = Lfrees; if(node < curL) break; updated = true; Lfrees--; curL = min(curL, cycL[node]); curR = max(curR, cycR[node]); } while(Rfrees < sz(p)){ int node = Rfrees; if(node > curR) break; updated = true; Rfrees++; curL = min(curL, cycL[node]); curR = max(curR, cycR[node]); } if(!updated) break; } } long long minimum_walk(vi _p, int _s) { p = _p; s = _s; popLRSingles(); int n = sz(p); for(int i = 0; i < n; i++){ cycL[i] = MOD; cycR[i] = -1; } for(int i = 0; i < n; i++){ if(cycR[i] == -1){ int curnode = i; while(true){ cycL[i] = min(cycL[i], curnode); cycR[i] = max(cycR[i], curnode); curnode = p[curnode]; if(curnode == i) break; } while(true){ cycL[curnode] = cycL[i]; cycR[curnode] = cycR[i]; curnode = p[curnode]; if(curnode == i) break; } } } ll ans = 0; for(int i = 0; i < n; i++){ ans+=abs(p[i]-i); } curL = s; curR = s; Lfrees = s; Rfrees = s; getFrees(); while(curL > 0 || curR < n-1){ int prev_curL = curL; int prev_curR = curR; ll L_cost = 0; ll R_cost = 0; bool non_boost = false; for(int i = curL-1; i >= 0; i--){ if(i+1 == curL){ L_cost+=2; curL--; } curL = min(curL, cycL[i]); if(cycR[i] > prev_curR){ //found non boost non_boost = true; break; } } for(int i = curR+1; i < n; i++){ if(i-1 == curR){ R_cost+=2; curR++; } curR = max(curR, cycR[i]); if(cycL[i] < prev_curL){ non_boost = true; break; } } if(!non_boost){ ans+=L_cost+R_cost; } else{ ans+=min(L_cost, R_cost); } getFrees(); } return ans; }
#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...