树状数组

来源:互联网 发布:营销活动数据分析报告 编辑:程序博客网 时间:2024/05/01 04:15

传送门 : 树状数组(这个博主写的不错点个赞

假设数组a[1..n],那么查询a[1]+…+a[n]的时间是log级别的,而且是一个在线的数据结构,支持随时修改某个元素的值,复杂度也为log级别。

树状数组

  • 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代表节点,后面代表这个节点是那些数据的和。
那么到底是哪些的和是怎么来的呢?

节点数值转换成二进制后,末尾有k个0,就有2的k次方个数据的和。
例如:
C1节点数字为1,二进制是:0001,末尾没有0,就是2的0次方,就是1,也就是只有一个数据的和。C1 = A1

如果是C2节点,数字为2,二进制: 0010,末尾一个0,就是2的1次方,就是两个数据的和。 C2 = A1+A2.

依次类推。

==通过运算得到C的数组下标==

C++的新用法还是挺方便的。。。。吼吼吼

#include<iostream>#include<string>using namespace std;//树状数组int lowbit(int x){    return x&(-x);}//节点数值转换成二进制后,末尾有k个0,就有2的k次方个数据的和。int sum_n(int C[],int n){    int sum = 0; // 第一步定义和为0    while(n > 0)    {        sum += C[n]; // 第二步 在 n > 0的情况 加上第n个节点        n -= lowbit(n); //第三步 让n跳到上一个需要加的位置    }    return sum;}//void update(int C[],int n,int pos, int newdata){//如果更新第i个数据,让其 +1    while(pos <= n)  //一共n个数据,第0号节点无数据,所以下标到n    {        C[pos] += newdata; // 更新数据        pos += lowbit(pos); // 下一个要更新的位置    }}int main(){    int arrayInt[] = {1,2,3,4,5,6,7,8,9};    int C[] = {0,1,3,3,10,5,11,7,28,9};    for(auto i:C){        cout<<i<<"\t";    }    cout<<"The sum of 0-5 is "<<sum_n(C,5)<<endl;    update(C,sizeof(C)/sizeof(int),3,2);    cout<<"After update C[3]+2\n";    for(auto i:C){        cout<<i<<"\t";    }    return 0;}/*0       1       3       3       10      5       11      7       28      9The sum of 0-5 is 15After update C[3]+20       1       3       5       12      5       11      7       30      9Process returned 0 (0x0)   execution time : 0.030 sPress any key to continue.*/
0 0
原创粉丝点击