标签:line lin 树状 分享 str turn 漂亮 display open
看到树状数组后觉得这个数据结构很优美,比较有意思,虽然很多时候线段树能做,但树状数组内存消耗更小,思想也很有意思,就想记录一下
看上去是比较漂亮的,A[] 是序列的实际数值, C[] 记录的是某一段A[]的和,例如 C[4]就是 sun(1--4)。
先介绍个很关键的函数:int lowbit(int x){return x&(-x);} 这个可以返回二进制数 x 中最低位的 1 还是 1 ,其余都为 0 的数,比如对于 1000(8的二进制) 1000=100+lowbit(100)=110+lowbit(110)=111+lowbit(111);
其实 C[i] 有很多性质:
1,将 i 化为二进制,比如 i = 6 = 110 那么 lowbit(6) = 2 ,代表 C[6] 记录了 2 个数的和, lowbit(7)=1 ,所以 C[7] 记录的 1 个数的和
2,C[i]的父节点是 C[i+lowbit(i)]
看懂了这些再看看代码,很容易理解了
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 5 using namespace std; 6 #define MAXN 1000 7 8 int n; 9 int A[MAXN]; 10 int C[MAXN]; 11 12 int lowbit(int x) 13 { 14 return x&(-x); 15 } 16 17 void new_tree(int n) // 建树 大概 n*log(n) 18 { 19 memset(C,0,sizeof(C)); 20 for (int i=1;i<=n;i++) 21 { 22 C[i]+=A[i]; 23 for (int j=i+lowbit(i);j<=n;j+=lowbit(j)) //性质2 24 C[j]+=A[i]; 25 } 26 } 27 28 void update(int x,int add) //A[x]增减 29 { 30 A[x]+=add; 31 while (x<=n) 32 { 33 C[x]+=add; 34 x+=lowbit(x); 35 } 36 } 37 38 int getsum(int x)//[1--x]的和 39 { 40 int sum=0; 41 while(x>0) 42 { 43 sum+=C[x]; 44 x -= lowbit(x); //性质1 45 } 46 return sum; 47 } 48 49 int main() 50 { 51 scanf("%d",&n); 52 for (int i=1;i<=n;i++) 53 scanf("%d",&A[i]); 54 new_tree(n); 55 56 int l,r; 57 scanf("%d %d",&l,&r); 58 printf("%d\n",getsum(r)-getsum(l-1)); //l--r 的和 59 60 return 0; 61 }
还可以升级到多维的,很厉害
标签:line lin 树状 分享 str turn 漂亮 display open
原文地址:http://www.cnblogs.com/haoabcd2010/p/6657393.html