题目链接
思路
用线段树维护三个最值
ms:在区间中连续最大的空房间数量
ls::在区间中左边连续的最大空房间的数量
rs:在区间中右边连续的嘴阀空房间的数量
- query
在询问的过程中,优先判断左儿子的空房间数量ms是否满足条件,这样能保证如果存在答案,答案总是最靠左的 - update
基本和带修的线段树的update函数一样
代码
//#pragma GCC optimize(2)
//#include<bits/stdc++.h>
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
typedef unsigned long ul;
typedef unsigned long long ull;
#define pi acos(-1.0)
#define e exp(1.0)
#define pb push_back
#define mk make_pair
#define fir first
#define sec second
#define scf scanf
#define prf printf
typedef pair<ll,ll> pa;
const int dir_4[4][2]={-1,0,0,1,1,0,0,-1};
const int dir_8[8][2]={-1,-1,-1,0,-1,1,0,1,1,1,1,0,1,-1,0,-1};
const ll INF=0x3f3f3f3f3f3f3f3f;
const int inf=0x3f3f3f3f;
const int maxn=5e5+7;//RE的话,尽量开大点
int N,M,lazy[maxn];//lazy:-1(没有标记),0(空房间),1(房间已用)
struct Node{
int l,r,ms,ls,rs;
Node(){}
Node(int l,int r,int ms,int ls,int rs):l(l),r(r),ms(ms),ls(ls),rs(rs){}
int len(){
return r-l+1;
}
int mid(){
return (l+r)>>1;
}
}node[maxn<<2];
void built(int l,int r,int rt){
int len=r-l+1;
node[rt]=Node(l,r,len,len,len);
lazy[rt]=-1;
if(l==r)
return ;
int mid=(l+r)>>1;
built(l,mid,rt<<1);
built(mid+1,r,rt<<1|1);
}
void up(int rt){
node[rt].ls=node[rt<<1].ls;
node[rt].rs=node[rt<<1|1].rs;
if(node[rt<<1].ls==node[rt<<1].len())
node[rt].ls+=node[rt<<1|1].ls;
if(node[rt<<1|1].rs==node[rt<<1|1].len())
node[rt].rs+=node[rt<<1].rs;
node[rt].ms=max(max(node[rt<<1].ms,node[rt<<1|1].ms),node[rt<<1].rs+node[rt<<1|1].ls);
return ;
}
void down(int rt){
if(lazy[rt]!=-1){
lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
if(lazy[rt]==0){
node[rt<<1].ms=node[rt<<1].ls=node[rt<<1].rs=node[rt<<1].len();
node[rt<<1|1].ms=node[rt<<1|1].ls=node[rt<<1|1].rs=node[rt<<1|1].len();
}
else{
node[rt<<1].ms=node[rt<<1].ls=node[rt<<1].rs=0;
node[rt<<1|1].ms=node[rt<<1|1].ls=node[rt<<1|1].rs=0;
}
lazy[rt]=-1;
}
return ;
}
void update(int l,int r,int va,int rt){
if(node[rt].l==l&&node[rt].r==r){
lazy[rt]=va;
if(va==0)
node[rt].ms=node[rt].ls=node[rt].rs=node[rt].len();
else
node[rt].ms=node[rt].ls=node[rt].rs=0;
return ;
}
if(node[rt].l!=node[rt].r)
down(rt);
int m=node[rt].mid();
if(r<=m)
update(l,r,va,rt<<1);
else if(l>m)
update(l,r,va,rt<<1|1);
else{
update(l,m,va,rt<<1);
update(m+1,r,va,rt<<1|1);
}
up(rt);
// cout<<"wodiu"<<endl;
}
int query(int x,int rt){
if(node[rt].l==node[rt].r)
return node[rt].l;
down(rt);
int m=node[rt].mid();
if(node[rt<<1].ms>=x)
return query(x,rt<<1);
else if(node[rt<<1].rs+node[rt<<1|1].ls>=x)
return m-node[rt<<1].rs+1;
else return query(x,rt<<1|1);
}
int main()
{
// freopen(".../.txt","w",stdout);
// freopen(".../.txt","r",stdin);
// ios::sync_with_stdio(false);
int i,j,k,op,x,y;
scf("%d%d",&N,&M);
built(1,N,1);
while(M--){
scf("%d%d",&op,&x);
if(op==2)
scf("%d",&y);
if(op==1){//有顾客租房子
if(node[1].ms<x){
prf("0\n");
}
else{
y=query(x,1);
prf("%d\n",y);
update(y,x+y-1,1,1);
}
}
else //有顾客退房子
update(x,x+y-1,0,1);
}
return 0;
}
/*
10 6
1 3
1 3
1 3
1 3
2 5 5
1 6
*/