【AlgorithmUp】Binary Indexed Tree(Fenwick tree)
引入
需求
给定一个数组,有以下两个操作要实现
query:能够计算前i个数的和;查询区间和update:支持单点更新
方案1:暴力法
query:用for循环求解,时间复杂度O(N)update:直接赋值,时间复杂度O(1)
方案2:前缀和数组
query:用额外的空间存储,时间复杂度O(1)update:赋值后,需要重新计算前缀和数组,时间复杂度O(N)
折中方案
Binary Indexed Tree和Segment Tree查找和修改时间复杂度均为
O(logN)Binary Indexed Tree:更少的空间,更易实现Segment Tree:更大的使用范围
- The BIT is specifically used for Dynamic - Cumulative stuffs, whereas the Segment tree is more general and can be used in all those situations where, the divide and conquer paradigm can be applied over queried interval.
- All the jobs doable by BIT can essentially be done by segment tree but not vice-versa
- 参考2:评论区
定义及实现
原理
- 任意整数可以表示用二进制的位组合表示
Each integer can be represented as a sum of powers of two. In the same way, a cumulative frequency can be represented as a sum of sets of subfrequencies
- 假设某一个index的二进制表示形式为
01100,index为BIT数组中的下标i,那么index位置的值表示记录原数组哪些范围的值呢?- 最后一个1拆开的第一个数开始01001(9)~它自己(12)
- 因此重点是找到最后一个1的位置,利用
lowbit函数进行快速查找
- 注:除原数组外,下标表示从1开始
lowbit函数
lowbit(i):代表i这个数字,二进制表示的最后一位1的位权(最低为为1)例如(
()内数字代表二进制,反之为10进制)1
2
3
4
5十进制 二进制 只保留最低位1
lowbit(8) => (1000) => (1000) => 8
lowbit(6) => (0110) => (0010) => 2
lowbit(12)=> (1100) => (0100) => 4
lowbit(7) => (0111) => (0001) => 1lowbit实现x & (-x)x & (~x + 1)
改进前缀和
C[i]: 代表原数组中a第i位 的前lowbit(i)项 之和例如
1
2
3
4# lowbit(10) = 2,所以是从10开始(含),一共两项
lowbit(10) = 2, C[10] = a[10] + a[9]
# lowbit(12) = 4,所以是从12开始(含),一共四项
lowbit(12) = 4, C[12] = a[12] + a[11] + a[10] + a[9]

query:前缀和查询
S[i] = S[i – lowbit(i)] + C[i]例如
1
2
3S[7] = s[7 - lowbit(7)] + c[7] = S[6] + C[7] = S[4] + C[6] + C[7] = C[4] + C[6] + C[7]
S[12] = s[12 - lowbit(12)] + c[12] = S[8] + C[12] = C[8] + C[12]
update:单点更新
- 假设修改
a[j],那么显然需要更新c[j],然后需要修改包含c[j]的区间,即c[i + lowbit(i)]
一维BIT
1 |
|
二维BIT
1 |
|
参考
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 cv-programmer!






