码迷,mamicode.com
首页 > 其他好文 > 详细

poj 3669 线段树成段更新+区间合并

时间:2015-07-18 18:24:49      阅读:133      评论:0      收藏:0      [点我收藏+]

标签:

添加 lsum[ ] , rsum[ ] , msum[ ] 来记录从左到右的区间,从右到左的区间和最大的区间;

#include<stdio.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 50005
int rsum[maxn<<2],lsum[maxn<<2],msum[maxn<<2];//msum[]维护区间1…N中的最大连续区间长度
int mark[maxn<<2];
int max(int x,int y)
{
    return x>y?x:y;
}
void pushup(int l,int r,int rt)
{
    int m=(l+r)/2;
    lsum[rt]=lsum[rt<<1];
    rsum[rt]=rsum[rt<<1|1];
    msum[rt]=max(msum[rt<<1],msum[rt<<1|1]);
    if(lsum[rt<<1]==m-l+1)
        lsum[rt]=lsum[rt<<1]+lsum[rt<<1|1];
    if(rsum[rt<<1|1]==r-m)
        rsum[rt]=rsum[rt<<1|1]+rsum[rt<<1];
    msum[rt]=max(msum[rt],lsum[rt<<1|1]+rsum[rt<<1]);
}
void pushdown(int l,int r,int rt)
{
    if(mark[rt]!=-1)
    {
        int len=r-l+1;

        mark[rt<<1]=mark[rt];
        mark[rt<<1|1]=mark[rt];
        if(mark[rt]==0)
        {
            lsum[rt<<1]=rsum[rt<<1]=msum[rt<<1]=0;
            lsum[rt<<1|1]=rsum[rt<<1|1]=msum[rt<<1|1]=0;
        }
        else
        {
            lsum[rt<<1]=rsum[rt<<1]=msum[rt<<1]=len-len/2;
            rsum[rt<<1|1]=lsum[rt<<1|1]=msum[rt<<1|1]=len/2;
        }
        mark[rt]=-1;
    }
}
void build(int l,int r,int rt)
{
    mark[rt]=-1;
    if(l==r)
    {
        lsum[rt]=rsum[rt]=msum[rt]=1;
        return ;
    }
    int m=(l+r)/2;
    build(lson);
    build(rson);
    pushup(l,r,rt);
}
void updata(int L,int R,int c,int l,int r,int rt)
{
    if(l>=L&&R>=r)
    {
        mark[rt]=c;
        if(mark[rt]==0)
        {
            lsum[rt]=rsum[rt]=msum[rt]=0;
        }
        else 
            lsum[rt]=rsum[rt]=msum[rt]=r-l+1;
        return ;
    }
    pushdown(l,r,rt);
    int m=(l+r)/2;
    if(m>=L)
        updata(L,R,c,lson);
    if(R>m)
        updata(L,R,c,rson);
    pushup(l,r,rt);
}
int query(int num,int l,int r,int rt)
{
    if(l==r)
    {
        return l;
    }
    pushdown(l,r,rt);
    int m=(l+r)/2;
    int ret;
    if(msum[rt<<1]>=num)//由于从最左边开始坐位子,所以rsum[rt<<1]>
    {
        return query(num,lson);
    }
    else if(lsum[rt<<1|1]+rsum[rt<<1]>=num)
        return m-rsum[rt<<1]+1;
    else
        return query(num,rson);
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        build(1,n,1);
        int a,b,c;
        while(m--)
        {
            scanf("%d",&a);
            if(a==1)
            {
                scanf("%d",&b);
                if(b>msum[1])
                    printf("0\n");
                else
                {
                    int ret=query(b,1,n,1);
                    printf("%d\n",ret);
                    updata(ret,ret+b-1,0,1,n,1);
                }
            }
            else
            {
                scanf("%d%d",&b,&c);
                updata(b,b+c-1,1,1,n,1);
            }
        }
    }
}

 

poj 3669 线段树成段更新+区间合并

标签:

原文地址:http://www.cnblogs.com/sweat123/p/4657238.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!