HDU 1166 敌兵布阵

经典线段树

 

#include
#include
#include
using namespace std;
int n;
int a[50002];
struct point//构建每一个点,每一个点都有左右两个子节点
{
    int l,r,sum;
}
p[200002];

void setuptree(int l,int r,int the)//用点构建一个树
{
    int mid;
    p[the].l=l;
    p[the].r=r;
    p[the].sum=0;
    if(l==r)
    {
        p[the].sum=a[l];
        return;
    }
    mid=(r+l)/2;
    setuptree(l,mid,the*2);
    setuptree(mid+1,r,the*2+1);
    p[the].sum=p[the*2].sum+p[the*2+1].sum;
}
void updatatree(int l,int r,int the,int x,int y)//更新这个树
{
    int mid;
    if(x>=l&&x<=r)
        p[the].sum+=y;

    mid=(r+l)/2;
    if(l==r)
        return;
    if(x<=mid)
        updatatree(l,mid,the*2,x,y);
    else if(x>mid)
        updatatree(mid+1,r,the*2+1,x,y);
}

int searchtree(int l,int r,int the)//查找树
{
    if(p[the].l==l&&p[the].r==r)
        return p[the].sum;
    int mid;
    mid=(p[the].l+p[the].r)/2;
    if(r<=mid)            //在左子树中
        return searchtree(l,r,the*2);
    else if(l>mid)       //在右子树中
        return searchtree(l,r,the*2+1);
    else                     //就在这个区间,两个子树都有要找的。
        return searchtree(l,mid,the*2)+searchtree(mid+1,r,the*2+1);
}

int main()
{
    int t,i,j;
    int x,y;
    char c[10];
    scanf("%d",&t);
    int Case=1;
    while(t--)
    {
        printf("Case %d:\n",Case++);
        scanf("%d",&n);
        for(i=1; i<=n; i++)
            scanf("%d",&a[i]);
        setuptree(1,n,1);
        memset(c,0,sizeof(c));
        while(~scanf("%s",c))
        {
            if(!strcmp(c,"End"))
                break;
            scanf("%d%d",&x,&y);
            if(!strcmp(c,"Query"))
                printf("%d\n",searchtree(x,y,1));
            if(!strcmp(c,"Add"))
                updatatree(1,n,1,x,y);
            if(!strcmp(c,"Sub"))
                updatatree(1,n,1,x,-y);
            memset(c,0,sizeof(c));
        }
    }
    return 0;
}

 

 

 

 

 

你可能感兴趣的:((树)字典树_线段树_二叉树)