这个题跟3667类似,比3667更简单一些吧,题意仍是宾馆订房退房问题,有3种操作(1、以a号房间开始标记连续订b个房间。2、以a号房间开始连续退b个房间。3、查询当前最长的连续空房间数)
思路:用线段树做,对区间进行标记和删除操作
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=16100;
int n,m;
struct Tree
{
int l;
int r;
int resl;
int resr;
int resm;
int flag;
void Get()
{
resl=resr=resm=flag==0?r-l+1:0;
}
}t[maxn*3];
void Build(int l,int r,int index)
{
t[index].l=l;
t[index].r=r;
t[index].flag=0;
t[index].Get();
if(l==r)
return;
int mid=(l+r)>>1;
Build(l,mid,index<<1);
Build(mid+1,r,index<<1|1);
}
void pushdown(int index)
{
if(t[index].l==t[index].r||t[index].flag==-1)
return;
t[index<<1].flag=t[index<<1|1].flag=t[index].flag;
t[index].flag=-1;
t[index<<1].Get();
t[index<<1|1].Get();
}
void pushup(int index)
{
t[index].resm=max(t[index<<1].resr+t[index<<1|1].resl,max(t[index<<1].resm,t[index<<1|1].resm));
t[index].resl=t[index<<1].resm==t[index<<1].r-t[index].l+1?t[index<<1].resm+t[index<<1|1].resl:t[index<<1].resl;
t[index].resr=t[index<<1|1].resm==t[index<<1|1].r-t[index<<1|1].l+1?t[index<<1|1].resm+t[index<<1].resr:t[index<<1|1].resr;
}
void Update(int l,int r,int val,int index)
{
pushdown(index);
if(t[index].l==l&&t[index].r==r)
{
t[index].flag=val;
t[index].Get();
return;
}
int mid=(t[index].l+t[index].r)>>1;
if(r<=mid)
Update(l,r,val,index<<1);
else if(l>mid)
Update(l,r,val,index<<1|1);
else
{
Update(l,mid,val,index<<1);
Update(mid+1,r,val,index<<1|1);
}
pushup(index);
}
int main()
{
scanf("%d%d",&n,&m);
Build(1,n,1);
while(m--)
{
int op;
scanf("%d",&op);
if(op==1)
{
int a,b;
scanf("%d%d",&a,&b);
Update(a,a+b-1,1,1);
}
else if(op==2)
{
int a,b;
scanf("%d%d",&a,&b);
Update(a,a+b-1,0,1);
}
else
printf("%d\n",t[1].resm);
}
return 0;
}