树状数组区间修改 一维&二维差分

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\),如何操作?

  1. \(c[x1][y1]+k\)
  2. \(c[x1][y2+1]-k\)
  3. \(c[x2+1][y1]-k\)
  4. \(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)\)

像一维一样,设四个树状数组维护即可。

posted @ 2026-01-15 08:12  Zwi  阅读(3)  评论(0)    收藏  举报