1. Prefix Sum
1.1 Algorithm Principle
The prefix sum is defined as recording the sum of all data to the left; when intermediate data is needed, it can be obtained in O(1) time.
- One-dimensional prefix sum
The sum of all terms from 1 to i.
Since when processing the i-th position, the first i-1 positions have already been computed, thus a[i] = a[i] + a[i-1].
- When the sum of [l,r] is needed, it can be obtained by a[r]-a[l-1]
- Two-dimensional prefix sum
Find the sum of data within the rectangle whose top-left corner is (1,1) and bottom-right corner is (i,j)
When processing (i,j), the first i-1 rows and the first j-1 elements in row i have been computed, so a[i][j] = a[i][j] + a[i-1][j] + a[i][j-1] - a[i-1][j-1].
- When the sum of data inside the rectangle with top-left corner (x1,y1) and bottom-right corner (x2,y2) is needed, it is a[x2][y2]-a[x2][y1-1]-a[x1-1][y2]+a[x1-1][y1-1]
1.2 Examples
Reference code:
void solve(){ cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i],a[i]+=a[i-1]; while(m--){ cin>>l>>r; cout<<a[r]-a[l-1]<<endl; }}Reference code:
void solve(){ cin>>n>>m>>q; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j],a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1]; while(q--){ cin>>x1>>y1>>x2>>y2; cout<<a[x2][y2]-a[x2][y1-1]-a[x1-1][y2]+a[x1-1][y1-1]<<endl; }}2. Difference
2.1 Algorithm Principle
The so-called difference array records the difference between each value and the previous value; when needing to operate on a range, the operation can be completed in O(1) time.
At the same time, we can see that the prefix sum of the difference array is the original array.
- One-dimensional difference
Compute the difference from the previous term. When needing to add or subtract to numbers in the range [l,r], it can be achieved by b[l]+=c and b[r+1]-=c
- Two-dimensional difference
The construction of the two-dimensional difference array can be reasoned backwards from its prefix sum.
When all data inside the rectangle defined by (x1,y1) and (x2,y2) is increased by c, i.e., a[x1,y1]~a[x2,y2] are all increased by c. Therefore by doing b[x1,y1]+=c, b[x1,y2+1]-=c, b[x2+1,y1]-=c, b[x2+1,y2+1]+=c, we can achieve adding c only to the region.
When constructing the difference array, one can see that it is adding a rectangle of width and height 1 with a[i,j], thus realizing a two-dimensional difference array.
2.2 Examples
Reference code:
void solve(){ for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++) b[i] = a[i]-a[i-1]; while(m--){ cin>>l>>r>>c; b[l]+=c;b[r+1]-=c; }for(int i=1,t=0;i<=n;i++) t+=b[i],cout<<t<<' ';}Reference code:
void add(){ b[x1][y1] += c;b[x1][y2+1] -=c; b[x2+1][y1] -= c;b[x2+1][y2+1] +=c;}void solve(){ for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j],x1=x2=i,y1=y2=j,c=a[i][j],add(); while(q--){ cin>>x1>>y1>>x2>>y2>>c; add(); } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ a[i][j] = b[i][j] + a[i-1][j]+a[i][j-1]-a[i-1][j-1]; cout<<a[i][j]<<' '; }cout<<endl; }}3. Two Pointers
3.1 Algorithm Principle
Two-pointer problems are mainly based on the properties of the sequence, using pointer j to record the valid query range, thereby reducing the time complexity of computations.
Two-pointer problems are mainly divided into the following two categories:
- In a single sequence, two pointers maintain a segment.
- In two sequences, maintain some order
Basic template (from AcWing)
void solve(){ for(int i=0,j=0;i<n;i++){ while(j<i && check(i,j)) j++;
// Specific problem logic }}3.2 Examples
Solution idea: set a cnt array to record the occurrence count of data in the [j,i] interval; when i points to a[i] that has already appeared, move j forward until the count of a[i] in [j,i-1] becomes 0. Track the length along the way.
Reference code:
void solve(){ for(int i=1,j=1;i<=n;i++){ if(cnt[a[i]]){ while(cnt[a[i]]) cnt[a[j++]]--; } cnt[a[i]]++; ans = max(i-j+1,ans); }cout<<ans<<endl;}Solution idea: Since the sequence is sorted in ascending order, you can stop when a[i]+a[j]>x; then a[i+1]+a[j] will also be greater than x. Therefore you can use j to record the boundary that needs to be checked, reducing search time.
Reference code:
void solve(){ for(int i=0,j=m-1;i<n,j>0;i++){ while(a[i]+b[j]>x) j--; if(a[i]+b[j]==x){ cout<<i<<' '<<j<<endl; return 0; } }}Solution idea: Since the substring appears in the source string in order, we can locate each character of the substring in the source string sequentially.
Reference code:
void solve(){ for(int i=0,j=0;i<n && j<m;i++,j++){ while(a[i] != b[j] && j<m) j++; if(i==n-1 && j < m) {cout<<"Yes"<<endl;return 0;} }cout<<"No"<<endl;}If this article helped you, please share it with others!
Some information may be outdated






