前缀和差分
有一列数字,多次询问一个区间的和
做法其实很简单,预处理一个数组sum[i]=a[i]+a[i-1]+a[i-2]+…+a[1]
所以想求一个区间只需要用b[r]-b[l]+1即可
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum[i]=a[i]+sum[i-1];
}
二维前缀
对于二维数组a(1,1)…a(n,m)考虑把他画到一个平面上,某一个位置的前缀和就是他左下方的所有数的和
如果想求一个二维前缀的话,可以先求一个一维前缀和,再对另一个维度进行求即可
差分
有一列数,我们多次进行区间加的操作,最后询问每一个位置
可以使用前缀和的逆变换,令sum[i]=a[i]-a[i-1],其中sum数组叫做差分数组
所以有了差分数组,我们就能解决这个问题了,所以对于a区间求和,只需要将两个边界点进行一个修改,b[L]+=v,b[R+1]-=v就好,至于为什么这么操作,因为数组是两个数的差,边界点的两个数会多加或者少加,所以做一些修改即可,最后还得来一下前缀和
for(int i=1;i<=n;i++)
a[i]=b[i]+a[i-1];//进行更新
二维差分
同样,就是差分搬到了二维平面上
其实画一个图就能很好的理解,需要一维一维的求解
二维前缀和,b[x,y]=b[x-1,y]+b[x,y-1]+b[x-1,y-1]+a[x,y]
矩阵求和,S(x1,y1,x2,y2)=b[x2,y2]-b[x1-1,y2]-b[x2,y1-1]+b[x1-1,y1-
二维差分,b[x,y]=a[x,y]+a[x-1,y-1]-a[x-1,y]-a[x,y-1]
修改矩形,[x1,y1,x2,y2]等价于b[x1,y1]+=v,b[x2+1,y2+1]+=v,b[x1,y2+1]-=v,b[x2+1,y1]-=v
打了半个小时,晚上画图证明…
总结
差分以及前缀和,有很多东西统计起来比较复杂,得不到很好的时间复杂度(注:时间107是1s限制),所以我们可以通过差分来解决问题,降低时间复杂度,这种算法是分厂神奇的,通过一个小节点的改动加上差分数组就可以进行一个更新