树状数组区间修改 一维&二维差分
posted on 2023-06-01 12:19:50 | under 笔记 | source
树状数组的区间修改
差分数组 \(c[i]=a[i]-a[i-1]\),则有 \(a[i]=c[1]+c[2]+...+c[i]\)。
因此,\(a[1]+a[2]+...+a[x]\)
\(=c[1]+c[1]+c[2]+...+c[1]+c[2]+...c[x]\)
\(=x*c[1]+(x-1)*c[2]+...+c[x]\)
\(=\sum_{i=1}^{x}(x-i+1)*c[i]\)
运用数学思想,将变量和常量拆开得:
\(=\sum_{i=1}^{x}(x+1)*c[i]-\sum_{i=1}^{x}i*c[i]\)
不妨设 \(A=\sum_{i=1}^{x}c[i]\),\(B=\sum_{i=1}^{x}i*c[i]\),则:
\(=(x+1)*A-B\)
我们只需用树状数组维护 \(A\) 和 \(B\) 即可。
二维差分
通过定义理解二维差分较难,不妨画图看看。
首先我们知道,给 \(c[i][j]+k\),则等同于将左上角为 \((i,j)\)、右下角为 \((n,m)\) 的矩阵的每个数 \(+k\)。
那么,考虑给左上角为 \((x1,y1)\)、右下角为 \((x2,y2)\) 的矩阵 \(+k\),如何操作?
- \(c[x1][y1]+k\)
- \(c[x1][y2+1]-k\)
- \(c[x2+1][y1]-k\)
- \(c[x2+1][y2+1]+k\)
可画图理解。简单地说,就是先加(第一步);加了发现有的不该加就减去(二三步);由于减了两次,所以还要加回去(第四步)。
至于初始化,有一种巧妙做法:初始化数组为 \(0\),在 \(i,j\) 加入 \(k\) ,等同于将左上角为 \((i,j)\)、右下角为 \((i,j)\) 的矩阵加 \(k\),很好写。
二维区间修改
结合上述两种思想。
\(\sum_{i=1}^{x}\sum_{j=1}^{y}a[i][j]\)
\(=\sum_{i=1}^{x}\sum_{j=1}^{y}\sum_{k=1}^{i}\sum_{h=1}^{j}c[i][j]\)
建议画图看看,\(c[i][j]\) 被多少个 \(a[i][j]\) 使用?每个 \(c[i][j]\) 被用了\((x-i+1)(y-j+1)\) 次。
然后把 \(i\)、\(j\) 单独拎出来。
\(=\sum_{i=1}^{x}\sum_{j=1}^{y}((x+1)*(y+1)*c[i][j]-(y+1)*c[i][j]*i-(x+1)*c[i][j]*j+c[i][j]*i*j)\)
像一维一样,设四个树状数组维护即可。

浙公网安备 33010602011771号