1 #include<iostream>
2 #include<cstdio>
3 #include<memory.h>
4 using namespace std;
5 int n,C[50005];
6 //--------------------------
7 int lowbit(int x){
8 return x&-x;
9 }
10 int sum(int x){
11 int ret=0;
12 while(x>0){
13 ret+=C[x];
14 x-=lowbit(x);
15 }
16 return ret;
17 }
18 void add(int x,int d){
19 while(x<=n){
20 C[x]+=d;
21 x+=lowbit(x);
22 }
23 }
24 //--------------------------
25 int main(){
26 int T;
27 scanf("%d",&T);
28 int kases=1;
29 int i,j;
30 int a;
31 for(;kases<=T;kases++){
32 memset(C,0,sizeof(C));
33 scanf("%d",&n);
34 for(i=1;i<=n;i++){
35 scanf("%d",&a);
36 add(i,a);
37 }
38 char str[10];
39 printf("Case %d:\n",kases);
40 bool ok=1;
41 while(ok){
42 scanf("%s",str);
43 switch(str[0]){
44 case ‘Q‘:
45 scanf("%d%d",&i,&j);
46 printf("%d\n",sum(j)-sum(i-1));
47 break;
48 case ‘A‘:
49 scanf("%d%d",&i,&j);
50 add(i,j);
51 break;
52 case ‘S‘:
53 scanf("%d%d",&i,&j);
54 add(i,-j);
55 break;
56 case ‘E‘:
57 ok=0;
58 break;
59 default:break;
60 }
61 }
62 }return 0;
63 }
1 #include<iostream>
2 #include<cmath>
3 using namespace std;
4 #define maxn 100005
5 class Node{
6 public:
7 int l,r;
8 int add;//附加值
9 int sum;
10 }node[maxn];
11 int getRight(int n){//获得满足2^x>=n的最小x[从0层开始,给编号获得层数]
12 return ceil(log10(n*1.0)/log10(2.0));
13 }
14 void build(int l,int r,int num){//输入区间[1,2^getRight(n)],num=1建树
15 if(l==r){
16 node[num].l=node[num].r=l;node[num].add=0;node[num].sum=0;
17 return;
18 }
19 node[num].l=l;node[num].r=r;node[num].add=0;node[num].sum=0;
20 build(l,(l+r)/2,num*2);
21 build((l+r)/2+1,r,num*2+1);
22 }
23 void add(int o,int l,int r,int v){//从o节点开始递归[只要调用时o=1即可]在区间[l,r]全部加v
24 if(l<=node[o].l && r>=node[o].r){//全覆盖[递归边界]
25 node[o].add+=v;
26 }else{
27 int M=node[o].l+(node[o].r-node[o].l)/2;
28 if(r<=M)add(o*2,l,r,v);
29 else if(l>M)add(o*2+1,l,r,v);
30 else{
31 add(o*2,l,M,v);
32 add(o*2+1,M+1,r,v);
33 }
34 }
35 //维护节点o
36 if(node[o].l!=node[o].r){//如果区间只是一个元素就不算
37 node[o].sum=node[2*o].sum+node[2*o+1].sum;
38 }else node[o].sum=0;
39 node[o].sum+=node[o].add*(node[o].r-node[o].l+1);
40 }
41
42 //这里addadd是从上往下这条路的累计addadd值[一同回溯记录这条路节点所有add之和,减少了一次回溯累加add值]
43 //初始时直接令其为0
44 int sum=0;
45 void ask(int o,int l,int r,int addadd){//从o节点开始递归[只要调用时o=1即可]在区间[l,r]的和
46 if(l<=node[o].l && r>=node[o].r){//全覆盖[递归边界]
47 sum+=(node[o].sum+addadd*(node[o].r-node[o].l+1));
48 }else{
49 int M=node[o].l+(node[o].r-node[o].l)/2;
50 if(r<=M)ask(o*2,l,r,node[o].add+addadd);
51 else if(l>M)ask(o*2+1,l,r,node[o].add+addadd);
52 else{
53 ask(o*2,l,M,node[o].add+addadd);
54 ask(o*2+1,M+1,r,node[o].add+addadd);
55 }
56 }
57 }
58 int main(){
59 int T;
60 scanf("%d",&T);
61 int kases=1;
62 int i,j;
63 int a;
64 for(;kases<=T;kases++){
65 int N;
66 scanf("%d",&N);
67 build(1,1<<getRight(N),1);
68 for(i=1;i<=N;i++){
69 scanf("%d",&a);
70 add(1,i,i,a);
71 }
72 char str[10];
73 printf("Case %d:\n",kases);
74 bool ok=1;
75 while(ok){
76 scanf("%s",str);
77 switch(str[0]){
78 case ‘Q‘:
79 scanf("%d%d",&i,&j);
80 sum=0;
81 ask(1,i,j,0);
82 printf("%d\n",sum);
83 break;
84 case ‘A‘:
85 scanf("%d%d",&i,&j);
86 add(1,i,i,j);
87 break;
88 case ‘S‘:
89 scanf("%d%d",&i,&j);
90 add(1,i,i,-j);
91 break;
92 case ‘E‘:
93 ok=0;
94 break;
95 default:break;
96 }
97 }
98 }return 0;
99 }
[HDU 1166 敌兵布阵] 线段树 或 树状数组,码迷,mamicode.com
时间: 2024-12-03 07:52:41