线段树——讲课用——最长连续空位

题目链接:https://www.luogu.org/problemnew/show/P2894

题意:

酒店n个房间,m个操作:入住或退房

如果操作为入住,同一批客人安排的房间号必须连续

操作1:有x个客人要入住,输出满足条件的最小的房间编号,若不满足条件输出0

操作2:房间为[x,y]的客人要退房

 

题解:

如果你会了第一题(BSS),这题就简单了

题意转化:询问最长连续空位位置,带修改

如果没有操作2,把每个房间权值看成1,就变成了BSS问题,不过输出的是左端点位置

操作2仅是一个区间修改罢了

 

#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

#define N 50000

int n,m;

int mx[N<<2|1],lmx[N<<2|1],rmx[N<<2|1];
int f[N<<2|1],siz[N<<2|1];

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
}

void build(int k,int l,int r)
{
     siz[k]=mx[k]=lmx[k]=rmx[k]=r-l+1;
     f[k]=-1;
     if(l==r) return;
     int mid=l+r>>1;
     build(k<<1,l,mid);
     build(k<<1|1,mid+1,r);
}

void down(int k,int l,int r)
{
    int L=k<<1,R=k<<1|1;
    if(f[k]) mx[L]=lmx[L]=rmx[L]=mx[R]=lmx[R]=rmx[R]=0;
    else 
    {
        mx[L]=lmx[L]=rmx[L]=siz[L];
        mx[R]=lmx[R]=rmx[R]=siz[R];
    }
    f[L]=f[R]=f[k];
    f[k]=-1;
}

int query(int k,int l,int r,int len)
{
    if(l==r) return l;
    if(f[k]!=-1) down(k,l,r); 
    int mid=l+r>>1;
    if(mx[k<<1]>=len) return query(k<<1,l,mid,len);
    if(rmx[k<<1]+lmx[k<<1|1]>=len) return mid-rmx[k<<1]+1;
    return query(k<<1|1,mid+1,r,len);
}

void up(int k)
{
    int L=k<<1,R=k<<1|1;
    mx[k]=max(mx[L],mx[R]);
    mx[k]=max(mx[k],rmx[L]+lmx[R]);
    if(mx[L]==siz[L]) lmx[k]=mx[L]+lmx[R];
    else lmx[k]=lmx[L];
    if(mx[R]==siz[R]) rmx[k]=mx[R]+rmx[L];
    else rmx[k]=rmx[R];
}

void change(int k,int l,int r,int opl,int opr,int in)
{
    if(l>=opl && r<=opr)
    {
        f[k]=in;
        if(!in) mx[k]=lmx[k]=rmx[k]=r-l+1;
        else mx[k]=lmx[k]=rmx[k]=0;
        return;
    }
    if(f[k]!=-1) down(k,l,r);
    int mid=l+r>>1;
    if(opl<=mid) change(k<<1,l,mid,opl,opr,in);
    if(opr>mid) change(k<<1|1,mid+1,r,opl,opr,in);
    up(k); 
}

void init()
{
    read(n); read(m);
    build(1,1,n);
    int opt,x,y;
    while(m--)
    {
        read(opt);
        if(opt==1) 
        {
            read(x);
            if(mx[1]<x) printf("0\n");
            else
            {
                y=query(1,1,n,x);
                printf("%d\n",y);
                change(1,1,n,y,y+x-1,1);
            }
        }
        else
        {
            read(x); read(y);
            change(1,1,n,x,x+y-1,0);
        }
    }
    
}

int main()
{
    init();
    return 0;
}

 

posted @ 2019-07-05 21:32  TRTTG  阅读(328)  评论(0编辑  收藏  举报