前缀和与差分
前缀和与差分
先记一下前缀和,比较简单。
前缀和
一维前缀和
一维前缀和:能以\(O(1)\)的时间完成求一段区间上的和。
定义:s[i] = a[1] + a[2] + ... + a[i]
求解\(l-r\)上的和就是s[r]-s[l-1]
二维前缀和
就是把一维的拓展了一下,相对应的求解s[i]
的方式会稍微更复杂一点
定义:S[i][j] = 第i行j列格子左上部分所有元素的和
接下来的画个图很好理解,求一块子矩阵(x1y1
到x2y2
)的方式就是:
Sum = S[x2][y2] - S[x1 - 1][y2] - S[x2][y1 - 1] + S[x1 - 1][y1 - 1]
差分
差分是前缀和的逆运算,相对难理解一点。
原数组a[n]
就是差分数组s[n]
的前缀和数组
差分的作用:能以\(O(1)\)的时间来完成区间上的加法。
其实要求差分数组比较难,最简单的理解方式:
先想象原数组a[n]
全是0,每次向里加一个数字,就是对这一块的区间进行了一次加法。
所以差分只有一个功能,就是向一段区间同时增改一个数字。建立差分数组也用这个思想。
一维差分
自己推一下就知道,在差分数组里,向s[i]
加一个数val
,会影响向后所有的数据,所以在s[r+1]
里补回来即可。
对[l,r]
进行一次加法: s[l] += val,s[r+1] -= val
二维差分
和一维差分同样的思想,只不过更难推一点。
x1y1
到x2y2
同时加一个数的方法是:
void insert(int x1, int y1, int x2, int y2, int val)
{
s[x1][y1] += val;
s[x2 + 1][y1] -= val;
s[x1][y2 + 1] -= val;
s[x2 + 1][y2 + 1] += val;
}