敌兵布阵

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 18120    Accepted Submission(s): 7877


Problem Description
C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了。A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况。由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工兵营地的人数都有可能发生变动,可能增加或减少若干人手,但这些都逃不过C国的监视。
中央情报局要研究敌人究竟演习什么战术,所以Tidy要随时向Derek汇报某一段连续的工兵营地一共有多少人,例如Derek问:“Tidy,马上汇报第3个营地到第10个营地共有多少人!”Tidy就要马上开始计算这一段的总人数并汇报。但敌兵营地的人数经常变动,而Derek每次询问的段都不一样,所以Tidy不得不每次都一个一个营地的去数,很快就精疲力尽了,Derek对Tidy的计算速度越来越不满:"你个死肥仔,算得这么慢,我炒你鱿鱼!”Tidy想:“你自己来算算看,这可真是一项累人的工作!我恨不得你炒我鱿鱼呢!”无奈之下,Tidy只好打电话向计算机专家Windbreaker求救,Windbreaker说:“死肥仔,叫你平时做多点acm题和看多点算法书,现在尝到苦果了吧!”Tidy说:"我知错了。。。"但Windbreaker已经挂掉电话了。Tidy很苦恼,这么算他真的会崩溃的,聪明的读者,你能写个程序帮他完成这项工作吗?不过如果你的程序效率不够高的话,Tidy还是会受到Derek的责骂的.
 

 

Input
第一行一个整数T,表示有T组数据。
每组数据第一行一个正整数N(N<=50000),表示敌人有N个工兵营地,接下来有N个正整数,第i个正整数ai代表第i个工兵营地里开始时有ai个人(1<=ai<=50)。
接下来每行有一条命令,命令有4种形式:
(1) Add i j,i和j为正整数,表示第i个营地增加j个人(j不超过30)
(2)Sub i j ,i和j为正整数,表示第i个营地减少j个人(j不超过30);
(3)Query i j ,i和j为正整数,i<=j,表示询问第i到第j个营地的总人数;
(4)End 表示结束,这条命令在每组数据最后出现;
每组数据最多有40000条命令
 

 

Output
对第i组数据,首先输出“Case i:”和回车,
对于每个Query询问,输出一个整数并回车,表示询问的段中的总人数,这个数保持在int以内。
 

 

Sample Input
1 10 1 2 3 4 5 6 7 8 9 10 Query 1 3 Add 3 6 Query 2 7 Sub 10 2 Add 6 3 Query 3 10 End
 

 

Sample Output
Case 1: 6 33 59
  1 /* 功能Function Description:    HDOJ-1166 树状数组插点问线  、线段树解法
  2    开发环境Environment:            DEV C++ 4.9.9.1
  3    技术特点Technique:
  4    版本Version:
  5    作者Author:                  可笑痴狂
  6    日期Date:                    20120808
  7    备注Notes:
  8 */
  9 
 10 /*
 11 //代码一:----树状数组
 12 #include<stdio.h>
 13 #include<string.h>
 14 
 15 int n;
 16 int a[50005];
 17 
 18 int lowbit(int i)
 19 {
 20     return i&(-i);
 21 }
 22 
 23 void update(int i,int num)
 24 {
 25     while(i<=n)
 26     {
 27         a[i]+=num;
 28         i+=lowbit(i);
 29     }
 30 }
 31 
 32 int getsum(int i)
 33 {
 34     int sum=0;
 35     while(i>0)
 36     {
 37         sum+=a[i];
 38         i-=lowbit(i);
 39     }
 40     return sum;
 41 }
 42 
 43 int main()
 44 {
 45     int T,i,j,m;
 46     char cmd[10];
 47     scanf("%d",&T);
 48     for(m=1;m<=T;++m)
 49     {
 50         printf("Case %d:\n",m);
 51         memset(a,0,sizeof(a));
 52         scanf("%d",&n);
 53         for(i=1;i<=n;++i)
 54         {
 55             scanf("%d",&j);
 56             update(i,j);
 57         }
 58         while(scanf("%s",cmd))
 59         {
 60             if(cmd[0]=='A')
 61             {
 62                 scanf("%d%d",&i,&j);
 63                 update(i,j);
 64             }
 65             else if(cmd[0]=='Q')
 66             {
 67                 scanf("%d%d",&i,&j);
 68                 printf("%d\n",getsum(j)-getsum(i-1));
 69             }
 70             else if(cmd[0]=='S')
 71             {
 72                 scanf("%d%d",&i,&j);
 73                 update(i,-j);
 74             }
 75             else
 76                 break;
 77         }
 78     }
 79     return 0;
 80 }
 81 */
 82 
 83 //代码二:-------线段树
 84 
 85 #include<stdio.h>
 86 #define MAX 50000
 87 
 88 struct node
 89 {
 90     int lc,rc;
 91     int sum;     //存放的是从lc到rc之间的总人数
 92 }tree[MAX*3];
 93 
 94 void build(int s,int t,int T)
 95 {
 96     int mid=(s+t)>>1;
 97     tree[T].lc=s;
 98     tree[T].rc=t;
 99     tree[T].sum=0;
100     if(s==t)
101         return;
102     build(s,mid,T<<1);
103     build(mid+1,t,(T<<1)|1);
104 }
105 
106 void insert(int num,int add,int T)    //编号为num的线段增加了add,从T开始查找,在含有num的线段中sum都加add
107 {
108     if(num<tree[T].lc||num>tree[T].rc)
109         return ;
110     else
111     {
112         tree[T].sum+=add;
113         if(tree[T].lc==tree[T].rc)
114             return;
115         if(num<=((tree[T].lc+tree[T].rc)>>1))
116             insert(num,add,T<<1);
117         else
118             insert(num,add,(T<<1)|1);
119     }
120 }
121 
122 int getsum(int s,int t,int T)  //统计从s到t的总人数,从T开始查找知道找到该条线段为止
123 {
124     int mid=(tree[T].lc+tree[T].rc)>>1;
125     if(tree[T].lc==s&&tree[T].rc==t)
126         return tree[T].sum;
127     if(t<=mid)
128         return getsum(s,t,T<<1);
129     else if(s>mid)
130         return getsum(s,t,(T<<1)|1);
131     else
132         return getsum(s,mid,T<<1)+getsum(mid+1,t,(T<<1)|1);
133 }
134 
135 
136 int main()
137 {
138     int k,i,j,m,n,t;
139     char cmd[10];
140     scanf("%d",&k);
141     for(m=1;m<=k;++m)
142     {
143         printf("Case %d:\n",m);
144         scanf("%d",&n);
145         build(1,n,1);
146         for(i=1;i<=n;++i)
147         {
148             scanf("%d",&t);
149             insert(i,t,1);
150         }
151         while(scanf("%s",cmd))
152         {
153             if(cmd[0]=='A')
154             {
155                 scanf("%d%d",&i,&j);
156                 insert(i,j,1);
157             }
158             else if(cmd[0]=='Q')
159             {
160                 scanf("%d%d",&i,&j);
161                 printf("%d\n",getsum(i,j,1));
162             }
163             else if(cmd[0]=='S')
164             {
165                 scanf("%d%d",&i,&j);
166                 insert(i,-j,1);
167             }
168             else
169                 break;
170         }
171     }
172     return 0;
173 }

 

 
posted on 2012-08-08 22:32  可笑痴狂  阅读(556)  评论(0编辑  收藏  举报