If there is no problem with one-dimensional and two-dimensional, you can jump directly
1D difference
First given an original array a: a[1], a[2], a[3], a[n];
then we construct an array b: b[1] ,b[2] , b[3], b[i];
make a[i] = b[1] + b[2] + b[3] +, + b[i]
The a array is the prefix and array of the b array, and in turn we call the b array the differential array of the a array.
Consider
the most direct way to construct a differential b array
as follows:
a[0]= 0;
b[1] = a[1] - a[0];
b[2] = a[2] - a[1];
b[ 3] = a [3] - a[2];
…
b[n] = a[n] - a[n-1];
There is an array of b, and through the prefix and operation , it can be done in O(n) time get an array.
One-dimensional difference - template question AcWing 797. Difference
Add c to each number in the interval [l, r]: b[l] += c, b[r + 1] -= c
example question
AcWing797. Difference
input one A sequence of integers of length n. Next, enter m operations, each operation contains three integers l, r, c, which means adding c to each number between [l, r] in the sequence.
Please output the sequence after all operations are performed.
Input format
The first line contains two integers n and m.
The second line contains n integers, representing a sequence of integers.
Next m lines, each line contains three integers l, r, c, representing an operation.
Output format
A total of one line, containing n integers, representing the final sequence.
Data range
1≤n, m≤100000,
1≤l≤r≤n,
−1000≤c≤1000,
−1000≤value of elements in integer sequence≤1000
Input example:
6 3
1 2 2 1 2 1
1 3 1
3 5 1
1 6 1
Output example:
3 4 5 3 4 2
#include<bits/stdc+.和>
using namespace std;
const int N=1e5+10;
int a[N],b[N];
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i]=a[i]-a[i-1]; //构建差分数组
}
int l,r,c;
while(m--)
{
scanf("%d%d%d",&l,&r,&c);
b[l]+=c; //将序列中[l, r]之间的每个数都加上c
b[r+1]-=c;
}
for(int i=1;i<=n;i++)
{
a[i]=b[i]+a[i-1]; //前缀和运算
printf("%d ",a[i]);
}
return 0;
}
2D difference
Author: z Lin Shen Shi Jianlu
If it is extended to two dimensions, we need to add c to the value of each element in the selected sub-matrix of the two-dimensional array, whether it can also achieve O(1) time complexity. The answer is yes, consider two-dimensional difference.
The a[][] array is the prefix and array of the b[][] array, then b[][] is the difference array of a[][] The original array: a[i][j] Let's construct the difference array
:
b [i][j]
makes a[i][j] in the a array is the sum of the rectangular elements enclosed by the upper left corner (1,1) to the lower right corner (i,j) of the b array.
How to construct the b array?
Let's think backwards.
The purpose of constructing a two-dimensional difference array is to make the operation of adding c to each element in the selected neutron matrix in the original two-dimensional array a, which can be optimized from the time complexity of O(n*n) to O (1)
It is known that the selected sub-matrix in the original array a is a rectangular area surrounded by (x1, y1) as the upper left corner and (x2, y2) as the lower right corner;
Always remember that array a is the prefix and array of array b. For example, the modification of b[i][j] of array b will affect every number in array a from a[i][j] and beyond. .
Assuming that we have already constructed the b array, analogous to the one-dimensional difference, we perform the following operations
to add the value of each element in the selected sub-matrix to the time complexity o(1)
b[x1][y1] + = c;
b[x1,][y2+1] - = c;
b[x2+1][y1] - = c;
b[x2+1][y2+1] + = c;
Each time the above operation is performed on the b array, it is equivalent to: time complexity o(n2)
for(int i=x1;i<=x2;i++)
for(int j=y1;j<=y2;j++)
a[i][j]+=c;
Let's draw a picture to understand this process:
b[x1][ y1 ] +=c ; Corresponding to Figure 1, add c to the elements of the blue rectangle area in the entire array a.
b[x1,][y2+1]-=c ; Corresponding to Figure 2, subtract c from the elements of the green rectangle area in the entire array a, so that the elements in it will not change.
b[x2+1][y1]- =c ; Corresponding to Figure 3, subtract c from the elements of the purple rectangle area in the entire array a, so that the elements in it will not change.
b[x2+1][y2+1]+=c; Corresponding to Figure 4, add c to the elements of the red rectangle area in the entire array a, the red ones are equivalent to being subtracted twice, plus c once , to restore it.
We encapsulate the above operations into an insert function:
void insert(int x1,int y1,int x2,int y2,int c)
{
//对b数组执行插入操作,等价于对a数组中的(x1,y1)到(x2,y2)之间的元素都加上了c
b[x1][y1]+=c;
b[x2+1][y1]-=c;
b[x1][y2+1]-=c;
b[x2+1][y2+1]+=c;
}
We can first assume that the a array is empty, then the b array is also empty at first, but in fact the a array is not empty, so we let (i, j) be the upper left corner to (i, j) every time The elements in the area of the upper right corner (actually, the area of a small square) are inserted into c=a[i][j], which is equivalent to adding in the range from (i,j) to (i,j) in the original array a a[i][j] , so n*m insertion operations are performed, and the differential b array is successfully constructed.
This is called curve saving the country.
code show as below:
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
insert(i,j,i,j,a[i][j]); //构建差分数组
}
}
Two-dimensional difference - template question AcWing 798. Difference matrix
Add c to all elements in the sub-matrix with (x1, y1) as the upper left corner and (x2, y2) as the lower right corner:
S[x1, y1] += c, S[x2 + 1, y1] -= c, S[x1, y2 + 1] -= c, S[x2 + 1, y2 + 1] += c
Example question
AcWing 798. Difference matrix
Input an integer matrix with n rows and m columns, and then input q operations, each operation contains five integers x1, y1, x2, y2, c, where (x1, y1) and (x2, y2 ) represent the upper-left and lower-right coordinates of a submatrix.
Each operation adds c to the value of each element in the selected submatrix.
Please output the matrix after all operations.
Input Format
The first line contains integers n,m,q.
The next n lines, each containing m integers, represent a matrix of integers.
The next q lines, each line contains 5 integers x1, y1, x2, y2, c, representing an operation.
The output format
has n lines in total, and each line contains m integers, indicating the final matrix after all operations are completed.
Data range
1≤n, m≤1000,
1≤q≤100000,
1≤x1≤x2≤n,
1≤y1≤y2≤m,
−1000≤c≤1000, −1000≤value
of elements in the matrix≤1000 input
Example:
3 4 3
1 2 2 1 3 2
2 1
1 1 1
1
1 1 2 2 1 1 3 2 3 2 3
1 3 4 1
Output example:
2 3 4 1
4 3 4 1
2 2 2 2
#include<iostream>
#include<cstdio>
using namespace std;
const int N = 1e3 + 10;
int a[N][N], b[N][N];
void insert(int x1, int y1, int x2, int y2, int c)
{
b[x1][y1] += c;
b[x2 + 1][y1] -= c;
b[x1][y2 + 1] -= c;
b[x2 + 1][y2 + 1] += c;
}
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++)
{
insert(i, j, i, j, a[i][j]); //构建差分数组
}
}
while (q--)
{
int x1, y1, x2, y2, c;
cin >> x1 >> y1 >> x2 >> y2 >> c;
insert(x1, y1, x2, y2, c);
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1]; //二维前缀和
}
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
printf("%d ", b[i][j]);
}
printf("\n");
}
return 0;
}
3D difference
Observe one-dimensional
b[l] = s[l] - s[l-1]
+s[l] , -s[l-1]
two-dimensional
b[i][j] = s[i][j] - s[i-1][j] - s[i][j-1] + s[i-1][j-1]
-s[i-1][j] , -s[i][j-1] , +s[i][j] , +s[i-1][j-1] have an odd number of minus one is
negative , an even number minus one is positive
0 0 { s[ i - 0 ][ j - 0 ] = s[ i ][ j ] } +1
0 1 { s[ i - 0 ][ j - 1 ] = s[ i ] [ j - 1] } -1
1 0 { s[ i - 1 ][ j - 0 ] = s[ i - 1 ][ j ] } -1 1 1
{ s[ i - 1][ j - 1 ]} -1
If you add c to the original sequence between (x1, y1) and (x2, y2):
b[x1][y1] += c; //00
b[x1][y2+1] -= c; //01
b[x2+1][y1] -= c; //10
b[x2+1][y2+1] += c; //11
In the same way,
three-dimensional
b[i][j][k] = s[i][j][k] - s[i-1][j][k] - s[i][j-1][k] + s[i-1][j-1][k]- s[i][j][k-1] + s[i-1][j][k-1] + s[i][j-1][k-1] - s[i-1][j-1][k-1];
Add c to the original sequence between (x1, y1, z1) and (x2, y2, z2):
b[x1 ][y1 ][z1 ] += c; // 000
b[x1 ][y1 ][z2 + 1] -= c; // 001
b[x1 ][y2 + 1][z1 ] -= c; // 010
b[x1 ][y2 + 1][z2 + 1] += c; // 011
b[x2 + 1][y1 ][z1 ] -= c; // 100
b[x2 + 1][y1 ][z2 + 1] += c; // 101
b[x2 + 1][y2 + 1][z1 ] += c; // 110
b[x2 + 1][y2 + 1][z2 + 1] -= c; // 111
Example question
AcWing 1232. Three-body attack
Three-body people will attack the earth.
In order to resist the attack, the earthlings sent out A×B×C warships, which lined up a cube with layer A, row B, and column C in space.
Among them, the life value of the battleship (denoted as battleship (i,j,k)) in row j, column k of layer i is d(i,j,k).
Trisolarans will launch m rounds of "cube attacks" on the earth, and each attack will cause the same damage to all warships in a small cube.
Specifically, the t-th round of attack is described by 7 parameters lat, rat, lbt, rbt, lct, rct, ht
; ]'s battleship (i,j,k) will be damaged by ht.
If the cumulative total damage received by a battleship exceeds its defense power, the battleship will explode.
The Earth Commander wants you to tell him which round the first battleship exploded after.
Input format
The first line includes 4 positive integers A, B, C, m;
The second line contains A×B×C integers, where the ((i−1)×B+(j−1))×C+(k−1)+1 number is d(i, j, k)
; 3 to line m+2, line (t − 2) contains 7 positive integers lat, rat, lbt, rbt, lct, rct, ht.
Output Format
Output which round of attack the first exploded warship exploded after.
It is guaranteed that such a battleship must exist.
Data range
1≤A×B×C≤106,
1≤m≤106,
0≤d(i, j, k), ht≤109,
1≤lat≤rat≤A,
1≤lbt≤rbt≤B,
1 ≤lct≤rct≤C
Layers, rows, and columns all start from 1.
Input example:
2 2 2 3
1 1 1 1 1 1 1
1 1
2 1 2 1 1 1 1 1 1 2 1 2 1 1
1 1 1 1 1 2
Output example:
2
examples explain
the attack in the second round After that, the battleship (1,1,1) suffered a total of 2 points of damage, which exceeded its defense and caused an explosion.
Note that A×B×C<=1e6, opening a three-dimensional array may time out, and converting the corresponding three-dimensional coordinates into one-dimensional coordinates (i×B+j)×k is too many queries, and the binary solution is to find the first bombed one
. battleship
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int const N=2e6+10;//多出一个面 (i,j,k,+1);
int a,b,c,m;
ll s[N];//原数组;
ll bb[N],dp[N]; //差分数组;
int op[N/2][7];
int d[8][4]=
{
{
0,0,0,1},{
0,0,1,-1},{
0,1,0,-1},{
0,1,1,1},
{
1,0,0,-1},{
1,0,1,1},{
1,1,0,1},{
1,1,1,-1},
};
int get(int i,int j,int k) //以一维数组的形式
{
return (i*b+j)*c+k;
}
bool check(int mid)//判断是否是第一个被炸毁的;
{
memcpy(bb,dp,sizeof bb);//拷贝;
for(int i=1; i<=mid; i++)
{
//将位于(x1, y1, z1)和(x2, y2, z2)之间的原序列都减去h:
int x1 = op[i][0], x2 = op[i][1];
int y1 = op[i][2], y2 = op[i][3];
int z1 = op[i][4], z2 = op[i][5], h = op[i][6];
bb[get(x1, y1, z1)] -= h;
bb[get(x1, y1, z2 + 1)] += h;
bb[get(x1, y2 + 1, z1)] += h;
bb[get(x1, y2 + 1, z2 + 1)] -= h;
bb[get(x2 + 1, y1, z1)] += h;
bb[get(x2 + 1, y1, z2 + 1)] -= h;
bb[get(x2 + 1, y2 + 1, z1)] -= h;
bb[get(x2 + 1, y2 + 1, z2 + 1)] += h;
}
memset(s,0,sizeof s); //前缀和求更改后原数组;
for(int i=1; i<=a; i++)
for(int j=1; j<=b; j++)
for(int k=1; k<=c; k++)
{
s[get(i,j,k)]=bb[get(i,j,k)];
for(int u=1; u<8; u++)
{
int x=i-d[u][0],y=j-d[u][1];
int z=k-d[u][2],t=d[u][3];
s[get(i,j,k)]-=s[get(x,y,z)]*t;
}
if(s[get(i,j,k)]<0)
return true;
}
return false;
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>a>>b>>c>>m;
for(int i=1; i<=a; i++)
for(int j=1; j<=b; j++)
for(int k=1; k<=c; k++)
cin>>s[get(i,j,k)];
//差分
for(int i=1; i<=a; i++)
for(int j=1; j<=b; j++)
for(int k=1; k<=c; k++)
for(int u=0; u<8; u++) //一共8种情况;000 001 010...
{
int x=i-d[u][0],y=j-d[u][1],z=k-d[u][2],t=d[u][3];
dp[get(i,j,k)]+=s[get(x,y,z)]*t;
}
//输入m个操作;
for(int i=1; i<=m; i++)
for(int j=0; j<7; j++)
cin>>op[i][j];
//二分查找
int l=1,r=m;
while(l<r)
{
int mid=l+r >> 1;
if(check(mid)) //如果第mid操作有炸毁,往前找
r=mid;
else
l=mid+1;
}
cout<<r<<endl;
return 0;
}