线段树 区间更新
1 x 求最左的x个连续空房间,输出左端点,并将区间更新为1,没有满足条件的则输出0
2 x,y 更新区间[x,y]的所有值为0
sum区间最长连续0串
lsum区间左端最长连续0串
rsum区间右端最长连续0串
sum[rt]=max(sum[lson],sum[rson],rson[lson]+lson[rson])
求左端点的时候
1.sum[lson]>=d,求左儿子>=d连续0串的左端点
2.rsum[lson]+lsum[rson],m-rsum[lson]-1;
3.求右儿子>=d连续0串的左端点
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define N 50005
using namespace std;
int lsum[N<<2],rsum[N<<2],sum[N<<2];
int cover[N<<2];
void pushup(int rt,int m){
lsum[rt]=lsum[rt<<1];
rsum[rt]=rsum[rt<<1|1];
sum[rt]=max(max(sum[rt<<1],sum[rt<<1|1]),rsum[rt<<1]+lsum[rt<<1|1]);
if(lsum[rt<<1]==m-(m>>1))
lsum[rt]+=lsum[rt<<1|1];
if(rsum[rt<<1|1]==(m>>1))
rsum[rt]+=rsum[rt<<1];
}
void pushdown(int rt,int m){
if(cover[rt]!=-1){
cover[rt<<1]=cover[rt<<1|1]=cover[rt];
sum[rt<<1]=lsum[rt<<1]=rsum[rt<<1]=cover[rt]*(m-(m>>1));
sum[rt<<1|1]=lsum[rt<<1|1]=rsum[rt<<1|1]=cover[rt]*(m>>1);
cover[rt]=-1;
}
}
void build(int l,int r,int rt){
cover[rt]=-1;
lsum[rt]=rsum[rt]=sum[rt]=r-l+1;
if(l==r)
return;
int m=(l+r)>>1;
build(lson);
build(rson);
}
void update(int L,int R,int c,int l,int r,int rt){
if(L<=l&&R>=r){
sum[rt]=lsum[rt]=rsum[rt]=c*(r-l+1);
cover[rt]=c;
return ;
}
pushdown(rt,r-l+1);
int m=(l+r)>>1;
if(L<=m)
update(L,R,c,lson);
if(R>m)
update(L,R,c,rson);
pushup(rt,r-l+1);
}
int query(int d,int l,int r,int rt){
if(l==r)
return l;
pushdown(rt,r-l+1);
int m=(l+r)>>1;
if(sum[rt<<1]>=d)
return query(d,lson);
else
if(rsum[rt<<1]+lsum[rt<<1|1]>=d)
return m-rsum[rt<<1]+1;
return query(d,rson);
}
int main()
{
int n,m,x,y,op;
while(~scanf("%d%d",&n,&m)){
build(1,n,1);
while(m--){
scanf("%d",&op);
if(op==1){
scanf("%d",&x);
if(sum[1]<x)
printf("0\n");
else {
int p=query(x,1,n,1);
printf("%d\n",p);
update(p,p+x-1,0,1,n,1);
}
}else {
scanf("%d%d",&x,&y);
update(x,x+y-1,1,1,n,1);
}
}
}
return 0;
}