「学习笔记」树状数组
目的:用数组来模拟树形结构。
树状数组可以解决大部分基于区间上的更新以及求和问题。

图中红色部分为 $C$ 数组,代表树状数组;黑色即为原来的数组 $A$。
可以得出:
$C[1] = A[1];$
$C[2] = A[1] + A[2];$
$C[3] = A[3];$
$C[4] = A[1] + A[2] + A[3] + A[4];$
$C[5] = A[5];$
$C[6] = A[5] + A[6];$
$C[7] = A[7];$
$C[8] = A[1] + A[2] + A[3] + A[4] + A[5] + A[6] + A[7] + A[8];$
可以得出规律(其中 $k$ 为 $i$ 的二进制中从最低位到高位连续 $0$ 的长度):
$C[i] = A[i - 2 ^ k + 1] + A[i - 2 ^ k + 2] + ... + A[i];$
$Eg$:
当 $i$ 为 $4$ 时,$4$ 的二进制为 $100$,所以 $k$ 的值为 $2$。
代入。$C[4] = A[4 - 2 ^ 2 + 1] + A[4 - 2 ^ k + 2] ... A[4]$。
整理。$c[4] = A[1] + A[2] + A[3] + A[4]$。
其它数同理。
还有 $lowbit$ 的含义是取出 $x$ 的最低位 $1$,换言之,$lowbit(x) = 2 ^ k$。
代码即为 x & -x.
即可把刚刚找的规律变成:$C[i] = A[i - lowbit(i) + 1] + A[i - lowbit(i) + 2] + ... A[i];$。
代码:
// 求 A[1 到 x] 的和
int Query(int x) {
int ans = 0;
for (; x; x -= x & -x) ans += c[x];
return ans;
}
// 在 i 的位置上加上 k
void Modify(int x, int val) {
// 跳父亲
for (; x <= n; x += x & -x) c[x] += val;
}

浙公网安备 33010602011771号