首页 > 代码库 > [HDU 1166 敌兵布阵] 线段树 或 树状数组

[HDU 1166 敌兵布阵] 线段树 或 树状数组

 

 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 }