树状数组选讲

来源:互联网 发布:mac录屏如何录制声音 编辑:程序博客网 时间:2024/06/08 08:05

树状数组选讲

      树状数组(Binary Indexed Tree(BIT), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值;经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值。
      树状数组,载体还是数组,但是它又有几分线段树的味道,数组本身就记录了某一段的值:

     我们看这张图:
         c[1]=a[1];
         c[2]=a[1]+a[2];
         c[3]=a[3];
         c[4]=a[1]+a[2]+a[3]+a[4];
         c[5]=a[5];
         c[6]=a[5]+a[6];
         c[7]=a[7];
         c[8]=a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8];
     所谓的求区间和比较快的算法,本质其实就是在第一次操作是已经算好了,最后只要调出来就好了;
     我们再来看看树状数组每一位包含数字的个数,不难发现c[n]所含数字个数等于2^k(k是n换做二进制后末尾0的个数);
     有个算法可以简单搞定2^k;
     
int lowbit(int x){return x&(-x);}
    至于原因吗。。。。。。。。我也不会;
   单点更新操作
    
void update(int x,int num){    while(x<=N)    {         d[x]+=num;         x+=lowbit(x);    }}
    和线段树一样单点更新之后必须要向上更新直到根节点(这里是最后一位N);
    比如你修改了a[2]的值,那么向上2,4,8都需要更新;
   区间更新操作
      这里和线段树也相似但是是需要两次修改后的单点操作
void update(int x,int num){    while(x>0)    {         d[x]+=num;         x-=lowbit(x);    }}

将左右区间分别带入就可以了;
例如将x1到x2的数值+1,就update(x1,1),update(x2,-1);
    求和操作
int getSum(int x){    int sum=0;    while(x>0)    {         sum+=c[x];         x-=lowbit(x);    }    return sum;}

    求前a[x]的总和,那一定有x个数,每次减去lowbit就是将x二进制中的1去掉一个;
综上树状数组讲完!

0 0
原创粉丝点击