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;
}

 

posted @ 2016-07-23 16:54  Twsc  阅读(363)  评论(6编辑  收藏  举报