树状数组

【树状数组是什么】

树状数组(Binary Indexed Tree, BIT)

支持单个元素修改 和 前缀查询。

比较一下:

子段和 修改单个元素
数组 \(O(n)\) \(O(1)\)
前缀和 \(O(1)\) \(O(n)\)
树状数组 \(O(\log n)\) \(O(\log n)\)

【树状数组的实现】

比如 \(a\) 数组有 16 个元素。

现在我们定义树状数组 \(t\)

\(t[i]\) 表示 \(\sum_{j=i-lowbit(i)+1}^{i}\)

其中 \(lowbit(x)=k\) 表示 \(2^k\mid x\) 但是 \(2^{k+1}\nmid x\) ,即二进制下最低的是 1 的位 所代表的数。

形象一点:

先把所有是 16 的倍数的下标取出,它们的值是以下标结尾的 16 个元素的和。

在把 8 的倍数取出,同样,但是 16 的倍数就不管了。

循环往复,直到取完 1 的倍数。


如上图,就是 16 个元素的例子。


经过这样的处理,查询前缀和的复杂度是 \(\log\) 级别 。

\(s[x]=s[x-lowbit(x)] + t[x]\),而 \(s[x-lowbit(x)]\) 又是一个同类型但更简单的子问题,递归求和即可。

相当于把 \(x\) 二进制拆位,因为 \(x-lowbit(x)\) 就直接消去了最后一个 1,下一次的 \(lowbit()\) 就至少乘 2,所以查询前缀和的复杂度是 \(\log n\)

单个元素修改的复杂度也是 \(\log\) 级别

假设我们要修改 \(a[num]\)

首先所有下标小于 \(num\)\(t_i\) 一定不用修改。

然后 \(t_{num}\) 一定要修改。

再之后,如果 \(t_x\) 要修改,那么 \(t_{x+lowbit(x)}\) 也要修改。

证明:

\(t_{x+lowbit(x)}\) 的管辖范围至少是 \(t_x\) 的 2 倍。

\(t_x\) 的管辖范围就是 \(lowbit(x)\)

所以 \(t_{x+lowbit(x)}\) 可以管辖 \(a[x],a[x+1],...,a[x+lowbit(x)]\),还可以管辖 \(t_x\) 的所有。

\(t_x\) 可以管到 \(a[num]\),所以 \(t_{x+lowbit(x)}\) 也要修改。

接着还有:除了上述元素,其他的元素都不用修改。

证明:

假设 \(t_x\) 要修改,按照方法下一个修改的应该是 \(t_{x+lowbit(x)}\)

我们只需要证明 \(t_{x+1},t_{x+2},...,t_{x+lowbit(x)-1}\) 都不修改即可。

而因为 \(x+lowbit(x)\) 恰使管辖范围增加,所以 \(x+1,x+2,...,x+lowbit(x)-1\) 都不能使管辖范围增加。

范围不增加,终点还远了,当然管不到 \(a_{num}\)

综上,我们只需要按照每次增加 \(lowbit(x)\) 的方式修改即可。

最后小问题:\(lowbit(x)\) 怎么算?

\(lowbit(x)=x\) & \((-x)\),按照补码算一下就证出来了。

【优缺点】

优点:

代码短、常数小。

缺点:

单点修改,可加不可减(比如求一个子段的最值,不能大减小),无法求任意子段,只能求前缀和。

【拓展】

  1. 树状数组优化 dp

一部分 dp 在转移的时候都是 \(dp[i]=max\{dp[j]|j\in[1,i)\}+k\) 的形式。

以前我们要用一重循环枚举 j,但是现在我们可以用树状数组快速求 \(dp[1]\) ~ \(dp[i - 1]\) 的最值,这刚好是一个前缀。

例子:最长上升子序列

先离散化。

\(dp[i]\) 表示以 \(i\) 号元素结尾的最长上升子序列长度。

当进行第 \(i\) 次循环,求出了 \(dp[i]\) 后,\(tr[a[i]]\)\(dp[i]\) 取 max,再赋值到 \(tr[a[i]]\)

这样我们要求 \(dp[i]\) 时,我们只需要求 \(tr[1]\) ~ $ tr[a[i] - 1]$ 的 \(max\) 再加一即可。

  1. Generic Cow Protests G

基本想法:\(dp[i]\) 表示前 \(i\) 个分成的方案数。

\(dp[i]\) = \(\sum dp[j]\)\(j\in [1,i)\),且 \(s[i]-s[j]\geq 0\)\(s[i]\) 表示 \(a[1]+a[2]+...+a[i]\)

注意:\(s[i]\geq s[j]\),考虑树状数组。

\(s[i]\) 为位置,\(dp[i]\) 为值。

posted @ 2024-02-05 14:35  FLY_lai  阅读(2)  评论(0编辑  收藏  举报