题意:n个房间,可以进行
操作1(插入连续的x个人,并输出这批人占据的第一个房间号,如果放不下,输出0);
操作2(从第x个房间开始,连续清空y个房间)。
思路:区间更新
AC代码:
#include<iostream>
#include<cstdio>
using namespace std;
struct node
{
int l,r,cover;//cover记录是否有人 -1,0,1
int s,e,n;// 表示左端点起最大长度,右端点起最大长度,整个区间最大长度
}hotel[200000];
void Push_Up(int l,int r,int rt) // 想父节点更新;
{
hotel[rt].s=hotel[rt<<1].s;
hotel[rt].e=hotel[rt<<1|1].e;
int mid=(l+r)>>1;
if(hotel[rt].s==mid-l+1) hotel[rt].s+=hotel[rt<<1|1].s;
if(hotel[rt].e==r-mid) hotel[rt].e+=hotel[rt<<1].e;
hotel[rt].n=max(max(hotel[rt<<1].n,hotel[rt<<1|1].n),hotel[rt<<1].e+hotel[rt<<1|1].s);
}
void down(int k)
{
if(hotel[k].cover!=-1)//不等于-1表示需要向下更新
{
hotel[k*2].cover=hotel[k*2+1].cover=hotel[k].cover;
if(hotel[k].cover) //如果等于1,说明将区间标记为0,即表示住人;
{
hotel[k*2].s=hotel[k*2].e=hotel[k*2].n=0;
hotel[k*2+1].s=hotel[1+k*2].e=hotel[1+k*2].n=0;
}
else//如果为0
{
hotel[k*2].s=hotel[k*2].e=hotel[k*2].n=hotel[k*2].r-hotel[k*2].l+1;
hotel[k*2+1].s=hotel[1+k*2].e=hotel[1+k*2].n=hotel[k*2+1].r-hotel[k*2+1].l+1;
}
hotel[k].cover=-1;//已更新,清零
}
}
void build(int s,int e,int k)
{
hotel[k].l=s;
hotel[k].r=e;
hotel[k].cover=-1;//将所有cover记为无人
hotel[k].s=hotel[k].e=hotel[k].n=e-s+1;//定义区间的左起、右起 、整个区间长度
if(s==e) return;
int m=(s+e)/2;
build(s,m,k*2);
build(m+1,e,k*2+1);
}
int query(int s,int e,int v,int k)
{
if(s==e) return s;
int m=(s+e)/2;
down(k);
if(hotel[k*2].n>=v) return query(s,m,v,k*2);//如果左枝的房间足够,查询左枝即可
else if(hotel[k*2].e+hotel[k*2+1].s>=v) return m-hotel[k*2].e+1;//或者左枝的右起加右枝的左起足够,返回左枝的点
else return query(m+1,e,v,k*2+1);//否则查询右枝
}
void update(int s,int e,int num,int k)
{
int l=hotel[k].l;
int r=hotel[k].r;
if(l==s&&r==e)
{
hotel[k].cover=num;
if(num) hotel[k].s=hotel[k].e=hotel[k].n=0;
else hotel[k].s=hotel[k].e=hotel[k].n=e-s+1;
return;
}
down(k);
int m=(l+r)/2;
if(e<=m) update(s,e,num,k<<1);
else if(s>m) update(s,e,num,k<<1|1);
else{
update(s,m,num,k<<1);
update(m+1,e,num,k<<1|1);
}
Push_Up(hotel[k].l,hotel[k].r,k);
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);//输入总房间数和样例个数
build(1,n,1);//建立房间
while(m--)
{
int k,a,b;
scanf("%d%d",&k,&a);
if(k==1)
{
if(hotel[1].n<a) printf("0\n");//如果总的剩余房间数小于a
else
{
b=query(1,n,a,1);//找到第一个没住人的房间号
printf("%d\n",b);
update(b,b+a-1,1,1);//把人安排进去(置一)
}
}
else
{
scanf("%d",&b);
update(a,a+b-1,0,1);//把人请出去(置〇)
}
}
return 0;
}