poj3667 区间合并,找最左边的空余块

题很简单:给两个操作1:查找最左边的a个空余块并填满

          2:把从第a个开始的连续b个块置空

线段树维护左连续,右连续,最大连续,lazy-tag即可,query函数值得学习

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 500005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int lmx[maxn<<2],rmx[maxn<<2],mx[maxn<<2],flag[maxn<<2];

inline void set0(int l,int r,int rt){
    lmx[rt]=rmx[rt]=mx[rt]=r-l+1;
    flag[rt]=0;
}
inline void set1(int l,int r,int rt){
    lmx[rt]=rmx[rt]=mx[rt]=0;
    flag[rt]=1;
}
inline void pushup(int l,int r,int rt){
    lmx[rt]=lmx[rt<<1];rmx[rt]=rmx[rt<<1|1];
    mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
    int m=l+r>>1;
    if(lmx[rt<<1]==m-l+1) lmx[rt]+=lmx[rt<<1|1];
    if(rmx[rt<<1|1]==r-m) rmx[rt]+=rmx[rt<<1];
    if(rmx[rt<<1]&&lmx[rt<<1|1]) 
        mx[rt]=max(mx[rt],rmx[rt<<1]+lmx[rt<<1|1]);    
    
}
inline void pushdown(int l,int r,int rt){
    if(flag[rt]>=0){
        int m=l+r>>1; 
        flag[rt<<1]=flag[rt<<1|1]=flag[rt];
        if(flag[rt]==0){
            set0(lson);set0(rson);
        }
        else if(flag[rt]==1){
            set1(lson);set1(rson);
        }
        flag[rt]=-1;
    }
}
void build(int l,int r,int rt){
    if(l==r){
        lmx[rt]=rmx[rt]=mx[rt]=1;
        flag[rt]=-1;
        return;
    }
    int m=l+r>>1;
    build(lson);
    build(rson);
    pushup(l,r,rt);
}
void  update(int L,int R,int op,int l,int r,int rt){
    if(L<=l && R>=r){
        if(op==0) set0(l,r,rt);
        if(op==1) set1(l,r,rt);
        return;
    }
    pushdown(l,r,rt);
    int m=l+r>>1;
    if(L<=m) 
        update(L,R,op,lson);
    if(R>m)
        update(L,R,op,rson);
    pushup(l,r,rt);
}
//cnt要么在左儿子,要么在中间合并块,要么在右子树
int query(int cnt,int l,int r,int rt){
    if(l==r)
        return l;
    pushdown(l,r,rt);
    int m=l+r>>1;
    if(cnt<=mx[rt<<1])
        return query(cnt,lson);
    else if(cnt<=rmx[rt<<1]+lmx[rt<<1|1])
        return m-rmx[rt<<1]+1;
    else 
        return query(cnt,rson);
}
int main(){
    int n,m;
    while(scanf("%d%d",&n,&m)==2){
        build(1,n,1);
        
        int a,b,op;
        while(m--){
            scanf("%d",&op);
            if(op==1){
                scanf("%d",&a);
                if(mx[1]<a){
                    puts("0");
                    continue;
                }
                int tmp=query(a,1,n,1);
                printf("%d\n",tmp);
                update(tmp,tmp+a-1,1,1,n,1);
            }
            else if(op==2){
                scanf("%d%d",&a,&b);
                update(a,a+b-1,0,1,n,1);
            }
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/9977184.html
今日推荐