树状数组(二叉搜索树)

数据结构好伤啊,今天碰到一个map竟然自己没有看明白,我会找时间好好写一篇map和vector的博客。

明白他的存放方式。我先给一张网上找的图片(引用自http://images.cnitblog.com/blog/402333/201303/02130035-8a70c86ecf024c049fa956184de467ab.png)。树状数组(二叉搜索树)_第1张图片

不过这张图片比较抽象,也可以观察刘汝佳的训练指南P195,不过最好理解的方法还是看百度的解释(出乎意料的简单啊)

百度:

令这棵树的结点编号为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

我们不难发现当lowbit(i)为几时我们就把a[i]储存前几位的和,这样就会产生对应的add和sum(add是对a[i]进行添加,sum是对a[i](包括a[i])进行求和)

sum:先拿a[6]来讲由于a[6]已经储存了a[5]所以我们便不需要再加a[5]了,而神奇的是恰巧loebit(6)为2,这样就可以避开a[5]了,如果想理解的更清楚请学习刘汝佳的训练指南。

add:不仅要修改本身还要修改后面带有a[i]的,同样的lowbit(i)也可以解决这个问题。

总之一句话,好神奇!

这里介绍一道入门题方便理解HDU1518,后附AC代码

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 #define N 50050
 6 int n;
 7 int a[N],c[N];
 8 int lowbit( int x ){
 9     return (x&-x);
10 }
11 void add(int i,int w){
12     while(i<=n){
13         c[i]+=w;
14         i=i+lowbit(i);
15     }
16 }
17 int sum(int i){
18     int sum=0;
19     while(i>0){
20         sum+=c[i];
21         i=i-lowbit(i);
22     }
23     return sum;
24 }
25 int main()
26 {
27     int t,w,u,v;
28     int cas=0;
29     char st[100];
30     scanf("%d",&t);
31     while(t--){
32         scanf("%d",&n);
33         for(int i=0;i<=n;i++)
34             a[i]=c[i]=0;
35         for(int i=1;i<=n;i++){
36             scanf("%d",&w);
37             add(i,w);
38         }
39         printf("Case %d:\n",++cas);
40         while(scanf("%s",st),strcmp(st,"End")!=0){
41             scanf("%d%d",&u,&v);
42             if(strcmp(st,"Query")==0){
43                 printf("%d\n",sum(v)-sum(u-1));
44             }else if(strcmp(st,"Add")==0){
45                 add(u,v);
46             }else if(strcmp(st,"Sub")==0){
47                 add(u,-v);//化减法为负值;
48             }
49 
50 
51         }
52     }
53 }
View Code

 

你可能感兴趣的:(树状数组(二叉搜索树))