通常对于求数组的两个操作:
一、更新某个元素
二、求数组中某个区间的元素的和
对于操作一,在O(1)可完成,对于操作二,在O(n)内可完成,但是如果操作二的次数很多,可能就比较耗时间了,所以这里对于操作二提供另外一种方法,叫做Binary Indexed Tree,时间复杂度为O(logn).
假设一共有N个元素,a[N]
这里用一个辅助数组tree[N],数组下标从1开始
用tree[i]表示从数组a中某一处一直到a[i]共2
k个元素的总和 即tree[i]=(a[i-2
K+1]~a[i])的和, 而2
K就是i的二进制表示中从右往左数的第一个1以及之后的0的十进制值,比如(1001000)
2的(1000)
2的十进制值为8,即2
K=8=i&(~i+1)
如:在i= 1 0 1 0 1 0 0 0时
~i= 0 1 0 1 0 1 1 1
~i+1= 0 1 0 1 1 0 0 0
i&(~i+1)= 0 0 0 0 1 0 0 0 = (1000)2=8
例如 index 1 2 3 4 5 6 7 8
index bit 1 10 11 100 101 110 111 1000
a 2 3 4 5 6 7 8 9
tree 2 2+3 4 2+3+4+5 6 6+7 8 2+3+4+5+6+7+8+9
对于操作一,假设我们更新a[x],将其值加v,这样,由于这个元素的改变,我们需要更新tree[N]数组中的相应元素
代码如下:
对于操作二,如果想要求a[1]~a[x]的和,代码如下:
a[i]~a[j]的和等于sum[j]-sum[i-1]