[USACO08FEB]酒店Hotel

题目大意

一段01序列,0代表没人住,1代表有人住,住房和退房都要求是修改一段连续区间.

求能够安排住房的区间的左端点

题解

线段树

要判断能否住 要维护区间0序列长最大值.和区间0序列最左边的长度和右边长度

代码

#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;

int sum[400010],lm[400010],rm[400010],m[400010],tag[400010],n,T;

void pushup(int rt){
    if(m[rt<<1]==sum[rt<<1]){
        lm[rt]=m[rt<<1]+lm[rt<<1|1];
    }else{
        lm[rt]=lm[rt<<1];
    }
    if(m[rt<<1|1]==sum[rt<<1|1]){
        rm[rt]=m[rt<<1|1]+rm[rt<<1];
    }else{
        rm[rt]=rm[rt<<1|1];
    }
    m[rt]=max(max(m[rt<<1],m[rt<<1|1]),rm[rt<<1]+lm[rt<<1|1]);
    return;
}

void pushdown(int rt){
    if(tag[rt]==0)    return;
    if(tag[rt]==1){
        tag[rt<<1]=tag[rt<<1|1]=1;
        m[rt<<1]=lm[rt<<1]=rm[rt<<1]=0;
        m[rt<<1|1]=lm[rt<<1|1]=rm[rt<<1|1]=0;
    }
    if(tag[rt]==2){
        tag[rt<<1]=tag[rt<<1|1]=2;
        m[rt<<1]=lm[rt<<1]=rm[rt<<1]=sum[rt<<1];
        m[rt<<1|1]=lm[rt<<1|1]=rm[rt<<1|1]=sum[rt<<1|1];
    }
    tag[rt]=0;
}

void build(int rt,int l,int r){
    lm[rt]=rm[rt]=m[rt]=sum[rt]=r-l+1;
    tag[rt]=0;
    if(l==r) return;
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    return;
}

int query(int rt,int l,int r,int len){
    pushdown(rt);
    if(l==r)    return l;
    int mid=(l+r)>>1;
    if(m[rt<<1]>=len)    return query(rt<<1,l,mid,len);
    if(rm[rt<<1]+lm[rt<<1|1]>=len)    return mid-rm[rt<<1]+1;
    else    return query(rt<<1|1,mid+1,r,len);
}

void modify(int L,int R,int c,int rt,int l,int r){
    pushdown(rt);
    if((L<=l)&&(r<=R)){
        if(c==1) m[rt]=lm[rt]=rm[rt]=0;
        else m[rt]=lm[rt]=rm[rt]=sum[rt];
        tag[rt]=c;
        return;
    }
    int mid=(l+r)>>1;
    if(L<=mid)    modify(L,R,c,rt<<1,l,mid);
    if(R>mid)    modify(L,R,c,rt<<1|1,mid+1,r);
    pushup(rt);
}

int main(){
    scanf("%d%d",&n,&T);
    build(1,1,n);
    while(T--){
        int opt,a,b;
        scanf("%d",&opt);
        if(opt==1){
            scanf("%d",&a);
            if(m[1]<a){printf("0\n");continue;}
            int p=query(1,1,n,a);
            printf("%d\n",p);
            modify(p,p+a-1,1,1,1,n);
        }else{
            scanf("%d%d",&a,&b);
            modify(a,a+b-1,2,1,1,n);
        }
    }
    return 0;
}

 

posted @ 2017-08-24 10:08  ANhour  阅读(160)  评论(0编辑  收藏  举报