首页 > 代码库 > kuangbin专题七、线段树

kuangbin专题七、线段树

技术分享

题意:线段树,单点更新,区间查询

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 using namespace std;
 6 
 7 const int maxn=5e4+5;
 8 int sum[maxn*4];  //sum求和,开四倍空间
 9 int num[maxn];  //存原数组下标[1,n]
10 
11 //up更新节点信息,这里是求和
12 void up(int rt)
13 {
14     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
15 }
16 //build建立线段树
17 void build(int rt,int l,int r)
18 {
19     if(l==r)//若到达叶节点
20     {
21         sum[rt]=num[l]; //存储A数组的值
22         return;
23     }
24     int m=(l+r)>>1;
25     build(rt<<1,l,m);//左右递归
26     build(rt<<1|1,m+1,r);
27     up(rt);  //更新信息
28 }
29 void update(int p,int add,int rt,int l,int r)
30 {
31     if(l==r)//到达叶节点,修改叶节点的值
32     {
33         sum[rt]+=add;
34         return;
35     }
36     int m=(l+r)>>1;
37     //根据条件判断往左子树调用,还是往右
38     if(p>m) update(p,add,rt<<1|1,m+1,r);
39     else update(p,add,rt<<1,l,m);
40     up(rt); //子节点更新了,本节点也要更新
41 }
42 int query(int L,int R,int rt,int l,int r)
43 {
44     if(L<=l && r<=R) return sum[rt];//区间内直接返回
45     int m=(l+r)>>1;
46     //累加答案
47     int ret=0;
48     if(L<=m) ret+=query(L,R,rt<<1,l,m);//左子区间有重叠,递归
49     if(R>m)ret+=query(L,R,rt<<1|1,m+1,r);//右子区间有重叠,递归
50     return ret;
51 }
52 int main()
53 {
54     int t;
55     scanf("%d",&t);
56     for(int kase=1;kase<=t;kase++)
57     {
58         int n;
59         memset(sum,0,sizeof(sum));
60         scanf("%d",&n);
61         for(int i=1;i<=n;i++)
62             scanf("%d",&num[i]);
63         build(1,1,n);
64         printf("Case %d:\n",kase);
65         char s[10];
66         while(scanf("%s",&s)!=EOF && strcmp(s,"End"))
67         {
68             int x,y;
69             scanf("%d%d",&x,&y);
70             if(s[0]==Q)printf("%d\n",query(x,y,1,1,n));
71             else if(s[0]==A)update(x,y,1,1,n);
72             else if(s[0]==S)update(x,-y,1,1,n);
73         }
74     }
75     return 0;
76 }

 

kuangbin专题七、线段树