Prefix sum
Function: interval query
Definition: prefix and array predix[n], original array a[n], the relationship between them is
Interval query: Find the sum of elements between a[left] to a[right]: p[right] – p[left-1]
template:
#include<iostream> using namespace std; #define int long long const int N = 1e5 + 5; int a[N]; int prefix[N]; signed main() { ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int n; cin>>n; for(int i=1;i<=n;i + + ) cin>>a[i]; for(int i=1;i<=n;i + + ) prefix[i] = prefix[i-1] + a[i]; int q; cin>>q; while(q--) { int l,r; cin>>l>>r; cout<<prefix[r] - prefix[l-1]<<'\\ '; } }
Difference
Function: Interval modification
Definition: The relationship between the difference array d[n] and the original array a[n] is:
d[i] = a[i] – a[i-1];
Interval modification: let the elements between a[left] to a[right] + x: d[left] + =x,d[right + 1]-=x
example:
//Restore to the original array and modify the suffix interval /* Enter n 1e5 in the first line The second line inputs the array a + -1e9 Enter m In the next m lines, input l, r, x, and add x to the elements in the interval l and r. Next enter q Next q queries, input l and r each time enter 5 1 1 1 1 1 2 1 3 1 2 5 -2 2 1 2 3 4 output 2 -1 */ #include<iostream> using namespace std; #define int long long const int N = 1e5 + 5; int a[N]; int predix[N]; int diff[N]; signed main() { ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int n; cin>>n; for(int i=1;i<=n;i + + ) cin>>a[i]; for(int i=1;i<=n;i + + ) diff[i] = a[i] - a[i-1]; int m; cin>>m; while(m--) { int l,r,x; cin>>l>>r>>x; diff[l] + =x; diff[r + 1]-=x; } for(int i=1;i<=n;i + + ) a[i] = a[i-1] + diff[i]; for(int i=1;i<=n;i + + ) predix[i] = predix[i-1] + a[i]; int q; cin>>q; while(q--) { int l,r; cin>>l>>r; cout<<predix[r] - predix[l-1]<<'\\ '; } }
The relationship between prefix sum, original array and difference
The difference is transformed into the original array by performing the prefix sum operation, and the original array is transformed into the prefix sum array by performing the prefix sum operation.
The prefix sum array is transformed into the original array by differential operation, and the original array is transformed into the differential array by differential operation.
The relationship between the three is similar to derivation, original function and integral
Two-dimensional prefix sum:
Formula derivation
p[3][3] = p[2][3] + p[3][2]-p[2][2] + a[3][2]
It can be inferred from this
p[i][j] = p[i-1][j] + p[i][j-1]-p[i-1][j-1] + a[i][j]
Use two-dimensional prefix and array to perform interval query
as the picture shows
Find the sum of elements between [3,3] to [5,5] ans
ans = p[5][5]-p[2][5]-p[5][2] + p[2][2]
It follows from this
The formula for interval query x1, y1 to x2, y2 is
p[x2][y2]-p[x1-1][y2]-p[x2][y1-1] + p[x1-1][y1-1]
Example questions
/* The first row n, m, q, n row m column q times query Next enter the array Each of the next q lines, x1, y1, x2, y2, represents the coordinates of the upper left corner and the lower right corner respectively. prefix[i][j] = prefix[i-1][j] + prefix[i][j-1] -prefix[i-1][j-1] + a[i][j] enter: 7 3 2 3 5 1 6 2 4 7 9 10 4 3 6 3 9 9 6 10 1 9 10 4 2 2 7 3 2 1 4 2 Output: 77 31 */ #include<iostream> using namespace std; #define int long long const int N = 1e3 + 5; int a[N][N]; int prefix[N][N]; signed main() { int n,m,q; cin>>n>>m>>q; for(int i=1;i<=n;i + + ) for(int j=1;j<=m;j + + ) cin>>a[i][j]; for(int i=1;i<=n;i + + ) for(int j=1;j<=m;j + + ) prefix[i][j] = prefix[i-1][j] + prefix[i][j-1] -prefix[i-1][j-1] + a[i][j]; while(q--) { int x1,y1,x2,y2; cin>>x1>>y1>>x2>>y2; cout<<prefix[x2][y2] - prefix[x1-1][y2] - prefix[x2][y1-1] + prefix[x1-1][y1-1]<<'\\ \ '; } }
Two-dimensional difference
Formula derivation:
for(int i=1;i<=n;i + + ) { for(int j=1;j<=m;j + + ) { diff[i][j] + = a[i][j]; diff[i + 1][j] -= a[i][j]; diff[i][j + 1] -= a[i][j]; diff[i + 1][j + 1] + = a[i][j]; } }
Interval modification
As shown below
diff[x1][y1] + =c; diff[x1][y2 + 1]-=c; diff[x2 + 1][y1]-=c; diff[x2 + 1][y2 + 1] + =c;
Example questions
/* Given a matrix with n rows and m columns There are q operations, each operation inputs x1, y1, x2, y2, c, which means the corresponding sub-matrix plus c Output the matrix after the operation is completed enter: 4 3 3 1 5 1 3 3 2 5 3 4 4 4 2 1 2 1 2 2 2 1 2 3 2 4 2 4 3 1 output 1 7 1 5 5 4 5 3 4 4 5 3 */ #includeusing namespace std; const int N = 1e3 + 5; int a[N][N]; int diff[N][N]; int main() { int n,m,q; cin>>n>>m>>q; for(int i=1;i<=n;i + + ) for(int j=1;j<=m;j + + ) cin>>a[i][j]; for(int i=1;i<=n;i + + ) { for(int j=1;j<=m;j + + ) { diff[i][j] + = a[i][j]; diff[i + 1][j] -= a[i][j]; diff[i][j + 1] -= a[i][j]; diff[i + 1][j + 1] + = a[i][j]; } } while(q--) { int x1,y1,x2,y2,c; cin>>x1>>y1>>x2>>y2>>c; diff[x1][y1] + =c; diff[x1][y2 + 1]-=c; diff[x2 + 1][y1]-=c; diff[x2 + 1][y2 + 1] + =c; } for(int i=1;i<=n;i + + ) for(int j=1;j<=m;j + + ) a[i][j] = a[i-1][j] + a[i][j-1] - a[i-1][j-1] + diff[i][j]; for(int i=1;i<=n;i + + ) { for(int j=1;j<=m;j + + ) cout< Example: Rat, rat, duck
Problem overview:
There are n animals on the farm, either rats or ducks, numbered from 1 to n, and each animal has a weight ai
You can use magic at most once to turn the rats numbered in [l,r] into ducks and ducks, and the ducks and ducks into rats.
What is the maximum total weight of a duck?
Enter T in the first line, indicating the number of samples 1~10
for each sample
Enter n 1e5 in the first line
The second line contains n integers, indicating the type of the i-th small animal. 0 is rat, 1 is duck.
The third line contains n integers, representing the weight of the i-th small animal 1e9
enter
2
3
0 0 0
1 2 3
4
0 1 0 0
2 5 6 5
output
6
16Ideas:
Use ESS to record the weight of ducks without magic.
Then use prefix[] to record the prefix sum of the weight offset
The so-called weight offset is how much the total weight of a duck will increase or decrease if magic is used on a certain animal.
For example, if a rat weighs 10kg, use magic on it and turn it into a duck. In this way, the total weight of the duck will increase by 10kg, so the weight offset of the rat is + 10
For another example, a duck weighs 9kg. Use magic on it to turn it into a rat. In this way, the total weight of the duck will be reduced by 9kg, so the weight offset of the duck is -9
In the end, you only need to find the maximum sub-segment sum of the weight offset prefix sum, that is, find a left and a right so that the value of prefix[right]-prefix[left-1] is the largest (enumerate right, one-level loop can be )
Code:
#include<iostream> using namespace std; const int N = 1e5 + 5; int a[N],b[N];//Type, weight int prefix[N];//The prefix sum of the offset void solve() { int n; cin>>n; int ess=0;//If you don’t do magic, the duck’s weight for(int i=1;i<=n;i + + ) cin>>a[i]; for(int i=1;i<=n;i + + ) { cin>>b[i]; prefix[i] = prefix[i-1] + (a[i]?-1:1)*b[i];//If it is a rat, add the weight, otherwise subtract ess + = a[i]*b[i]; } int maxa=0,mina=0;//The maximum sub-segment sum of prefix, the smallest prefix[] before i for(int i=1;i<=n;i + + ) { maxa = max(maxa,prefix[i]-mina); mina = min(mina,prefix[i]); } cout<<ess + maxa<<'\\ '; } int main() { int t; cin>>t; while(t--) solve(); }