前缀和
一维前缀和
我们先看一维前缀和
我们在预处理时通常写下这样的公式,这个公式是很好理解的,(0,i)的前缀和就会等于
(0,i-1)的前缀和+本位的值a[i]
// 1
sum[i]=sum[i-1]+a[i];
那如果我们要求某个区间的和呢?比方说区间【l,r】,这也是很好理解的我们这段区间的部分和,就会等区间的最远端的和减去不属于区间的这部分和
// 0 1
s=sum[r]-sum[l-1]
二维前缀和
二维前缀和,我们通过画图,也不难理解其含义
预处理时
// 01 10 11
sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+a[i][j]
求部分和时比方说x方向上的范围是【lx,rx】
y方向上的范围是【ly,ry】那么我们的部分和公式应该是怎么写的呢?
// 00 01 10 11
s=sum[rx][ry]-sum[rx][ly-1]-sum[lx-1][ry]+sum[lx-1][ly-1]
三维前缀和
以上前缀和我们都可以很好的通过画图来理解和记忆,但是三维的就是立方体,我们每次需要通过画立方体来理解和记忆,实在是过于困难,有没有什么巧记的方法呢?
有的,读者可能发现我在写上面前缀和公式的时候都标记上了二进制数,实际上,我们可以利用二进制数来记忆前缀和的公式,这样不仅记忆轻松,在处理高维的前缀和时我们也不会漏
预处理时i-1,j-1,k-1均代表1而i,j,k都代表0
当其二进制数中有奇数个1时该项为正,偶数个1时该项为负
这样我们可以很轻松写出预处理阶段的公式(不要忘记了本项a【i】【j】【k】)
我们通过二进制的顺序来写,这样就不会错漏
本项 001 010 011 100 101
S[i][j][k]=A[i][j][k]+S[i][j][k-1]+S[i][j-1][k]-S[i][j-1][k-1]+S[i-1][j][k]-S[i-1][j][k-1]
110 111
-S[i-1][j-1][k]+S[i-1][j-1][k-1];//前缀和预处理
那求部分和阶段呢?
我们用rx,ry,rz代表0,lx-1,ly-1,lz-1代表1
其与预处理则是相反的,有奇数个1时该项为负,偶数个1时该项为正
000 001 010 011 100
S=S[rx][ry][rz]-S[rx][ry][lz-1]-S[rx][ly-1][rz]+S[rx][ly-1][lz-1]-S[lx-1][ry][rz]
101 110 111
+S[lx-1][ry][lz-1]+S[lx-1][ly-1][rz]-S[lx-1][ly-1][lz-1];//求部分和
如此记忆公式,我们在使用时就可以轻松回忆