POJ3667 Hotel

【题目描述】

给定一排连续的房间,有两个操作:1--找到一排连续尽可能靠左的n个房间,入住房间,并输出最左的房间号,如果不存在输出0;

2--清空某个区间内房间的人 。

【分析】

非常非常经典的一道题。

ps.前两天做的这题,当时想了半天没有想好怎么去维护,后来依靠题解磕磕绊绊的过了这题。结果今天写题解的时候还是没有马上想到思路,有空重新做一次这题。

s[n][0]表示以区间左端点开始的连续空房间个数

s[n][1]表示以区间右端点结束的连续空房间个数

s[n][2]表示整个区间的连续空房间个数

s[n][3]为懒惰标记。

注意询问的时候要输出满足条件的最左的房间号,所以注意下判断的次序即可。

#include<cstdio>
#define  N 50010
#define lson l,m,n<<1
#define rson m+1,r,n<<1|1
using namespace std;
int s[N<<2][4];
int max(int a,int b,int c){
    int ans=a>b?a:b;
    return ans>c?ans:c;
}
void pushup(int n,int m){
    s[n][0]=s[n<<1][0];
    s[n][1]=s[n<<1|1][1];
    if(s[n<<1][0]==(m-(m>>1)))
    s[n][0]+=s[n<<1|1][0];
    if(s[n<<1|1][1]==(m>>1))
    s[n][1]+=s[n<<1][1];
    s[n][2]=max(s[n<<1][2],s[n<<1|1][2],s[n<<1][1]+s[n<<1|1][0]);
}
void pushdown(int n,int m){
    if(s[n][3]!=-1){
        s[n<<1][0]=s[n<<1][1]=s[n<<1][2]=s[n][3]?0:(m-(m>>1));
        s[n<<1|1][0]=s[n<<1|1][1]=s[n<<1|1][2]=s[n][3]?0:(m>>1);
        s[n<<1][3]=s[n<<1|1][3]=s[n][3];
        s[n][3]=-1;
    }
}
void build(int l,int r,int n){
    s[n][0]=s[n][1]=s[n][2]=r-l+1;
    s[n][3]=-1;
    if(l==r)return;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}
void update(int ll,int rr,int f,int l,int r,int n){
    if(ll==l&&rr==r){
        s[n][0]=s[n][1]=s[n][2]=f?0:(r-l+1);
        s[n][3]=f;
        return;
    }
    pushdown(n,r-l+1);
    int m=(l+r)>>1;
    if(rr<=m)
    update(ll,rr,f,lson);
    else if(ll>m)
    update(ll,rr,f,rson);
    else
    update(ll,m,f,lson),update(m+1,rr,f,rson);
    pushup(n,r-l+1);
}
int query(int nn,int l,int r,int n){
    if(l==r)return l;
    pushdown(n,r-l+1);
    int m=(l+r)>>1;
    if(s[n<<1][2]>=nn)
    return query(nn,lson);
    else if(s[n<<1][1]+s[n<<1|1][0]>=nn)
    return m-s[n<<1][1]+1;
    return query(nn,rson);
}
int main(){
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        build(1,n,1);
        for(int i=1;i<=m;i++){
            int f,a,b;
            scanf("%d",&f);
            if(f==1){
                scanf("%d",&a);
                if(s[1][2]<a) puts("0");
                else{
                    int ans=query(a,1,n,1);
                    printf("%d\n",ans);
                    update(ans,ans+a-1,1,1,n,1);
                }
            }
            else if(f==2){
                scanf("%d%d",&a,&b);
                update(a,a+b-1,0,1,n,1);
            }
        }
    }
    return 0;
}
posted @ 2012-08-01 23:20  silver__bullet  阅读(142)  评论(0编辑  收藏  举报