差分是前缀和的逆运算
一维差分:
给定一个初始数组 a,构造一个差分数组 b ,使 a 是 b 的前缀和;
一维差分的核心操作是用来解决将 a数组的 [L,R]区间全部加上c,代码如下
#include <bits/stdc++.h>
using namespace std;
const N = 110;
int a[N]; //原始数组
int b[N]; //差分数组
int main(){
int n;
cin >> n; //数组中元素个数
for(int i=1;i<=n;i++) cin >> a[i];
/*初始化差分数组*/
for(int i=1;i<=n;i++)
b[i]=a[i]-a[i-1];
/*核心操作,对a进行m次区间加数*/
int m;
cin >> m;
for(int i=0;i<m;i++){
int L,R,c;
cin >> L >> R >> c;
b[L]+=c; /*等价于对差分数组进行此操作*/
b[R+1]-=c;
}
/*求a数组最后状态*/
for(int i=1;i<=n;i++){
a[i]=a[i-1]+b[i]; //即求b的前缀和
}
return 0;
}
//也可从a自身进行操作,即不用差分数组b,实现如下
/*将a初始化为差分数组*/
for(int i=n;i>0;i--){
a[i]=a[i]-a[i-1];
}
/*核心操作类似,在a上进行操作*/
/*求a数组最后状态*/
for(int i=1;i<=n;i++){
a[i]+=a[i-1];
}
二维差分:
与一维差分类似,给定一个初始二维数组 a[][],构造一个差分数组 b[][],使 a 是 b的前缀和
二维差分的核心操作是在以(x1,y1)为左上角,(x2,y2)为右下角的矩形区域中的点全部加上c,实现如下
#include<bits/stdc++.h>
using namespace std;
const int N=110;
int a[N][N];
int b[N][N];
void insert(int x1,int y1,int x2,int y2,int c){ //关键操作在差分数组上的等价操作
b[x1][y1]+=c;
b[x2+1][y2+1]+=c;
b[x1][y2+1]-=c;
b[x2+1][y1]-=c;
}
int main(){
int n,m; //n行m列的矩阵
cin >> n >> m;
/*初始化原始数组a*/
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
/*初始化差分数组b*/
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
insert(i,j,i,j,a[i][j]);
}
/*关键操作*/
int q;
cin >>q;
for(int i=0;i<q;i++){
int x1,y1,x2,y2,c;
cin >> x1 >> y1 >> x2 >> y2 >> c;
insert(x1,y1,x2,y2,c);
}
/*求a数组最后状态,等价于求b的前缀和*/
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];
return 0;
}
/*也可以只在a数组上操作*/