定义
计 0 为空房间,1 为有人的房间,[lx,rx]为当前线段树区间
定义线段树记录一下内容——
1. k0,[lx,rx]中连续最大空房间数量
2. l0,[lx,rx]中从左往右连续的空房间数量
3. r0,[lx,rx]中从右往左连续的空房间数量
pushup(int x)
pushup 时按照以下方式合并
对于K0——
1. 可以是lson.k0,
2. 也可以是rson.k0,
3. 还可能是lson.r0+rson.l0。
对于L0——
1. L0=lson.l0
2. 若lson.l0=lson.len,则L0=lson.len+rson.l0
对于R0——
1. R0=rson.r0
2. 若rson.r0=rson.len,则R0=rson.llen+lson.r0
pushdown
定义 tag 为线段树节点的 lazy_tag
1. tag=-1 时,不下传
2. tag!=-1 时,表示是下传全空还是全满
3.
void pushdown(int x){
if(tree[x].tag==-1)return;
if(tree[x].tag){
tree[ls(x)].k0=tree[ls(x)].l0=tree[ls(x)].r0=0;
tree[rs(x)].k0=tree[rs(x)].l0=tree[rs(x)].r0=0;
tree[ls(x)].tag=tree[rs(x)].tag=1;
}
else{
tree[ls(x)].k0=tree[ls(x)].l0=tree[ls(x)].r0=(tree[ls(x)].r-tree[ls(x)].l+1);
tree[rs(x)].k0=tree[rs(x)].l0=tree[rs(x)].r0=(tree[rs(x)].r-tree[rs(x)].l+1);
tree[ls(x)].tag=tree[rs(x)].tag=0;
}
tree[x].tag=-1;
return;
}
query
权值线段树的思想走
int query(int x,int len){
if(tree[x].k0<len)return 0;
if(tree[x].l==tree[x].r)return tree[x].l;
pushdown(x);
if(tree[ls(x)].k0>=len)return query(ls(x),len);
if(tree[ls(x)].r0+tree[rs(x)].l0>=len)return tree[ls(x)].r-tree[ls(x)].r0+1;
return query(rs(x),len);
}
Code
#include<bits/stdc++.h>
#define ls(x) ((x)<<1)
#define rs(x) ((x)<<1|1)
using namespace std;
const int MAXN=50000;
int n,m;
struct Node{
int k0,l0,r0,l,r,tag;
}tree[MAXN*4+1];
void pushup(int x){
int mid=tree[x].l+tree[x].r;mid>>=1;
tree[x].k0=max({tree[ls(x)].k0,tree[rs(x)].k0,tree[ls(x)].r0+tree[rs(x)].l0});
tree[x].l0=max(tree[ls(x)].l0,(tree[ls(x)].l0+tree[rs(x)].l0)*(mid-tree[x].l+1==tree[ls(x)].l0));
tree[x].r0=max(tree[rs(x)].r0,(tree[rs(x)].r0+tree[ls(x)].r0)*(tree[x].r-mid==tree[rs(x)].r0));
return;
}
void pushdown(int x){
if(tree[x].tag==-1)return;
if(tree[x].tag){
tree[ls(x)].k0=tree[ls(x)].l0=tree[ls(x)].r0=0;
tree[rs(x)].k0=tree[rs(x)].l0=tree[rs(x)].r0=0;
tree[ls(x)].tag=tree[rs(x)].tag=1;
}
else{
tree[ls(x)].k0=tree[ls(x)].l0=tree[ls(x)].r0=(tree[ls(x)].r-tree[ls(x)].l+1);
tree[rs(x)].k0=tree[rs(x)].l0=tree[rs(x)].r0=(tree[rs(x)].r-tree[rs(x)].l+1);
tree[ls(x)].tag=tree[rs(x)].tag=0;
}
tree[x].tag=-1;
return;
}
void build(int x,int lx,int rx){
tree[x].l=lx,tree[x].r=rx;tree[x].tag=-1;
if(lx==rx){
tree[x].k0=tree[x].l0=tree[x].r0=1;
return;
}
build(ls(x),lx,(lx+rx)/2);
build(rs(x),(lx+rx)/2+1,rx);
pushup(x);
return;
}
void change(int x,int L,int R,int d){
if(L<=tree[x].l&&tree[x].r<=R){
tree[x].tag=d;
tree[x].k0=tree[x].l0=tree[x].r0=(d?0:(tree[x].r-tree[x].l+1));
return;
}
pushdown(x);
int mid=(tree[x].l+tree[x].r)>>1;
if(L<=mid)change(ls(x),L,R,d);
if(R>mid)change(rs(x),L,R,d);
pushup(x);
return;
}
int query(int x,int len){
if(tree[x].k0<len)return 0;
if(tree[x].l==tree[x].r)return tree[x].l;
pushdown(x);
if(tree[ls(x)].k0>=len)return query(ls(x),len);
if(tree[ls(x)].r0+tree[rs(x)].l0>=len)return tree[ls(x)].r-tree[ls(x)].r0+1;
return query(rs(x),len);
}
int main(){
scanf("%d%d",&n,&m);
build(1,1,n);
while(m--){
int op;scanf("%d",&op);
if(op==2){
int x,d;scanf("%d%d",&x,&d);
change(1,x,x+d-1,0);
}
else{
int d;scanf("%d",&d);
int ans=query(1,d);
printf("%d\n",ans);
if(!ans)continue;
change(1,ans,ans+d-1,1);
}
}
return 0;
}