关于区间合并的线段树。
要求的是满足一个条件的最左边的位置。
所以可以维护一个sum,suml,sumr分别表示一段区间内空房间的数目,从最左边开始的数目,以及从最右边开始的数目,在pushup的时候需要对区间进行合并,这样在考虑询问的时候,根据维护的信息,优先考虑左边房间就行了。
代码:
#include<cstdio>
#include<cstring>
#define lson l,m,rt << 1
#define rson m + 1,r,rt << 1 | 1
using namespace std;
const int maxn = 50000 + 10;
int suml[maxn<<2],sumr[maxn<<2],sum[maxn<<2];
int cover[maxn<<2];
int n,m;
void init()
{
freopen("poj3667.in","r",stdin);
freopen("poj3667.out","w",stdout);
}
void build(int l,int r,int rt)
{
sum[rt] = suml[rt] = sumr[rt] = r - l + 1;
cover[rt] = -1;
if(l == r)return;
int m = (l + r) >> 1;
build(lson);
build(rson);
}
int max(int a,int b)
{
return a > b ? a : b;
}
void pushup(int rt,int m)
{
suml[rt] = suml[rt<<1];
sumr[rt] = sumr[rt<<1|1];
if(suml[rt] == m - (m >> 1))suml[rt] += suml[rt<<1|1];
if(sumr[rt] == (m >> 1))sumr[rt] += sumr[rt<<1];
sum[rt] = max(suml[rt<<1|1] + sumr[rt<<1],max(sum[rt<<1],sum[rt<<1|1]));
}
void pushdown(int rt,int m)
{
if(cover[rt] != -1)
{
cover[rt<<1] = cover[rt<<1|1] = cover[rt];
sum[rt<<1] = suml[rt<<1] = sumr[rt<<1] = cover[rt] ? 0 : m - (m >> 1);
sum[rt<<1|1] = suml[rt<<1|1] = sumr[rt<<1|1] = cover[rt] ? 0 : (m >> 1);
cover[rt] = -1;
}
}
void update(int L,int R,int c,int l,int r,int rt)
{
if(L <= l && r <= R)
{
sum[rt] = suml[rt] = sumr[rt] = c ? 0 : r - l + 1;
cover[rt] = c;
return;
}
pushdown(rt,r - l + 1);
int m = (l + r) >> 1;
if(L <= m)update(L,R,c,lson);
if(m < R)update(L,R,c,rson);
pushup(rt,r - l + 1);
}
int query(int tot,int l,int r,int rt)
{
if(l == r)return l;
pushdown(rt,r - l + 1);
int m = (l + r) >> 1;
if(sum[rt<<1] >= tot)return query(tot,lson);
else if(sumr[rt<<1] + suml[rt<<1|1] >= tot)return m - sumr[rt<<1] + 1;
return query(tot,rson);
}
void readdata()
{
memset(cover,-1,sizeof(cover));
scanf("%d%d",&n,&m);
build(1,n,1);
for(int i = 1;i <= m;i++)
{
int op,d;
scanf("%d",&op);
if(op == 1)
{
scanf("%d",&d);
if(sum[1] < d)puts("0");
else
{
int tmp = query(d,1,n,1);
printf("%d\n",tmp);
update(tmp,tmp + d - 1,1,1,n,1);
}
}
else
{
int x;
scanf("%d%d",&x,&d);
update(x,x + d - 1,0,1,n,1);
}
}
}
int main()
{
init();
readdata();
return 0;
}