hdu1166

尼玛,无力吐槽,搞了几个小时,没想到是输出Case 时出错

这种类型是线段树,关于线段树,线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。

 

  对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度。

 

  使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,因此有时需要离散化让空间压缩。参照这个图理解下

 

 

 

建树:

void build(int left,int right,int i)
{
    int mid;
    b[i].left=left;
    b[i].right=right;
    if(left==right)
    {
        b[i].sum=a[left];
        return ;
    }

    mid=(left+right)/2;
    build(left,mid,2*i);
    build(mid+1,right,2*i+1);
    b[i].sum=b[2*i].sum+b[2*i+1].sum;

}

  查找:

int Query(int left, int right,int i)
{
    int mid;
    if(b[i].left==left && b[i].right ==right) return b[i].sum;
    mid=(b[i].left+b[i].right)/2;
    if(right<=mid) return Query(left,right,2*i);
    else if (left>mid ) return Query(left,right,2*i+1);
    else return Query(left,mid,2*i) + Query(mid+1,right,2*i+1);
}

  删除,增加:

void  Add(int id,int num,int i)
{
    if(b[i].left==b[i].right)
    {
        b[i].sum=b[i].sum+num;
        return ;
    }
    else
    {
        b[i].sum=b[i].sum+num;
        if(id<=b[i*2].right) Add(id,num,2*i);
        else Add(id,num,2*i+1);
    }
}

  所以,有了以上函数,这道题就不会超时了啊

#include <stdio.h>
#include <string.h>
int a[50010];
struct node
{
    int left,right,sum;
}b[150010];


void build(int left,int right,int i)
{
    int mid;
    b[i].left=left;
    b[i].right=right;
    if(left==right)
    {
        b[i].sum=a[left];
        return ;
    }

    mid=(left+right)/2;
    build(left,mid,2*i);
    build(mid+1,right,2*i+1);
    b[i].sum=b[2*i].sum+b[2*i+1].sum;

}

void  Add(int id,int num,int i)
{
    if(b[i].left==b[i].right)
    {
        b[i].sum=b[i].sum+num;
        return ;
    }
    else
    {
        b[i].sum=b[i].sum+num;
        if(id<=b[i*2].right) Add(id,num,2*i);
        else Add(id,num,2*i+1);
    }
}


int Query(int left, int right,int i)
{
    int mid;
    if(b[i].left==left && b[i].right ==right) return b[i].sum;
    mid=(b[i].left+b[i].right)/2;
    if(right<=mid) return Query(left,right,2*i);
    else if (left>mid ) return Query(left,right,2*i+1);
    else return Query(left,mid,2*i) + Query(mid+1,right,2*i+1);
}


int main()
{
    int Case;
    int n;
    char str[10];
    scanf("%d",&Case);
    int id,num;
    int i;
    int k=1;
    while(Case--)
    {

        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        build(1,n,1);
        printf("Case %d:\n",k++);
        while(1)
        {

            scanf("%s",str);
            if(strcmp(str,"End")==0) break;
            scanf("%d%d",&id,&num);
            if(strcmp(str,"Query")==0)
            {
                printf("%d\n",Query(id,num,1));
            }
            if(strcmp(str,"Add")==0)
            {
                //scanf("%d%d",&id,&num);
                Add(id,num,1);
            }
            if(strcmp(str,"Sub")==0)
            {
                //scanf("%d%d",&id,&num);
                Add(id,-num,1);
            }
        }
    }
    return 0;
}

  

posted on 2012-08-01 17:10  矮人狙击手!  阅读(1069)  评论(0编辑  收藏  举报

导航