D - 敌兵布阵
题目连接 http://acm.hust.edu.cn/vjudge/contest/121192#problem/D
这是线段树的应用,建树,查询,更新(包括点和区间)
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define MAXN 50005//宏定义的格式 #define MAXN 50005 int cnt[MAXN*4]; void Build(int l,int r,int pt) { if( l==r){ scanf("%d",&cnt[pt]);//如果左端点等于右端点就输入这个点的数据,每个点都是最小的一个区间 return ; } int mid=(l+r)>>1;//(l+r)>>1等于(l+r)/2 Build(l,mid,pt<<1);//pt<<1等于pt*2 Build(mid+1,r,pt<<1|1);//pt<<1|1等于pt*2+1 cnt[pt]=cnt[pt<<1]+cnt[pt<<1|1];//涉及求和的题让父区间等于所有子区间的和 } void Update(int i,int add,int l,int r,int pt)//点更新(通过循环找到要更新的点, //同时更新包含此点的区间) { if( l==r){ cnt[pt]+=add; return ; } int mid=(l+r)>>1; if(i<=mid) Update(i,add,l,mid,pt<<1); else Update(i,add,mid+1,r,pt<<1|1); cnt[pt]=cnt[pt<<1]+cnt[pt<<1|1]; } int Query(int L,int R,int l,int r,int pt)//区间查询 { if( L<=l&&R>=r)//当查询区间大于等于给定的区间时 就直接返回区间的值 return cnt[pt]; int sum=0; int mid=(l+r)>>1; if(L<=mid) sum+=Query(L,R,l,mid,pt<<1); if(R>mid) sum+=Query(L,R,mid+1,r,pt<<1|1); return sum; } int main() { int i,t,n,c,l,r; char cmd[10]; scanf("%d",&t); for( c=1; c<=t; c++){ memset(cnt,0,sizeof(cnt)); scanf("%d",&n); Build(1,n,1); printf("Case %d:\n",c); while( true){ scanf("%s",cmd); if( cmd[0]=='E') break; if( cmd[0]=='Q'){ scanf("%d%d",&l,&r); printf("%d\n",Query(l,r,1,n,1)); } else if( cmd[0]=='A'){ scanf("%d%d",&i,&l); Update(i,l,1,n,1); } else{ scanf("%d%d",&i,&l); Update(i,-l,1,n,1); } } } return 0; }