[USACO08FEB]酒店Hotel 线段树

[USACO08FEB]酒店Hotel 线段树

题面

其实就是区间多维护一个lmax,rmax(表示从左开始有连续lmax个空房,一直有连续rmax个空房到最右边),合并时讨论一下即可。

void push_up(int x, int l, int r){
    int mid=(l+r)>>1;
    if(sum[lson]==mid-l+1) lmax[x]=sum[lson]+lmax[rson];
    else lmax[x]=lmax[lson];
    if(sum[rson]==r-(mid+1)+1) rmax[x]=sum[rson]+rmax[lson];
    else rmax[x]=rmax[rson];
    sum[x]=max(max(sum[lson], sum[rson]), rmax[lson]+lmax[rson]);
}

另外,查询时按顺序判断左节点、跨左右节点、右节点是否存在空房大于\(x\)的情况,有则递归下去,这样保证找到最左区间。

#include <cstdio>
#include <algorithm>
#define MAXN 50005
#define MAXM MAXN*4
using namespace std;
int n,m;
inline int read(){
    char ch=getchar();int s=0;
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return s;
}
#define tag_none 0
#define tag_book 1
#define tag_unbook 2
#define lson (x<<1)
#define rson (x<<1|1)
int lmax[MAXM],rmax[MAXM],sum[MAXM],lazy[MAXM];
void push_down(int x, int l, int r){
    if(lazy[x]==tag_none) return;
    lazy[lson]=lazy[rson]=lazy[x];
    if(lazy[x]==tag_book){
        sum[lson]=lmax[lson]=rmax[lson]=0;
        sum[rson]=lmax[rson]=rmax[rson]=0;
    }else{
        int mid=(l+r)>>1;
        sum[lson]=lmax[lson]=rmax[lson]=mid-l+1;
        sum[rson]=lmax[rson]=rmax[rson]=r-(mid+1)+1;
    }
    lazy[x]=tag_none;
}
void push_up(int x, int l, int r){
    int mid=(l+r)>>1;
    if(sum[lson]==mid-l+1) lmax[x]=sum[lson]+lmax[rson];
    else lmax[x]=lmax[lson];
    if(sum[rson]==r-(mid+1)+1) rmax[x]=sum[rson]+rmax[lson];
    else rmax[x]=rmax[rson];
    sum[x]=max(max(sum[lson], sum[rson]), rmax[lson]+lmax[rson]);
}
void change(int x, int l, int r, int cl, int cr, int tag){
    if(cl<=l&&r<=cr){
        if(tag==tag_book) sum[x]=lmax[x]=rmax[x]=0;
        else sum[x]=lmax[x]=rmax[x]=r-l+1;
        lazy[x]=tag;
        return;
    }
    push_down(x, l, r);
    int mid=(l+r)>>1;
    if(cl<=mid) change(lson, l, mid, cl, cr, tag);
    if(mid<cr) change(rson, mid+1, r, cl, cr, tag);
    push_up(x, l, r);
}
int query(int x, int l, int r, int val){
    if(l==r) return l;
    push_down(x, l, r);
    int mid=(l+r)>>1;
    if(sum[lson]>=val) return query(lson, l, mid, val);
    if(rmax[lson]+lmax[rson]>=val) return mid-rmax[lson]+1;
    else return query(rson, mid+1, r, val);
}
void buildt(int x, int l, int r){
    if(l==r){
        sum[x]=lmax[x]=rmax[x]=1;
        return;
    }
    int mid=(l+r)>>1;
    buildt(lson, l, mid);
    buildt(rson, mid+1, r);
    push_up(x, l, r);
}
int main(){
    n=read(),m=read();
    buildt(1, 1, n);
    while(m--){
        int opt=read();
        if(opt==1){
            int x=read();
            if(sum[1]>=x){
                int ans=query(1, 1, n, x);
                printf("%d\n", ans);
                change(1, 1, n, ans, ans+x-1, tag_book);
            }else printf("0\n");
        }else{
            int x=read(),y=read();
            change(1, 1, n, x, x+y-1, tag_unbook);
        }
    }
    return 0;
}

posted @ 2019-10-27 21:02  Santiego  阅读(203)  评论(0编辑  收藏  举报