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

一维树状数组入门

时间:2019-08-08 21:14:54      阅读:113      评论:0      收藏:0      [点我收藏+]

标签:数组   fine   deque   iostream   val   targe   update   data   代码   

个人觉得非常棒的博客:https://www.cnblogs.com/xenny/p/9739600.html

第一类:单点更新,区间查询

    例题:http://acm.hdu.edu.cn/showproblem.php?pid=1166

     AC代码:

技术图片
 1 /* */
 2 # include <iostream>
 3 # include <cstdio>
 4 # include <cstring>
 5 # include <string>
 6 # include <cstdlib>
 7 # include <queue>
 8 # include <stack>
 9 # include <vector>
10 # include <map>
11 # include <set>
12 # include <cmath>
13 # include <bitset>
14 # include <functional>
15 using namespace std;
16 
17 int n, m;
18 int a[50005], c[50005];///对应原数组和树状数组
19 int lowbit(int x)
20 {
21     return x&(-x);///当x为0时结果为0,当x为奇数时,结果为1;
22     ///当x为偶数时,结果为x中2的最大次方的因子
23     ///2^k=i&(-i)
24 }
25 
26 void updata(int i, int k)///在第i个位置上加上k
27 {
28     while( i<=n )///a[i]包含于c[i+2^k], c[i+2^k+2^k], c[i+2^k+2^k+2^k], ,,,
29     {
30         c[i] += k;
31         i += lowbit(i);
32     }
33 }
34 
35 int getsum(int i)
36 {
37     int res=0;
38     while( i>0 )
39     {
40         res += c[i];
41         i -= lowbit(i);
42     }
43     return res;
44 }
45 
46 int main()
47 {
48     int t;
49     cin>>t;
50     for(int tot=1; tot<=t; tot++ )
51     {
52         cout<<"Case "<<tot<<":"<<endl;
53         memset(a, 0, sizeof(a));
54         memset(c, 0, sizeof(c));
55         cin>>n;
56         for(int i=1; i<=n; i++ )
57         {
58             cin>>a[i];
59             updata(i, a[i]);
60         }
61 
62         string s;
63         int x, y;
64         while( cin>>s && s[0]!=E )
65         {
66             cin>>x>>y;
67             if( s[0]==Q)
68             {
69                 int sum=getsum(y)-getsum(x-1);
70                 cout<<sum<<endl;
71             }
72             else if( s[0]==A )
73             {
74                 updata(x, y);
75             }
76             else if( s[0]==S )
77             {
78                 updata(x, -y);
79             }
80         }
81     }
82     return 0;
83 }
View Code

第二类:区间修改,单点查询

    例题:http://acm.hdu.edu.cn/showproblem.php?pid=1556

    AC代码:

 

技术图片
 1 /* 一位数状数组:区间修改,单点查询 */
 2 # include <iostream>
 3 # include <stdio.h>
 4 # include <string.h>
 5 # include <string>
 6 # include <algorithm>
 7 # include <cmath>
 8 # include <cstdlib>
 9 # include <cctype>
10 # include <deque>
11 # include <climits>
12 # include <queue>
13 # include <stack>
14 # include <set>
15 # include <bitset>
16 # include <list>
17 # include <map>
18 using namespace std;
19 
20 # define LL long long
21 # define lowbit(x)(x&(-x))
22 # define gcd(a, b) __gcd(a, b)
23 # define INF 0x3f3f3f3f
24 # define N 100010
25 
26 int c[N];///树状数组不一定是求和
27 
28 void updata(int x, int val)
29 {
30     while( x<=N )
31     {
32         c[x] += val;
33         x += lowbit(x);
34     }
35 }
36 
37 int getsum(int x)
38 {
39     int res=0;
40     while( x>0 )
41     {
42         res += c[x];
43         x -= lowbit(x);
44     }
45     return res;
46 }
47 
48 int main()
49 {
50     int n, x, y, i;
51     while( ~ scanf("%d", &n) && n )
52     {
53         memset(c, 0, sizeof(c));
54         for(i=0; i<n; i++ )
55         {
56             scanf("%d %d", &x, &y);
57             updata(x, 1);
58             updata(y+1, -1);
59         }
60 
61         for(i=1; i<=n-1; i++ )
62             printf("%d ", getsum(i));
63         printf("%d\n", getsum(n));
64     }
65     return 0;
66 }
View Code

 

 

第三类:区间修改,区间查询

    例题:http://poj.org/problem?id=3468

 

     AC代码:

技术图片
 1 #include<cstring>
 2 #include<cstdio>
 3 #include<iostream>
 4 #include<algorithm>
 5  
 6 using namespace std;
 7  
 8 #define maxn 100004
 9  
10 int n,m;
11 long long c1[maxn],c2[maxn];
12 long long a[maxn];
13  
14 inline int lowbit(int x)
15 {
16     return x&-x;
17 }
18  
19 inline void update(int index,int x,long long val)
20 {
21     if(index==0) for(int i=x;i<=n;i+=lowbit(i)) c1[i]+=val;
22     else for(int i=x;i<=n;i+=lowbit(i)) c2[i]+=(x-1)*val;
23 }
24  
25 inline long long query(int x)
26 {
27     long long sum1=0,sum2=0;
28     for(int i=x;i>0;i-=lowbit(i)) sum1+=c1[i],sum2+=c2[i];
29     return x*sum1-sum2;
30 }
31  
32 void init()
33 {
34     a[0]=0;
35     memset(c1,0,sizeof c1);
36     memset(c2,0,sizeof c2);
37     for(int i=1;i<=n;i++)
38     {
39         long long d=a[i]-a[i-1];
40         update(0,i,d);
41         update(1,i,d);
42     }
43 }
44  
45 int main()
46 {
47     while(scanf("%d%d",&n,&m)!=EOF)
48     {
49         for(int i=1;i<=n;i++)
50         {
51             scanf("%lld",&a[i]);
52         }
53         init();
54         while(m--)
55         {
56             char op[3];
57             scanf("%s",op);
58             if(op[0]==Q)
59             {
60                 int l,r;
61                 scanf("%d%d",&l,&r);
62                 long long ans=query(r)-query(l-1);
63                 printf("%lld\n",ans);
64             }
65             else
66             {
67                 int l,r;
68                 long long x;
69                 scanf("%d%d%lld",&l,&r,&x);
70                 update(0,l,x);
71                 update(0,r+1,-x);
72                 update(1,l,x);
73                 update(1,r+1,-x);
74             }
75         }
76     }
77     return 0;
78 }
View Code

 

一维树状数组入门

标签:数组   fine   deque   iostream   val   targe   update   data   代码   

原文地址:https://www.cnblogs.com/wsy107316/p/11323605.html

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