以前学习过的线段树,在查询和更新的基础上加入了区间合并,利用延迟标志来实现这一方法
代码在这:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=50050;
struct node
{
int l,r;
int mk;
int ls,rs,ms;
}tree[N*10];
int n,m;
int x,y,a,b;
void pushup(int i)
{
int ll=tree[i*2].r-tree[i*2].l+1;
int rr=tree[i*2+1].r-tree[i*2+1].l+1;
tree[i].ls=tree[i*2].ls;
if(tree[i*2].ls==ll) tree[i].ls+=tree[i*2+1].ls;
tree[i].rs=tree[i*2+1].rs;
if(tree[i*2+1].rs==rr) tree[i].rs+=tree[i*2].rs;
tree[i].ms=max(max(tree[i*2].ms,tree[i*2+1].ms),tree[i*2].rs+tree[i*2+1].ls);
}
void buildtree(int i,int l,int r)
{
tree[i].l=l;
tree[i].r=r;
tree[i].mk=-1;
tree[i].ls=tree[i].rs=tree[i].ms=r-l+1;
if(l==r) return;
buildtree(i*2,l,(l+r)/2);
buildtree(i*2+1,(l+r)/2+1,r);
pushup(i);
}
void pushdown(int i)
{
if(tree[i].mk!=-1)
{
int ll=tree[i*2].r-tree[i*2].l+1;
int rr=tree[i*2+1].r-tree[i*2+1].l+1;
tree[i*2].mk=tree[i*2+1].mk=tree[i].mk;
tree[i].mk=-1;
tree[i*2].ls=tree[i*2].rs=tree[i*2].ms=tree[i*2].mk?0:ll;
tree[i*2+1].ls=tree[i*2+1].rs=tree[i*2+1].ms=tree[i*2+1].mk?0:rr;
}
}
void updata(int i,int l,int r,int c)
{
if(tree[i].l==l&&tree[i].r==r)
{
tree[i].ms=tree[i].ls=tree[i].rs=c?0:(r-l+1);
tree[i].mk=c;
return;
}
pushdown(i);
int m=(tree[i].r+tree[i].l)/2;
if(r<=m) updata(i*2,l,r,c);
else if(l>m) updata(i*2+1,l,r,c);
else
{
updata(i*2,l,m,c);
updata(i*2+1,m+1,r,c);
}
pushup(i);
}
int query(int i,int a)
{
if(tree[i].l==tree[i].r) return tree[i].l;
pushdown(i);
int m=(tree[i].r+tree[i].l)/2;
if(tree[i*2].ms>=a) return query(i*2,a);
if((tree[i*2].rs+tree[i*2+1].ls)>=a) return m-tree[i*2].rs+1;
return query(i*2+1,a);
}
int main()
{
scanf("%d%d",&n,&m);
buildtree(1,1,n);
while(m--)
{
scanf("%d",&x);
if(x==1)
{
scanf("%d",&y);
if(tree[1].ms<y) printf("0\n");
else
{
int yy=query(1,y);
printf("%d\n",yy);
updata(1,yy,yy+y-1,1);
}
}
else if(x==2)
{
scanf("%d%d",&a,&b);
updata(1,a,a+b-1,0);
}
}
return 0;
}