一维树状数组入门

个人觉得非常棒的博客: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 }

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

    例题: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 }

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

    例题: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 }

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

时间: 2024-08-03 16:31:02

一维树状数组入门的相关文章

树状数组入门

用office做了一张pdf - - 这是一维的情形,如果是二维,可以把每一行的一维树状数组看成一个节点,然后再把二维树状数组看成一维树状数组. 好文章:https://www.topcoder.com/community/data-science/data-science-tutorials/binary-indexed-trees/#prob 两道入门题:http://acm.hdu.edu.cn/showproblem.php?pid=1556 http://poj.org/problem

Binary Indexted Tree 树状数组入门

感谢http://www.cnblogs.com/xudong-bupt/p/3484080.html 树状数组(BIT)是能够完成下述操作的数据结构: 给定一初始值全为零的数列a1,a2a,a3...,an 1.给定i,计算a1+a2+...+ai 2.给定i和x,执行ai+=x BIT的结构: 数组bit[N] bit[1]=C1=A1;bit[2]=C2=C1+A2; BIT就是使用数组来维护上面所说的部分和 以1结尾的1,3,5,7长度为1 以1个0结尾的2,6长度为2 以两个0结尾的4

一维树状数组(HD1166)

#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<string.h> using namespace std; #define BITMAX 50001 //数组大小 typedef int valueType; //元素类型定义 valueType BITree[BITMAX]; //一维树状数组,初始化 /* 2^k k表示节点编号 x 二进制末尾 0 的个数 */ inline int lowbit(int

一维树状数组

Apple Tree http://poj.org/problem?id=3321 1 #include<cstdio> 2 #include<cstring> 3 #define mt(a,b) memset(a,b,sizeof(a)) 4 const int M=100010; 5 struct G{ 6 struct E{ 7 int u,v,next; 8 }e[M<<1]; 9 int le,head[M]; 10 void init(){ 11 le=0;

HDU 1166 敌兵布阵【树状数组入门题】

敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 74051    Accepted Submission(s): 31080 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务

二维树状数组入门题 poj2642Stars

题目连接:Stars 题解:把一维的的树状数组扩展到二维就行,复杂度为o(mlog^2n) #include<bits/stdc++.h> #include<set> #include<cstdio> #include<iomanip> #include<iostream> #include<string> #include<cstring> #include<algorithm> #define pb pus

树状数组入门 hdu1541 Stars

树状数组 树状数组(Binary Indexed Tree(B.I.T), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构.主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值:经过简单修改可以在log(n)的复杂度下进行范围修改,但是这时只能查询其中一个元素的值(如果加入多个辅助数组则可以实现区间修改与区间查询). 树状数组和线段树很像,但能用树状数组解决的问题,基本上都能用线段树解决,而线段树能解决的树状数组不一定能解决.相比较而言,树状数组效率要

HDU - 1556 Color the ball (一维树状数组 + 区间修改 + 单点求值)

HDU - 1556 Color the ball Time Limit: 3000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u Submit Status Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的"小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次颜色.但是N次以后lele已经忘记了第I个气

HDU 1166 敌兵布阵 (树状数组入门)

树状数组的引入: 对于查询和修改要求差不多,使用树状数组可以达到logN的复杂度 红色矩形表示的数组C就是树状数组.这里,C[i]表示A[i-2^k+1]到A[i]的和,而k则是i在二进制时末尾0的个数,或者说是i用2的幂方和表示时的最小指数. 所谓的k,也是该节点在树中的高度. 修改第i个元素,为了维护数组C的意义,需要修改C[i]以及C[i]的全部祖先,而非C[i]的祖先的节点则对于第i个元素的修改,不会发生改变.祖先共有"树的高度 - C[i]节点高度"个 要求区间[p,q]元素