用lmax记录从最左端边起的最长线段,rmax记录从最右端...,max记录整条线段中最长的线段,tag=-1表示无需更新,0表示空,1表示满。
由于 1 和 l 很像,找了很久才发现我query中写成了 l,mid写成了1,mid 。
下次学习大牛的写法 #define lson l,m,rt<<1 这样就不容易犯这种错误了。
#include<cstdio>
#include<iostream>
using namespace std;
#define lson rt<<1
#define rson rt<<1|1
const int N=50005;
struct node{
int lmax,rmax,max,tag;
}t[N*4];
void build(int l,int r,int rt){
t[rt].lmax=t[rt].rmax=t[rt].max=r-l+1;
t[rt].tag=-1;//-1无更新,0空房,1不空
if(l==r) return;
int mid=(l+r)/2;
build(l,mid,lson);
build(mid+1,r,rson);
}
void push_down(int rt,int len){
if(t[rt].tag!=-1){
t[lson].tag=t[rson].tag=t[rt].tag;
int left=t[rt].tag? 0:(len+1)/2;//左边个数
t[lson].lmax=t[lson].rmax=t[lson].max=left;
int right=t[rt].tag? 0:(len-(len+1)/2);//右边个数
t[rson].lmax=t[rson].rmax=t[rson].max=right;
t[rt].tag=-1;
}
}
int Max(int a,int b){
return a>b?a:b;
}
void push_up(int rt,int len){
t[rt].lmax=t[lson].lmax;
t[rt].rmax=t[rson].rmax;
if(t[rt].lmax==(len+1)/2)
t[rt].lmax+=t[rson].lmax;
if(t[rt].rmax==(len-(len+1)/2))
t[rt].rmax+=t[lson].rmax;
t[rt].max=Max(t[lson].rmax+t[rson].lmax,Max(t[lson].max,t[rson].max));
}
int query(int len,int l,int r,int rt){
push_down(rt,r-l+1);
int mid=(l+r)/2;
if(t[lson].max>=len)//左儿子够
return query(len,l,mid,lson);
else if(t[lson].rmax+t[rson].lmax>=len)//中间
return mid-t[lson].rmax+1;
else if(t[rson].max>=len)//右儿子够
return query(len,mid+1,r,rson);
return 0;
}
void update(int a,int b,int c,int l,int r,int rt){
if(a<=l&&b>=r){
t[rt].tag=c;
int full=c? 0:r-l+1;
t[rt].lmax=t[rt].rmax=t[rt].max=full;
return;
}
push_down(rt,r-l+1);
int mid=(l+r)/2;
if(a<=mid)
update(a,b,c,l,mid,lson);
if(b>mid)
update(a,b,c,mid+1,r,rson);
push_up(rt,r-l+1);
}
int main(){
int n,m;
while(cin>>n>>m){
build(1,n,1);
int op,x,len;
for(int i=0;i<m;i++){
scanf("%d",&op);
if(op==1){
scanf("%d",&len);
int k=query(len,1,n,1);
printf("%d\n",k);
if(k!=0)
update(k,k+len-1,1,1,n,1);
}
else{//删除一段
scanf("%d %d",&x,&len);
update(x,x+len-1,0,1,n,1);
}
}
}
return 0;
}