题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=16216
题意:给定每个点的人数,并且中间会有增减的操作。求某一段区间的人数和
思路:线段树第一题,所以多少有点参考别人代码。主要熟悉了下线段树的建立、查找、更新的方法,采用二进制。
源码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
int const MAXN = 50000+5;
int peo[MAXN<<2];
int n;
int query(int l,int r,int L,int R,int st)
{
int ans = 0;
if(l<=L && r>=R)
return peo[st];
int mid = (L+R)>>1;
if(mid>=l) ans+=query(l,r,L,mid,st<<1);
if(mid<r) ans+=query(l,r,mid+1,R,(st<<1)+1);
// printf("ans = %d\n",ans);
return ans;
}
void update(int mark,int add,int L,int R,int st)
{
if(L==R){
peo[st] += add;
return;
}
else{
int mid = (R+L)/2;
int ans = 0;
if(mid>=mark) update(mark,add,L,mid,st<<1);
else update(mark,add,mid+1,R,(st<<1)+1);
// printf("ans = %d\n",ans);
peo[st] = peo[st<<1] + peo[(st<<1)+1];
return;
}
// for(int i=1;i<=(n<<2); i++)
// printf("%d ",peo[i]);
// printf("\n");
}
int main()
{
int t;
scanf("%d",&t);
for(int i=1; i<=t; i++){
memset(peo,0,sizeof(peo));
int a,b;
char temp[5];
scanf("%d",&n);
for(int j=1; j<=n; j++){
scanf("%d",&b);
update(j,b,1,n,1);
}
printf("Case %d:\n",i);
while(scanf("%s",temp)!=EOF && temp[0]!='E'){
scanf("%d%d",&a,&b);
if(temp[0]=='Q')
printf("%d\n",query(a,b,1,n,1));
if(temp[0] == 'A') update(a,b,1,n,1);
else if(temp[0] == 'S') update(a,-b,1,n,1);
// for(i=1; i<(n<<2); i++)
// printf("%d ",peo[i]);
// printf("\n");
}
}
return 0;
}