链接:点击打开链接
给定N个连续的房间,最初的时候全部是空的,接下来m个操作,总共有一下两种操作:
1、 a:询问是不是有连续长度为a的空房间,有的话住进最左边
2 、a b:将[a,a+b-1]的房间清空
基础的区间合并和覆盖问题,维护四个域:懒惰标记setv,区间最值maxv,从左端点开始的连续的最大房间数lmax,从右端点开始的连续的最大房间数rmax
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 50010
#define lson l,mid,n<<1
#define rson mid+1,r,n<<1|1
int sum[N<<2],lsum[N<<2],rsum[N<<2],cover[N<<2];
//int MAX(int a,int b){
// return a>b?a:b;
// }
void bulid(int l,int r,int n){
int mid;
mid=(l+r)>>1;
cover[n]=-1;
sum[n]=lsum[n]=rsum[n]=r-l+1;
if(l==r)
return;
bulid(lson);
bulid(rson);
}
void pushdown(int n,int k){
if(cover[n]!=-1){
cover[n<<1]=cover[n<<1|1]=cover[n];
lsum[n<<1]=rsum[n<<1]=sum[n<<1]=cover[n]?0:(k-(k>>1));
lsum[n<<1|1]=rsum[n<<1|1]=sum[n<<1|1]=cover[n]?0:(k>>1);
cover[n]=-1;
}
}
void pushup(int n,int k){
lsum[n]=lsum[n<<1];
rsum[n]=rsum[n<<1|1];
if(lsum[n<<1]==(k-(k>>1)))
lsum[n]+=lsum[n<<1|1];
if(rsum[n<<1|1]==(k>>1))
rsum[n]+=rsum[n<<1];
sum[n]=max(rsum[n<<1]+lsum[n<<1|1],max(sum[n<<1],sum[n<<1|1]));
}
int query(int w,int l,int r,int n){
if(l==r)
return 1;
pushdown(n,r-l+1);
int mid=(l+r)>>1;
if(sum[n<<1]>=w)
return query(w,lson);
else if(rsum[n<<1]+lsum[n<<1|1]>=w)
return mid-rsum[n<<1]+1;
//else
return query(w,rson);
}
void update(int L,int R,int c,int l,int r,int n){
if(L<=l&&r<=R){
lsum[n]=rsum[n]=sum[n]=c?0:r-l+1;
cover[n]=c;
return;
}
pushdown(n,r-l+1);
int mid=(l+r)>>1;
if(L<=mid)
update(L,R,c,lson);
if(R>mid)
update(L,R,c,rson);
pushup(n,r-l+1);
}
int main(){
int n,m,a,b,c,d;
scanf("%d %d",&n,&m);
bulid(1,n,1);
while(m--){
scanf("%d",&a);
if(a==1){
scanf("%d",&b);
if(sum[1]<b)
printf("0\n");
else{
d=query(b,1,n,1);
printf("%d\n",d);
update(d,d+b-1,1,1,n,1);
}
}
else{
scanf("%d %d",&c,&d);
update(c,d+c-1,0,1,n,1);
}
}
return 0;
}