Binary Index Tree 树状数组
树状数组
树状数组是能够完成下述操作的数据结构:
给定一个初始值全为0的数列,\(a_1,a_2,\dots,a_n\)
- 给定i,计算\(a_1+a_2+\dots+a_n\)
- 给定i和x,执行\(a_i+=x\)
即单点修改和区间和计算
原理介绍
树状数组结构
使用大节点保存了多个子节点的信息(区间和信息),如图,\(a_8\)为\(a_1 \sim a8\)的和,\(a_6\)则为\(a_5,a_6\),十分巧妙
其中每个节点的相关节点和其下标对应的二进制有关,与其二进制末尾0的个数有关。其中求\(a_1+a_2+\dots+a_n\),有以下规律:
- \(SUM(2) = a[1]+a[2]\)
- \(SUM(3) = a[2] + a[3]\)
- \(SUM(4) = a[4]\)
- \(SUM(5) = a[4]+a[5]\)
- \(SUM(6) = a[4]+a[6]\)
要获取\(SUM[n]\)则必须知道\(SUM(n-(2^{0的个数}))\),这个 \(2^{0的个数}\) 的个数通过以下函数获取:
1 | int lowbit(int x) { |
也可以用宏实现,x和-x按位相与便可以获得\(2^{num(0)}\)
所以获取\(SUM(n)\),可以由以下代码获取:
1 | int getsum(int n) { |
对于单点更新,从以下结论可以得出方法:
更新点x,则所有包含点x结果的点均要更新,而包含点x的点即为x+lowbit(x),所以代码如下:
1 | // v当然可以是负数 |