这是典型的线段树区间合并。知道lazy标记的同学比较好懂一点,这其中就用到了lazy标记。话不多说,上代码
#include <iostream>
#include <stdio.h>
#include<algorithm>
using namespace std;
const int MAX=5*1e4+10;
int M,N,a,b,c;
typedef struct
{
int lnum,rnum,mnum;
int cover,left,right;
}P;
P p[4*MAX];
void pushup(int k)
{
int lm=k<<1,rm=lm+1,llen=p[lm].right-p[lm].left+1,rlen=p[rm].right-p[rm].left+1;
if(p[lm].lnum==llen)
p[k].lnum=llen+p[rm].lnum;
else
p[k].lnum=p[lm].lnum;
if(p[rm].rnum==rlen)
p[k].rnum=p[lm].rnum+rlen;
else
p[k].rnum=p[rm].rnum;
p[k].mnum=max(max(max(p[k].lnum,p[k].rnum),p[lm].mnum),p[rm].mnum);
p[k].mnum=max(p[lm].rnum+p[rm].lnum,p[k].mnum);
}
void pushdown(int k)
{
if(p[k].cover!=-1)//不用一次更新完此结点下所有的节点,类似于lazy标记
{
int lt=k<<1,rt=lt+1;
p[lt].cover=p[rt].cover=p[k].cover;
p[k].cover=-1;
int ll=p[lt].right-p[lt].left+1,rr=p[rt].right-p[rt].left+1;
p[lt].rnum=p[lt].lnum=p[lt].mnum=p[lt].cover?0:ll;
p[rt].rnum=p[rt].lnum=p[rt].mnum=p[rt].cover?0:rr;
}
}
void build(int k,int l,int r)
{
p[k].left=l;
p[k].right=r;
p[k].cover=-1;
p[k].lnum=p[k].rnum=p[k].mnum=r-l+1;
if(l==r)
return;
int lm=k<<1,rm=lm+1,mid=(l+r)>>1;
build(lm,l,mid);
build(rm,mid+1,r);
pushup(k);
}
void update(int st,int ed,int co,int k)
{
if(p[k].left==st&&p[k].right==ed)
{
p[k].lnum=p[k].rnum=p[k].mnum=co?0:p[k].right-p[k].left+1;
p[k].cover=co;
return;
}
pushdown(k);
int mid=(p[k].left+p[k].right)>>1;
if(mid>=ed)
update(st,ed,co,k<<1);
else
if(st>mid)
update(st,ed,co,k<<1|1);
else
{
update(st,mid,co,k<<1);
update(mid+1,ed,co,k<<1|1);
}
pushup(k);
}
int query(int k,int len)
{
pushdown(k);
if(p[k<<1].mnum>=len)
return query(k<<1,len);
else
if(p[k<<1].rnum+p[k<<1|1].lnum>=len)
return p[k<<1].right-p[k<<1].rnum+1;
return query(k<<1|1,len);
}
int main()
{
scanf("%d%d",&N,&M);
build(1,1,N);
for(int i=0;i<M;i++)
{
scanf("%d%d",&a,&b);
if(a==1)
{//printf("%d\n",p[1].mnum);
if(p[1].mnum<b)
printf("0\n");
else
{
int st=query(1,b);
printf("%d\n",st);
update(st,st+b-1,1,1);
}
}
else
{
scanf("%d",&c);
update(b,b+c-1,0,1);
}
}
return 0;
}