题目链接:http://poj.org/problem?id=3667
思路:线段树的区间合并,lm表示该区间从左边开始最大的空区间,mm表示该区间最大的空区间,rm表示从右边数最大的空区间
注意向下更新
#include<cstdio>
#include<cstring>
using namespace std;
const int N=50005;
struct node
{
int l,r,lm,rm,mm;
}d[N<<3];
int max(int a,int b)
{
if(a>=b)
return a;
return b;
}
void pushup(int rt)
{
if(d[rt].l==d[rt].r)
return;
d[rt].mm=max(d[rt<<1].mm,max(d[rt<<1|1].mm,d[rt<<1].rm+d[rt<<1|1].lm));
int len=d[rt<<1].r-d[rt<<1].l+1;
if(d[rt<<1].lm==len)
d[rt].lm=len+d[rt<<1|1].lm;
else
d[rt].lm=d[rt<<1].lm;
len=d[rt<<1|1].r-d[rt<<1|1].l+1;
if(d[rt<<1|1].lm==len)
d[rt].rm=d[rt<<1].rm+len;
else
d[rt].rm=d[rt<<1|1].rm;
}
void pushdown(int rt)
{
if(d[rt].l==d[rt].r)
return ;
if(d[rt].mm==0)
{
d[rt<<1].mm=d[rt<<1|1].mm=0;
d[rt<<1].lm=d[rt<<1|1].lm=0;
d[rt<<1].rm=d[rt<<1|1].rm=0;
}
else
{
d[rt<<1].mm=d[rt<<1].lm=d[rt<<1].rm=d[rt<<1].r-d[rt<<1].l+1;
d[rt<<1|1].mm=d[rt<<1|1].lm=d[rt<<1|1].rm=d[rt<<1|1].r-d[rt<<1|1].l+1;
}
}
void build(int rt,int L,int R)
{
d[rt].l=L;
d[rt].r=R;
d[rt].lm=d[rt].rm=d[rt].mm=(R-L)+1;
if(L==R)
return ;
int mid=(L+R)>>1;
build(rt<<1,L,mid);
build(rt<<1|1,mid+1,R);
}
void updata(int rt,int L,int R,int a)
{
if(d[rt].l==L&&d[rt].r==R)
{
if(a==0)
d[rt].mm=d[rt].lm=d[rt].rm=R-L+1;
else if(a==1)
d[rt].mm=d[rt].lm=d[rt].rm=0;
return ;
}
int len=d[rt].r-d[rt].l+1;
if((d[rt].mm==0&&d[rt].lm==0&&d[rt].rm==0)||(d[rt].mm==len&&d[rt].lm==len&&d[rt].rm==len))
pushdown(rt);
int mid=(d[rt].l+d[rt].r)>>1;
if(R<=mid)
updata(rt<<1,L,R,a);
else if(L>mid)
updata(rt<<1|1,L,R,a);
else
{
updata(rt<<1,L,mid,a);
updata(rt<<1|1,mid+1,R,a);
}
pushup(rt);
}
int query(int rt,int L)
{
int ans;
if(d[rt].lm>=L)
return d[rt].l;
else if(d[rt].mm>=L)
{
ans=query(rt<<1,L);
if(ans!=0)
return ans;
if(d[rt<<1].rm+d[rt<<1|1].lm>=L)
return d[rt<<1].r-d[rt<<1].rm+1;
ans=query(rt<<1|1,L);
if(ans!=0)
return ans;
}
else if(d[rt].rm>=L)
return d[rt].r-d[rt].rm+1;
return 0;
}
int main()
{
int n,m,p,b,c,st;
//freopen("in.txt","r",stdin);
while(scanf("%d%d",&n,&m)!=EOF)
{
build(1,1,n);
while(m--)
{
scanf("%d",&p);
if(p==1)
{
scanf("%d",&b);
st=query(1,b);
printf("%d\n",st);
if(st)
updata(1,st,st+b-1,1);
}
else if(p==2)
{
scanf("%d%d",&b,&c);
updata(1,b,b+c-1,0);
}
}
}
return 0;
}