差分和前缀和是逆运算
差分数组可以将对a数组任意区间的加/减操作优化到O ( 1 )
一维差分
797. 差分 - AcWing题库
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int a[N], b[N];
void insert(int l, int r, int c){
b[l] += c; //表示l以后(包括l)的元素都被+c
b[r+1] -= c; //要被r+1和r+1以后的元素-c,保证这部分元素不变
}
int main(){
int n,m;
cin >> n >> m;
for(int i = 1; i <= n; i++){
cin >> a[i];
insert(i,i,a[i]);
}
while(m--){
int l,r,c;
cin >> l >> r >> c;
insert(l, r, c);
}
for(int i = 1; i <= n; i++) {
b[i] += b[i-1];
cout << b[i] << ' ';
}
return 0;
}
二维差分
差分矩阵实现前缀和子矩阵整体数值的增加和减少
798. 差分矩阵 - AcWing题库
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int a[N][N], b[N][N];
void insert(int x1, int y1, int x2, int y2, int c){ /*核心是这个插入函数,以图形的思路进行记忆!*/
b[x1][y1] += c; //这个意味着在(x1,y1)以后的元素都被 +c
b[x1][y2+1] -= c;
b[x2+1][y1] -= c;
b[x2+1][y2+1] += c; //右下角的多减了一次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];
insert(i,j,i,j,a[i][j]); //构建差分矩阵,等于在一个1*1的矩阵中插入自己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]; //取二维前缀和作为结果
cout << b[i][j] << ' ';
}
cout<<endl;
}
return 0;
}