鸣谢 这位爷。html
前缀和与差分是比较简单常常用到做为预处理的大手子出如今各大场所而且是一对搭档。数组
一维的简简单单,二维的有点复杂。spa
从一个\(2 \times 2\)的矩阵开始看,从左上角到红色部分的前缀和确定是由两个黄色部分加两个绿色部分作成的,左上角到黄色部分的前缀和很显然是一维前缀和作出来的,因此左上角到红色部分的前缀和很显然是由两个一维前缀和加起来减掉一个多加的的绿色部分,而后就能够拓展:
红色部分的前缀和显然由蓝色的加黄色的减去多加的绿色。htm
公式:
\[sum[i][j]=a[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]\]blog
而后求出前缀和以后怎么\(O(1)\)去查询呢?
如图所示,求紫色部分值,显然由黄色部分的前缀和减去两个蓝色部分的前缀和,再加上一个多减去的绿色部分。
公式:
\[sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1]\]get
而后二维差分就是他的兄弟.。由于差完分还原值的时候是经过对差分数组作前缀和进行还原,因此差分的时候也是根据前缀和的性质去差分。
要在紫色部分加上一个值,因此首先在开始处\((x1,y1)\)加上一个值,根据前缀和的性质,此次增长值影响到了从\((x1,y1)\)到右下角的矩阵,超出了要修改的范围,因此为了给两个蓝色消除影响,应该在\((x1,y2+1)\)和\((x2+1,y2)\)处加上要修改值的相反数。可是这样的话会多消一个绿色区域,因此要在\((x2+1,y2+1)\)加上要修改的值来消除多消的影响。
公式:
\[dif[x1][y1]+=a,dif[x1][y2+1]-=a,dif[x2+1][y1]-=a,dif[x2+1][y2+1]+=a\]class
又懂了。im