题目意思很简洁,就是多次查询连续空段n的最靠左区间,并覆盖,或者把某段变成空。
用线段树维护三个参数,lmaxn,rmax,max分别表示靠左最长连续,靠右最长连续,最长连续。
修改时,父节点的三个参数都能从子节点参数求得(具体看代码),查询时,也能由子节点和父节点的三个参数递归的得到解答。这个过程不是太好讲明白,得自己想,具体的看代码。
#include <iostream>
#include <stdio.h>
#include <string.h>
#define ls t<<1
#define rs t<<1|1
#define midt (tr[t].l+tr[t].r)>>1
using namespace std;
const int maxn=50000+10;
struct
{
int l,r;
int lmax,rmax,max;
int lazy;
}tr[maxn*4];
void maketree(int t,int l,int r)
{
tr[t].l=l;
tr[t].r=r;
tr[t].lmax=tr[t].rmax=tr[t].max=(r-l+1);
tr[t].lazy=0;
if(l==r) return;
int mid=midt;
maketree(ls,l,mid);
maketree(rs,mid+1,r);
}
void pushdown(int t)
{
if(tr[t].lazy==1)
{
tr[ls].lmax=tr[ls].rmax=tr[ls].max=tr[ls].r-tr[ls].l+1;
tr[ls].lazy=tr[t].lazy;
tr[rs].lmax=tr[rs].rmax=tr[rs].max=tr[rs].r-tr[rs].l+1;
tr[rs].lazy=tr[t].lazy;
}
else
{
tr[ls].lmax=tr[ls].rmax=tr[ls].max=0;
tr[ls].lazy=tr[t].lazy;
tr[rs].lmax=tr[rs].rmax=tr[rs].max=0;
tr[rs].lazy=tr[t].lazy;
}
tr[t].lazy=0;
}
void modify(int t,int l,int r,int tmp)
{
//
printf("%d %d %d\n",t,tr[t].l,tr[t].r);
if(l==tr[t].l&&r==tr[t].r)
{
tr[t].lazy=tmp;
if(tmp==1)
tr[t].lmax=tr[t].rmax=tr[t].max=(r-l+1);
else
tr[t].lmax=tr[t].rmax=tr[t].max=0;
return;
}
if(tr[t].lazy)
pushdown(t);
int mid=midt;
if(r<=mid)
modify(ls,l,r,tmp);
else if(mid+1<=l)
modify(rs,l,r,tmp);
else
{
modify(ls,l,mid,tmp);
modify(rs,mid+1,r,tmp);
}
tr[t].max=max(tr[ls].max,tr[rs].max);
tr[t].max=max(tr[t].max,tr[ls].rmax+tr[rs].lmax);
tr[t].lmax=tr[ls].lmax;
tr[t].rmax=tr[rs].rmax;
if(tr[ls].lmax==(tr[ls].r-tr[ls].l+1))
tr[t].lmax+=tr[rs].lmax;
if(tr[rs].rmax==(tr[rs].r-tr[rs].l+1))
tr[t].rmax+=tr[ls].rmax;
}
int query(int t,int tmp)
{
//
printf("%d\n",t);
if(tr[t].max<tmp) return(0);
if(tr[t].lazy)
pushdown(t);
if(tr[t].lmax>=tmp)
{
printf("%d\n",tr[t].l);
modify(1,tr[t].l,tr[t].l+tmp-1,-1);
}
else if(tr[ls].max>=tmp)
{
query(ls,tmp);
}
else if(tr[ls].rmax+tr[rs].lmax>=tmp)
{
int l=tr[ls].r-tr[ls].rmax+1;
printf("%d\n",l);
modify(1,l,l+tmp-1,-1);
}
else
{
query(rs,tmp);
}
return(1);
}
int main()
{
//
freopen("in.txt","r",stdin);
int n,k;
int tmp,l,r,ret;
while(scanf("%d %d",&n,&k)!=EOF)
{
maketree(1,1,n);
for(int i=1;i<=k;i++)
{
scanf("%d",&tmp);
if(tmp==2)
{
scanf("%d %d",&l,&r);
modify(1,l,l+r-1,1);
}
else
{
scanf("%d",&r);
ret=query(1,r);
if(ret==0)
printf("0\n");
}
}
}
return 0;
}