POJ 3667 Hotel

题意: 一个有 N 个连续房间的旅馆,对 m 次询问对应两种操作。

    1  a      询问是不是有连续长度为a的空房间,有的话住进最左边
          2 a b    将[a,a+b-1]的房间清空

分析: 区间合并类线段树。

         update  成段更新 

         query   找到满足条件的最左端点

#include<stdio.h>
#include<string.h>
#define maxn 50005
int max(int a,int b)
{ return a>b?a:b; }
int lsum[maxn<<2];
int rsum[maxn<<2];
int msum[maxn<<2];
int cover[maxn<<2];
void creat(int l,int r,int rt)
{
    msum[rt]=lsum[rt]=rsum[rt]=r-l+1;
    cover[rt]=-1;
    if(l==r) return;
    int m=(l+r)>>1;
    creat(l,m,rt<<1);
    creat(m+1,r,rt<<1|1);
}
void pushup(int rt,int x)
{
    lsum[rt]=lsum[rt<<1];
    rsum[rt]=rsum[rt<<1|1];
    if(lsum[rt]==x-(x>>1))
        lsum[rt]+=lsum[rt<<1|1];
    if(rsum[rt]==(x>>1))
        rsum[rt]+=rsum[rt<<1];
    msum[rt]=max(lsum[rt<<1|1]+rsum[rt<<1],max(msum[rt<<1],msum[rt<<1|1]));
}
void pushdown(int rt,int x)
{
    if(cover[rt]!=-1)
    {
        cover[rt<<1]=cover[rt<<1|1]=cover[rt];
        msum[rt<<1]=lsum[rt<<1]=rsum[rt<<1]=cover[rt]?0:x-(x>>1);
        msum[rt<<1|1]=lsum[rt<<1|1]=rsum[rt<<1|1]=cover[rt]?0:(x>>1);
        cover[rt]=-1;
    }
}
void update(int L,int R,int x,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        msum[rt]=lsum[rt]=rsum[rt]=(r-l+1)*x;
        cover[rt]=x?0:1;
        return;
    }
    // 成段更新
    pushdown(rt,r-l+1);
    int m=(l+r)>>1;
    if(L<=m) update(L,R,x,l,m,rt<<1);
    if(R>m)  update(L,R,x,m+1,r,rt<<1|1);
    pushup(rt,r-l+1);
}
int query(int x,int l,int r,int rt)
{
    if(l==r)
        return l;
    pushdown(rt,r-l+1);
    int m=(l+r)>>1;
    if(msum[rt<<1]>=x)
        return query(x,l,m,rt<<1);
    else if(rsum[rt<<1]+lsum[rt<<1|1]>=x)
        return m-rsum[rt<<1]+1;
    return query(x,m+1,r,rt<<1|1);

}
int main()
{
    int a,b,p,n,m,k;
    scanf("%d%d",&n,&m);
    creat(1,n,1);
    while(m--)
    {
        scanf("%d",&p);
        if(p==1)
        {
            scanf("%d",&a);
            if(msum[1]<a)
                printf("0\n");
            else  
            {
                k=query(a,1,n,1);
                printf("%d\n",k);
                update(k,k+a-1,0,1,n,1);
            }
        }
        else 
        {
            scanf("%d%d",&a,&b);
            update(a,a+b-1,1,1,n,1);
        }
    }
    return 0;
}

 

        

posted @ 2012-08-04 11:43  'wind  阅读(163)  评论(0编辑  收藏  举报