2015-06-08
问题简述:
原题的题意相当于有一些连续摆放的箱子,里面装着球,球的数量可以加减,现要查询几个连续的箱子里球的总数,其中存在放球和拿球的操作。
解题思路:
查询区间和的问题,可以使用线段树。
最初的输入相当于构建线段树的过程;每一次的加减相当于对线段树进行更新;最后使用线段树的查询区间和算法直接得出答案。
源代码:
1 /* 2 OJ: HDOJ 3 ID: forever 4 TASK: 1166.敌兵布阵 5 LANG: C++ 6 NOTE: 线段树 7 */ 8 #include <cstdio> 9 10 const int MAX=200005; 11 int a[MAX]; 12 char str[10]; 13 14 void build(int l,int r,int flag) { 15 if(l==r) { 16 scanf("%d",&a[flag]); 17 return; 18 } 19 int m=(l+r)/2; 20 build(l,m,flag*2); 21 build(m+1,r,flag*2+1); 22 a[flag]=a[flag*2]+a[flag*2+1]; 23 } 24 25 void update(int x,int y,int l,int r,int flag) { 26 if(l==r) { 27 a[flag]+=y; 28 return; 29 } 30 int m=(l+r)/2; 31 if(x<=m) 32 update(x,y,l,m,flag*2); 33 else 34 update(x,y,m+1,r,flag*2+1); 35 a[flag]=a[flag*2]+a[flag*2+1]; 36 } 37 38 int query(int x,int y,int l,int r,int flag) { 39 if(x<=l&&r<=y) 40 return a[flag]; 41 int m=(l+r)/2; 42 int ans=0; 43 if(x<=m) 44 ans+=query(x,y,l,m,flag*2); 45 if(y>m) 46 ans+=query(x,y,m+1,r,flag*2+1); 47 return ans; 48 } 49 50 int main() 51 { 52 int t,n,x,y,k=1; 53 scanf("%d",&t); 54 while(t--) { 55 scanf("%d",&n); 56 build(1,n,1); 57 printf("Case %d:\n",k++); 58 while(scanf("%s",str)&&str[0]!=‘E‘) { 59 scanf("%d %d",&x,&y); 60 if(str[0]==‘Q‘) 61 printf("%d\n",query(x,y,1,n,1)); 62 else if(str[0]==‘A‘) 63 update(x,y,1,n,1); 64 else if(str[0]==‘S‘) 65 update(x,-y,1,n,1); 66 } 67 } 68 return 0; 69 }
时间: 2024-10-29 05:02:52