一:定义
二:作用
可以在O(1)的时间内的进行很多连续的数的加减操作
三:一维差分
1.关系
我们现在有一个数组a,还有它的前缀和数组sum
那么数组a就是它的前缀和数组sum的差分数组
也就是说,一个数组的差分数组只要经过一次前缀和操作就成了原数组
2.构造
现在我们知道了一维差分数组和原数组之间的关系
那我们就可以假定d数组是a数组的差分数组
那么,问题来了,怎么构造d数组呢?
多想亿想我们就能发现
d[i] = a[i]-a[i-1]
所以d数组就可以等于
#include<bits/stdc++.h>
using namespace std;
int a[114514];
int d[114514];//a的差分数组
int n;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)d[i] = a[i]-a[i-1];
return 0;
}
3.操作
现在我们已经构建好了d数组,那我们怎么能让它进行大规模的加减操作呢?
因为a是d的前缀和数组,所以要想在最后把d还原,就要对d进行前缀和操作
那么,如果把d[i]加一个数,那么还原后一定会影响其后的所有数字
所以,我们不仅要在开始点+x(x为增加的数),还要在它的结束点的后一个点-x
这样就不会影响到之后的数了
那么代码就是
int x,y,z;//x 表示左节点,y表示右节点,z表示增加的数
cin>>x>>y>>z;
a[x] += z;
a[y+1] -= z;
四:二维差分
1.关系
同一维差分,当a是d的前缀和数组时,d是a的差分数组
2.构造和操作
因为二维的差分数组不好构造,所以,我们可以在输入时就进行操作
我们可以先假装a数组的数为0,
那么d数组就肯定全是0
然后我们在把输入a当作往d数组进行增加操作
那么,当我们输入完a数组的数字,d就自然成为了a的差分数组
那怎么操作呢?
我们可以类比二维前缀和来理解
如果x1,y1代表左上坐标,x2,y2 代表右下坐标
那么如果只把d[x1][y1]增加肯定不行
因为我们要是直接把d[x1][y1]增加的话,那么从(x1,y1)到后面的内容都会增加,
所以我们要让多余部分d[x2+1][y1]和d[x1][y2+1]减少
同时,因为d[x2+1][y1]和d[x1][y2+1]减少,所以d[x2+1][y2+1]后的内容会减两遍
那么还要把d[x2+1][y2+1]增加
所以增加的部分的代码就是
int x1,y1,x2,y2,z;//z为增加的量
cin>>x1>>y1>>x2>>y2>>z;
d[x1][y1] += z;
d[x2 + 1][y1] -= z;
d[x1][y2 + 1] -= z;
d[x2 + 1][y2 + 1] += z;
3.注意
另外,在构建时,如果输入a[i][j]
那么x1和x2都是i,y1和y2都是j
五:结语
如果本文对您有帮助的话,别忘记点赞收藏加关注支持一下吖~