POJ 3667 Hotel 線段樹 區間合併(成段更新)

//POJ 3667 Hotel 線段樹 區間合併(成段更新)

/*
題目大意:有n間房子,有兩種操作:
	1 a:詢問是不是有連續長度爲a的空房間,有的話住進最左邊
	2 a b:將[a,a+b-1]的房間清空思路:記錄區間中最長的空房間 ,

線段樹操作:
	update:區間替換 
	query:詢問滿足條件的最左端點 ,線段樹每個節點記錄 
	3個參數 :
	lsum :左端開始的空餘量 ;
	rsum :右端開始的空餘量 ;
	msum : 最大空餘量(可能在中間)
*/

#include<stdio.h>

#define N 50005
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r

int lsum[N<<2],rsum[N<<2],msum[N<<2];
int add[N<<2];
int n,m;

int Max(int x,int y){
    return x>y?x:y;
}

void pushup(int rt,int m){
    lsum[rt] = lsum[rt<<1];
    rsum[rt] = rsum[rt<<1|1];
    if(lsum[rt] == m-(m>>1)) lsum[rt] += lsum[rt<<1|1];
    if(rsum[rt] == (m>>1)) rsum[rt] += rsum[rt<<1];
    msum[rt] = Max(rsum[rt<<1] + lsum[rt<<1|1],Max(msum[rt<<1],msum[rt<<1|1]));
}

void pushdown(int rt,int m){
    if(add[rt] != -1){
        add[rt<<1] = add[rt<<1|1] = add[rt];
        lsum[rt<<1] = rsum[rt<<1] = msum[rt<<1] = add[rt] ? 0 : m-(m>>1);
        lsum[rt<<1|1] = rsum[rt<<1|1] = msum[rt<<1|1] = add[rt] ? 0 : (m>>1);
        add[rt] = -1;
    }
}

void build(int rt,int l,int r){
    lsum[rt] = rsum[rt] = msum[rt] = r-l+1;
    add[rt] = -1;
    if(l == r) return;
    int mid = (l + r) >> 1;
    build(lson);
    build(rson);
}

int query(int rt,int l,int r,int w){
    if(l == r)    return l;
    pushdown(rt,r-l+1);
    int mid = (l + r) >> 1;
    if(msum[rt<<1] >= w)
        return query(lson,w);
    else if(rsum[rt<<1] + lsum[rt<<1|1] >= w)
        return mid-rsum[rt<<1]+1;
    else
        return query(rson,w);
}

void update(int rt,int l,int r,int L,int R,int w){
    if(L <= l && R >= r){
        lsum[rt] = rsum[rt] = msum[rt] = w ? 0 :r-l+1;
        add[rt] = w;;
        return;
    }
    pushdown(rt,r-l+1);
    int mid = (l  + r) >> 1;
    if(L <= mid) update(lson,L,R,w);
    if(R > mid ) update(rson,L,R,w);
    pushup(rt,r-l+1);
}

int main(){
    int i;
    int op,a,b,c;
    while(scanf("%d %d",&n,&m)!=EOF){
        build(1,1,n);
        for(i = 1; i <= m; ++i){
            scanf("%d",&op);
            if(op == 1){
                scanf("%d",&c);
                if(msum[1] < c)
                    puts("0");
                else{
                    int res = query(1,1,n,c);
                    printf("%d\n",res);
                    update(1,1,n,res,res+c-1,1);
                }
            }
            else{
                scanf("%d %d",&a,&b);
                update(1,1,n,a,a+b-1,0);
            }
        }
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章