题目链接:http://poj.org/problem?id=3667
题目大意:两个操作,1 x表示找出最左连着的x个空位置,并占满,输出最左端,2 x y表示清空x到y位置
题目思路:逆向思维,空位置用1,占了的位置用0。然后就是基础的线段树区间合并,跟炸地道那题的x所在1长度方法是一样的。维护最左连续1,最右连续1和最长连续1。维护方法跟那题一样,可以看之前的博客。然后这题的还有个难点在查询。当整个区间的连续1个数都小于x时返回0。否则看左子树是否有这么多0,有的话继续搜左子树,如果左子树的最右连续1+右字数最左连续1是否满足,满足的话直接返回,否则搜右子树。
以下是代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
const int MAXN = 5e4+5;
const int MOD = 1e9+7;
struct node{
int l,r,lm,rm,mm,mark;
}a[MAXN<<2];
void build(int rt,int l,int r){
a[rt].l=l,a[rt].r=r;
a[rt].lm=a[rt].rm=a[rt].mm=r-l+1;
a[rt].mark=-1;
if(l==r)return;
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
}
void spread(int rt){
if(a[rt].mark!=-1){
a[rt<<1].lm=a[rt<<1].rm=a[rt<<1].mm=a[rt].mark*(a[rt<<1].r-a[rt<<1].l+1);
a[rt<<1|1].lm=a[rt<<1|1].rm=a[rt<<1|1].mm=a[rt].mark*(a[rt<<1|1].r-a[rt<<1|1].l+1);
a[rt<<1].mark=a[rt<<1|1].mark=a[rt].mark;
a[rt].mark=-1;
}
}
void update(int rt,int l,int r,int val){
if(l<=a[rt].l&&a[rt].r<=r){
a[rt].lm=a[rt].rm=a[rt].mm=val*(a[rt].r-a[rt].l+1);
a[rt].mark=val;
return;
}
spread(rt);
int mid=(a[rt].l+a[rt].r)>>1;
if(l<=mid)update(rt<<1,l,r,val);
if(r>mid)update(rt<<1|1,l,r,val);
a[rt].lm=a[rt<<1].lm;
a[rt].rm=a[rt<<1|1].rm;
a[rt].mm=max(a[rt<<1].mm,a[rt<<1|1].mm);
a[rt].mm=max(a[rt].mm,a[rt<<1].rm+a[rt<<1|1].lm);
if(a[rt<<1].lm==a[rt<<1].r-a[rt<<1].l+1)a[rt].lm+=a[rt<<1|1].lm;
if(a[rt<<1|1].rm==a[rt<<1|1].r-a[rt<<1|1].l+1)a[rt].rm+=a[rt<<1].rm;
}
int query(int rt,int x){
spread(rt);
if(a[rt].lm==x){
return a[rt].l;
}
if(a[rt<<1].mm>=x)return query(rt<<1,x);
else if(a[rt<<1].rm+a[rt<<1|1].lm>=x)return a[rt<<1].r-a[rt<<1].rm+1;
else return query(rt<<1|1,x);
}
int main(){
int n,m,p,x,y;
while(~scanf("%d%d",&n,&m)){
build(1,1,n);
while(m--){
scanf("%d",&p);
if(p==1){
scanf("%d",&x);
if(a[1].mm<x){
printf("0\n");
continue;
}
int l=query(1,x);
update(1,l,l+x-1,0);
printf("%d\n",l);
}
else{
scanf("%d%d",&x,&y);
update(1,x,x+y-1,1);
}
}
}
return 0;
}