POJ3667 Hotel(成段更新&&区间最值&&区间合并)

题目大意

给定N个连续的房间,最初的时候全部是空的,接下来m个操作,总共有一下两种操作:

1、 a:询问是不是有连续长度为a的空房间,有的话住进最左边
2 、a b:将[a,a+b-1]的房间清空

题解

基础的区间合并和覆盖问题,维护四个域:懒惰标记setv,区间最值maxv,从左端点开始的连续的最大房间数lmax,从右端点开始的连续的最大房间数rmax

主要就是要理解PushUp操作

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 50005
#define lson l,m,s<<1
#define rson m+1,r, s<<1|1
int maxv[MAXN<<2],setv[MAXN<<2],lmax[MAXN<<2],rmax[MAXN<<2];
void build(int l,int r,int s)
{
        maxv[s]=lmax[s]=rmax[s]=r-l+1;
        setv[s]=-1;
        if(l==r) return;
        int m=(l+r)>>1;
        build(lson);
        build(rson);
}
void PushUp(int s,int m)
{
        lmax[s]=lmax[s<<1];
        rmax[s]=rmax[s<<1|1];
        if(lmax[s<<1]==(m-(m>>1))) lmax[s]+=lmax[s<<1|1];
        if(rmax[s<<1|1]==(m>>1)) rmax[s]+=rmax[s<<1];
        maxv[s]=max(max(maxv[s<<1],maxv[s<<1|1]),rmax[s<<1]+lmax[s<<1|1]);
}
void PushDown(int s,int m)
{
        if(setv[s]!=-1) {
                setv[s<<1]=setv[s<<1|1]=setv[s];
                maxv[s<<1]=lmax[s<<1]=rmax[s<<1]=setv[s]?0:(m-(m>>1));
                maxv[s<<1|1]=lmax[s<<1|1]=rmax[s<<1|1]=setv[s]?0:(m>>1);
                setv[s]=-1;
        }
}
void update(int ql,int qr,int d,int l,int r,int s)
{
        if(ql<=l&&r<=qr) {
                maxv[s]=lmax[s]=rmax[s]=d?0:r-l+1;
                setv[s]=d;
                return;
        }
        PushDown(s,r-l+1);
        int m=(l+r)>>1;
        if(ql<=m) update(ql,qr,d,lson);
        if(qr>m) update(ql,qr,d,rson);
        PushUp(s,r-l+1);
}
int query(int p,int l,int r,int s)
{
        if(l==r) return l;
        PushDown(s,r-l+1);
        int m=(l+r)>>1;
        if(maxv[s<<1]>=p) return query(p,lson);
        else if((rmax[s<<1]+lmax[s<<1|1])>=p) return m-rmax[s<<1]+1;
        return query(p,rson);
}
int main(void)
{
        int n,m,a,b,c;
        scanf("%d%d",&n,&m);
        build(1,n,1);
        while(m--) {
                scanf("%d",&a);
                if(a==1) {
                        scanf("%d",&b);
                        if(maxv[1]<b) printf("0\n");
                        else {
                                c=query(b,1,n,1);
                                printf("%d\n",c);
                                update(c,c+b-1,1,1,n,1);
                        }
                } else {
                        scanf("%d%d",&b,&c);
                        update(b,b+c-1,0,1,n,1);
                }
        }
        return 0;
}

原文地址:https://www.cnblogs.com/zjbztianya/p/3114503.html