poj 3667 Hotel

线段树处理区间合并问题。

#include<stdio.h>
#define MAX 50010
#include<algorithm>
using namespace std;

int L[4*MAX+1],R[4*MAX+1],M[4*MAX+1],covered[4*MAX+1];

void pushup(int l,int r,int rt)
{
    int k=R[rt<<1]+L[rt<<1|1]; int m=(l+r)/2;

    if(L[rt<<1]==m-l+1)  L[rt]=L[rt<<1]+L[rt<<1|1];
    else L[rt]=L[rt<<1];

    if(R[rt<<1|1]==r-m)  R[rt]=R[rt<<1|1]+R[rt<<1];
    else R[rt]=R[rt<<1|1];

    M[rt]= max( max(M[rt<<1],M[rt<<1|1]), k );
}

void pushdown(int l,int r,int rt)
{
    int m=(l+r)/2;
    if( covered[rt]==-1 ) return;
    covered[rt<<1]=covered[rt<<1|1]=covered[rt];
    if( covered[rt]==1 )
    {
        L[rt<<1]=R[rt<<1]=M[rt<<1]=0;
        L[rt<<1|1]=R[rt<<1|1]=M[rt<<1|1]=0;
    }
    if( covered[rt]==0 )
    {
        L[rt<<1]=R[rt<<1]=M[rt<<1]=m-l+1;
        L[rt<<1|1]=R[rt<<1|1]=M[rt<<1|1]=r-m;
    }
    covered[rt]=-1;
}

void build(int l,int r,int rt)
{
    L[rt]=R[rt]=M[rt]=r-l+1;
    covered[rt]=-1;
    if(l==r) return ;
    int m=(l+r)/2;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
}

void update(int tag,int a,int b,int l,int r,int rt)
{
    if( l==a && r==b )
    {
        if( tag==0 ){
            L[rt]=R[rt]=M[rt]=r-l+1;
            covered[rt]=tag;
        }
        else
        {
            covered[rt]=tag;
            L[rt]=R[rt]=M[rt]=0;
        }
        return;
    }
    pushdown(l,r,rt);
    int m=(l+r)/2;
    if( b<=m ) update(tag,a,b,l,m,rt<<1);
    else
        if( a>m ) update(tag,a,b,m+1,r,rt<<1|1);
        else
        {
            update(tag,a,m,l,m,rt<<1);
            update(tag,m+1,b,m+1,r,rt<<1|1);
        }
    pushup(l,r,rt);
}

int query(int len,int l,int r,int rt)
{
    if( l==r ) return 1;
    int m=(l+r)/2;
    pushdown(l,r,rt);
    if( M[rt<<1]>=len )  return query(len,l,m,rt<<1);
    else
        if( R[rt<<1]+L[rt<<1|1] >= len ) return m-R[rt<<1]+1;
        else
            return  query(len,m+1,r,rt<<1|1);
}
int main()
{
    int i,j,k;int N,m;
    scanf("%d%d",&N,&m);
    build(1,N,1);
    for(i=1;i<=m;i++)
    {
        scanf("%d",&j);
        if(j==1)
        {
            int len;
            scanf("%d",&len);
            if( M[1]<len ) printf("0\n");
            else
            {
                int ans=query(len,1,N,1);
                update(1,ans,ans+len-1,1,N,1);
                printf("%d\n",ans);
            }
        }
        else
        {
            int s,len;
            scanf("%d%d",&s,&len);
            update(0,s,s+len-1,1,N,1);
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值