binary indexed tree 二分索引树 树状数组

来源:互联网 发布:淘宝店铺智能版 好用吗 编辑:程序博客网 时间:2024/05/17 01:37

参考:

https://www.byvoid.com/blog/binary-index-tree

http://www.cnblogs.com/sixdaycoder/p/4348360.html

http://blog.csdn.net/liangzhaoyang1/article/details/51365192


1)求Ci

C[i] = A[i-2^k+1] + .........+A[i]

其中k表示,将i转化为2进制后,从右往左数,0的个数。

      C1 = A1
      C2 = C1 + A2 = A1 + A2
      C3 = A3
      C4 = C2 + C3 + A4 = A1 + A2 + A3 + A4
      C5 = A5
      C6 = C5 + A6 = A5 + A6
      C7 = A7
      C8 = C4 + C6 + C7 + A8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8

按照C[i] = A[i-2^k+1] + .........+A[i]计算Ci,会产生一些重复计算。如求C8时,C8 =  A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8。其中A1 + A2 + A3 + A4=C4、 A5 + A6=C6、A7=C7在前面我们已经计算过了,所以我们可以先计算C8的所有子节点,然后将子节点的值累加,这是动态规划的思想,动态规划的核心思想就是避免子问题重复计算。C8的子节点有C4、C6、C7、A8。那么怎么求子节点呢?见下面。

2)求Ci的子节点。

8的二进制形式是1000。对其右移操作,得0100,此时k=2,8-2^2=4,C4。再右移的0010,k=1,8-2^1=6,C6。继续右移0001,k=0,8-2^0 = 7, C7。再加上其本身A8,就得到C8了。再如6,110。右移011,k=0,6-2^0 = 5,C5。再加上A6即为C6。再如7,111。因为其末尾已经没有0了,不用右移,直接是A7。

1)和2)结合求Ci的代码:

vector<int> build_BIT(vector<int> &nums) {        vector<int> BIT;//树状数组(二分索引树)int size = nums.size(), temp, s;for (int i = 1; i <= size; ++i){ //构建BITtemp = nums[i-1];s = i;while (s%2!=1){    s = s>>1;temp += BIT[i - lowbit(s) - 1];}BIT.push_back(temp);}return BIT;}

3)求Ci的父节点。

C [i+2^k]即为Ci的父节点,如C4,4=0100,k=2,所以i+2^k = 4+2^2 = 8, 即C8。如C5,5=0101,k=0,所以i+2^k = 5+2^0 = 6, 即C6。

4)怎么求k( 也即怎么求2^k )?

2^k=k&(~k+1),根据补码的性质化简为k&(-k);  这里上面有篇文章里面讲的很细点击打开链接。

5)怎么求前缀和,这才是树状数组要解决的问题。

sum(i) = sum( i - lowbit(i) ) + C[i]

由于C[i]已知,所以sum(i)可以通过递归求解,递归出口为当i = 0时。如sum(8) = sum(8-8) + C8 = C8; sum(6) = sum(6-2^1) + C6 = sum(4-2^2) + C4 +C6 = C4 +C6。

<span style="font-size:18px;">int sum(int p)    {        int rs=0;        while (p)        {            rs+=C[p];            p-=lowbit(p);        }        return rs;    }</span>
6) 更新Ai以及Ci
假如Ai的现在的值为Ai’,则delta = Ai' - Ai。那么改变这个值,会影响哪些C呢?

会改变Ci的父节点、父节点的父节点,具体代码如下:

<span style="font-size:18px;">void modify(int p,int delta)    {        while (p<=N)        {            C[p]+=delta;            p+=lowbit(p);        }    }</span>


1 0
原创粉丝点击