比较经典的题目,题目中有两种成段覆盖的方式,因此在节点设置两个标记cover(房间清空),set(房间注满)。
再每个节点设置一个sum表示区间最长连续空房间。
然后设置lsum表示包括最左边房间的最长连续空房间,rsum表示包括最右边房间的最长连续空房间。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define lc l,m,index<<1
#define rc m+1,r,index<<1|1
#define N 50005
struct node
{
int cover;
int set;
int sum;
int lsum,rsum;
}seg[N<<2];
int n,q;
void fcover(int l,int r,int index)
{
seg[index].cover=1;
seg[index].set=0;
seg[index].sum=seg[index].lsum=seg[index].rsum=r-l+1;
}
void fset(int l,int r,int index)
{
seg[index].cover=0;
seg[index].set=1;
seg[index].sum=seg[index].lsum=seg[index].rsum=0;
}
void pushup(int l,int r,int index)
{
int m=(l+r)>>1;
node& father=seg[index];
node& lson=seg[index<<1];
node& rson=seg[index<<1|1];
father.lsum=lson.lsum;
father.rsum=rson.rsum;
father.sum=max(lson.sum,rson.sum);
father.sum=max(father.sum,lson.rsum+rson.lsum);
if(lson.lsum==m-l+1)father.lsum+=rson.lsum;
if(rson.rsum==r-m)father.rsum+=lson.rsum;
}
void pushdown(int l,int r,int index)
{
int m=(l+r)>>1;
node& father=seg[index];
node& lson=seg[index<<1];
node& rson=seg[index<<1|1];
if(father.cover)
{
fcover(lc);
fcover(rc);
father.cover=0;
}
if(father.set)
{
fset(lc);
fset(rc);
father.set=0;
}
}
void build(int l,int r,int index)
{
seg[index].cover=seg[index].set=0;
seg[index].sum=seg[index].lsum=seg[index].rsum=r-l+1;
int m=(l+r)>>1;
if(l==r)return;
build(lc);
build(rc);
}
void updataset(int L,int R,int l,int r,int index)
{
if(L==l&&R==r)
{
fset(l,r,index);
return;
}
pushdown(l,r,index);
int m=(l+r)>>1;
if(R<=m)updataset(L,R,lc);
else if(L>m)updataset(L,R,rc);
else
{
updataset(L,m,lc);
updataset(m+1,R,rc);
}
pushup(l,r,index);
}
void updatacover(int L,int R,int l,int r,int index)
{
if(L==l&&R==r)
{
fcover(l,r,index);
return;
}
pushdown(l,r,index);
int m=(l+r)>>1;
if(R<=m)updatacover(L,R,lc);
else if(L>m)updatacover(L,R,rc);
else
{
updatacover(L,m,lc);
updatacover(m+1,R,rc);
}
pushup(l,r,index);
}
int query(int id,int l,int r,int index)
{
if(l==r)return l;
pushdown(l,r,index);
int m=(l+r)>>1;
if(seg[index<<1].sum>=id)return query(id,lc);
else if(seg[index<<1].rsum+seg[index<<1|1].lsum>=id)return m-seg[index<<1].rsum+1;
else return query(id,rc);
}
int main()
{
int op,a,b;
while(scanf("%d%d",&n,&q)!=EOF)
{
build(1,n,1);
while(q--)
{
scanf("%d%d",&op,&a);
if(op==1)
{
if(seg[1].sum<a)puts("0");
else
{
b=query(a,1,n,1);
printf("%d\n",b);
updataset(b,b+a-1,1,n,1);
}
}
else
{
scanf("%d",&b);
updatacover(a,a+b-1,1,n,1);
}
}
}
return 0;
}