码迷,mamicode.com
首页 > 编程语言 > 详细

树状数组

时间:2017-04-01 20:22:45      阅读:160      评论:0      收藏:0      [点我收藏+]

标签: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 }
View Code

 还可以升级到多维的,很厉害

树状数组

标签:line   lin   树状   分享   str   turn   漂亮   display   open   

原文地址:http://www.cnblogs.com/haoabcd2010/p/6657393.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!