树状数组

来源:互联网 发布:计算机算法基础pdf 编辑:程序博客网 时间:2024/05/22 15:34

半年前自己曾试图理解,半年后还是背代码。

树状数组可用来求逆序数,前缀和,频繁的修改A[i],则C[i]也频繁变,注意下标是从1开始的,而且只能求下标从1到n的和。


令这棵树的结点编号为C1,C2……Cn。令每个结点的值为这棵树的值的总和,那么容易发现:

C1 = A1

C2 = A1 + A2

C3 = A3

C4 = A1 + A2 + A3 + A4

C5 = A5

C6 = A5 + A6

C7 = A7

C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8

……

C16 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 + A9 + A10 + A11 + A12 + A13 + A14 + A15 + A16

数组c的项数有个特点:即c数组下标用二进制表示时,从有右向左第一个1所在位置代表的数 值,比如c8,1000,从右向左第一个1 的位置为3,2^3=8,所以c8有8项。同时,c8在第三层,即2^k。

 树状数组里有个lowbit函数,就是求2^k。

int lowbit(int x)  

{
return x&(-x);

基本部分

int sum(int x)     //前缀和

{

     int ans=0;

      while(x>0)

    {

     ans+=c[i];

     x-=lowbit(x);

    }

   return  ans;

}

void add(int i,int d)     //第i位置,a[i]修改d,则c也改变

{

    while(i<=n)

   {

     c[i]+=d;

     i+=lowbit(i);

   }

}

适用于区间求和问题,求逆序数

1 0