HDU 1166

  这是一道线段树的入门题,用于学习基本的线段树的建树、更新、访问的操作。只在这里说说基本的操作。

  首先是建树(void build(int root,int le,int ri)),采用递归的方式:root为当前节点,le为区间的左端点,ri为区间的右端点;如果le==ri,说明此时长度为1,建到最底层了,所以返回;否则,建立左子树和右子树,显然左子树在数组中的下标为2*root,右子树为2*root+1,这时还要将区间一分为二,左子树负责[le,(le+ri)/2]的部分,右子树负责[(le+ri)/2+1,ri]的部分。另外一个操作是更新(void fix(int root,int le,int ri,int val)),同样采用递归的方式,当le>camp[root].right或ri<camp[root].left,说明当前节点负责的区间不是需要更新的区间,返回。显然只有当le<=camp[root].left且ri>=camp[root].right的时候当前节点负责的区间才是需要更新区间的子集,于是更新当前节点,然后更新其左子树和右子树。访问操作因题而异,这道题里如果当前区间是需要查询区间的子集,就返回节点存储的val。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_CAMP 50005
#define MAX_LINE 115
char *query="Query",*add="Add",*sub="Sub",*end="End";
struct segTree
{
    int left;
    int right;
    int val;
}camp[4*MAX_CAMP];
void build(int,int,int),fix(int,int,int,int);
int query_sum(int,int,int),sum=0,n;
int main()
{
    int t,i;
    scanf("%d",&t);
    for(i=1;i<=t;i++)
    {
    int j;
    scanf("%d",&n);
    memset(camp,0,sizeof(camp));
    build(1,1,n);
    for(j=0;j<n;j++)
    {
        int tem;
        scanf("%d",&tem);
        fix(1,j+1,j+1,tem);
    }
    char inpt[MAX_LINE];
    printf("Case %d:\n",i);
    while(scanf("%s",inpt)!=EOF)
    {
        if(strcmp(inpt,end)==0)
        {
        break;
        }
        else if(strcmp(inpt,query)==0)
        {
        int le,ri;
        sum=0;
        scanf("%d%d",&le,&ri);
        sum=query_sum(1,le,ri);
        printf("%d\n",sum);
        }
        else if(strcmp(inpt,add)==0)
        {
        int dest,num;
        scanf("%d%d",&dest,&num);
        fix(1,dest,dest,num);
        }
        else
        {
        int dest,num;
        scanf("%d%d",&dest,&num);
        fix(1,dest,dest,-num);
        }
    }
    }
    return 0;
}
void build(int root,int le,int ri)
{
    if(le>ri)
    return ;
    camp[root].left=le;
    camp[root].right=ri;
    if(le==ri)
    return ;
    int mid=(ri+le)/2;
    build(root*2,le,mid);
    build(root*2+1,mid+1,ri);
}
void fix(int root,int le,int ri,int val)
{
    if(le<=camp[root].left&&ri>=camp[root].right)
    {
    camp[root].val+=val;
    return ;
    }
    if(le>camp[root].right||ri<camp[root].left)
    {
    return ;
    }
    fix(root*2,le,ri,val);
    fix(root*2+1,le,ri,val);
    camp[root].val=camp[root*2].val+camp[root*2+1].val;
}
int query_sum(int root,int le,int ri)
{
    if(le<=camp[root].left&&ri>=camp[root].right)
    {
    return camp[root].val;
    }
    if(le>camp[root].right||ri<camp[root].left)
    {
    return 0;
    }
    return query_sum(root*2,le,ri)+query_sum(root*2+1,le,ri);
}
posted @ 2012-08-06 10:36  等待电子的砹  阅读(162)  评论(0编辑  收藏  举报