HDU 1540 (区间合并)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define maxn 50010
#define Lson root*2
#define Rson root*2+1
#define Max(a,b)(a>b?a:b)
int ac[maxn];
struct ndoe
{//lsum表示左区间的连续,rsum表示在右区间的连续,sum表示中间区间的连续;
    int L,R;
    int lsum,rsum,sum;
    int Mid()
    {
        return (R+L)/2;
    }
    int len()
    {
        return (R-L+1);
    }
} a[maxn*4];
void BuildTree(int root,int L,int R)
{
    a[root].L=L,a[root].R=R;
    a[root].lsum = a[root].rsum = a[root].sum = a[root].len();
    if(L==R) return ;
    BuildTree(Lson,L,a[root].Mid());
    BuildTree(Rson,a[root].Mid()+1,R);
}
void pushup(int root)
{
    a[root].lsum = a[Lson].lsum, a[root].rsum = a[Rson].rsum;//左区间的连续 最大为子节点的最大连续,右区间同理;

    if(a[Lson].lsum == a[Lson].len())                       //如果子节点的最大连续等于其长度,则说明其最大连续可以加上右区间的左连续;
        a[root].lsum = a[Lson].lsum + a[Rson].lsum;        
    if(a[Rson].rsum == a[Rson].len())
        a[root].rsum = a[Rson].rsum + a[Lson].rsum;

    a[root].sum = Max(a[root].lsum, Max(a[root].rsum, a[Lson].rsum+a[Rson].lsum));//中间区间的最大为三个数的最大值(左连续,右连续,子节点左区间的右连续+右区间的左连续)
}
void update(int root, int k, int e)
{
    if( a[root].L == a[root].R )
    {
        a[root].lsum = a[root].rsum = a[root].sum = e;
        return ;
    }

    if(k <= a[root].Mid())
        update(Lson, k, e);
    else
        update(Rson, k, e);

    pushup(root);
}
int Query(int root,int k)
{
    if(a[root].sum ==0 )
        return 0;
    if(k < a[root].L +a[root].lsum)    //判断其是否在左区间;K < 左端点 + 左连续;
        return a[root].lsum;
    if(k > a[root].R - a[root].rsum)  //判断其是否在右区间; k > 右端点 - 右连续;
        return a[root].rsum;
    if(k > (a[Lson].R - a[Lson].rsum) && k < (a[Rson].L + a[Rson].lsum)) //判断是否在中间; 右端点 - 右连续 < K < 左端点 + 左连续;
        return a[Rson].lsum + a[Lson].rsum;
    if(k<=a[root].Mid())
        return Query(Lson,k);
    else
        return Query(Rson,k);
}
int main()
{
    int n,m,k,w;
    char str[10];
    while(~scanf("%d%d",&n,&m))
    {
        k=0;
        BuildTree(1,1,n);
        while(m--)
        {
            scanf("%s",str);
            if(str[0]=='D')
            {
                scanf("%d",&w);
                ac[k]=w;
                update(1,w,0);
                k++;
            }
            if(str[0]=='R')
            {
                k--;
                w = ac[k];
                update(1,w,1);
            }
            if(str[0] == 'Q')
            {
                scanf("%d",&w);
                printf("%d\n",Query(1,w));
            }
        }
    }
    return 0;
}

 

posted @ 2015-08-03 17:09  _Nestling  阅读(173)  评论(0编辑  收藏  举报