- Choose the invariant that makes a window valid or useful.
- Advance the right boundary and add the new element.
- Move the left boundary only as needed while maintaining the invariant and updating the answer.
Code notes
- 125 lines of C++ from the credited upstream file ccc17s5.cpp.
- The implementation visibly relies on sequence storage.
- 7 loop blocks detected.
Complexity
Confirm that neither pointer moves backwards; if so, the scan is usually linear apart from the window’s data-structure operations.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
12 3#include <bits/stdc++.h>4#define pii pair<int, int>5#define vpii vector<pair<int, int>>6#define vi vector<int>7#define pb push_back8#define ms(a, x) memset(a, x, sizeof(a))9#define fs first10#define sn second11const int INF = 0x3f3f3f3f;12using namespace std;13/*14 sqrt decomp15store passengers in every block16 17when operating18we only need to worry about the passengers in the right most of block19all the ones to the left wont affect sum value20*/21 22const int MAXBLOCKS = 390;23const int MAXN = 150001;24int N, M, Q;25int len;26int numBlocks;27 28int decomp[MAXBLOCKS]; 29vi lines[MAXN]; 30int whichLine[MAXN];31int posInLine[MAXN];32int arr[MAXN];33int shift[MAXN]; 34vi rightBounds[MAXN];35 36 3738void initRBound() {39 for(int bl = 0; bl < N; bl+=len) {40 int br = min(bl+len-1,N-1);41 for(int j = br; j >= bl; j--) {42 int line = whichLine[j];43 if(rightBounds[line].size() == 0) {44 rightBounds[line].push_back(j);45 continue;46 }47 if(rightBounds[line].back()/len != j/len) {48 rightBounds[line].push_back(j);49 }50 }51 }52}53 54 5556int getVal(int i) {57 int line = whichLine[i];58 int mod = lines[line].size();59 return arr[lines[line][((posInLine[i]-shift[line]%mod)+mod)%mod]];60}61 626364int query(int l, int r) {65 int ans = 0;66 for(int i = l; i <= r;) {67 if(i%len == 0 && i+len-1<=r) {68 ans+=decomp[i/len];69 i+=len;70 }else{71 ans+=getVal(i);72 i++;73 }74 }75 return ans;76}77 787980void operate(int x) {81 for(int i = 0; i < rightBounds[x].size(); i++) {82 int curBlock = rightBounds[x][i];83 int nextBlock = rightBounds[x][(i+1)%rightBounds[x].size()];84 int curVal=getVal(curBlock);85 decomp[curBlock/len]-=curVal;86 decomp[nextBlock/len]+=curVal;87 }88 89 shift[x]++;90 shift[x]%=lines[x].size();91}92 93int main() {94 ios_base::sync_with_stdio(0);95 cin.tie(0);96 cout.tie(0);97 cin >> N >> M >> Q;98 len = sqrt(N);99 numBlocks = N/len;100 for(int i = 0 ; i < N; i++) {101 int x; cin >> x;102 posInLine[i]=lines[x].size();103 lines[x].push_back(i);104 whichLine[i] = x;105 }106 for(int i = 0 ; i < N; i++) {107 int x; cin >> x;108 arr[i] = x;109 decomp[i/len]+=x;110 }111 112 initRBound();113 while(Q--) {114 int dir; cin >> dir;115 if(dir == 1) {116 int l, r; cin >> l >> r;117 l--; r--;118 cout << query(l, r) << '\n';119 }else {120 int x; cin >> x;121 operate(x);122 }123 }124 return 0;125}