树状数组

来源:互联网 发布:制造业软件系统架构 编辑:程序博客网 时间:2024/05/16 13:41

树状数组(Binary Indexed Tree(BIT), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构。主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值;经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值。

下图为树状数组:




建立树状数组:   ----------------------------------------------------------------------------------------------------------------------   1

令这棵树的结点编号为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
每个结点Cn都有2^k(k为n的二进制末尾0的个数)个元素,2^k可以由下面的函数求得:

int lowbit(int n){     return x&(-X);}

x&(-x)其中-x为x的补码

接下来就是如何创建树状数组:

void createarray(int n,int *A,int *C){      int i,t;      for(i=0;i<n;i++)     {           scanf("%d",&t);           A[i]=A[i-1]+t;//没有考虑i=0的情况           C[i]=A[i]-A[i-lowbit(i)+1];     }}
为什么这样创建?

如 1 处 和下图就可以知道:


求数组A[0.....j]的总和:

int SUM(int j,int *c){     int sum=0;     while(j>0)     {           sum+=c[j];           j-=lowbot(j);     }      return sum;}
         修改数组第i个元素的值:
void changearray(int n,int i,int *c,int t){     while(i <= n)      {            c[i]+=t;            i+=lowbit(i);      }}
          对于树状数组在NYOJ的经典例题为“士兵杀敌”系列题目。







0 0
原创粉丝点击