//9372104 NKHelloWorld 3667 Accepted 3740K 1000MS G++ 3738B 2011-09-29 15:06:22
//9372139 NKHelloWorld 3667 Accepted 3228K 594MS C++ 3740B 2011-09-29 15:12:45
/*
转自:http://www.cnblogs.com/superbin/archive/2010/07/18/1780194.html
题型:线段树(设计并维护复杂域)
描述:旅店登记,1.找一段最靠前的连续w个空房间;2.退订[x,x-d+1]段的房间。
思路:
1. 域的设计
struct Seg {
int l, r;
int lx, rx, mx;
char cv;
};
lx :左端连续空房间数
rx: 右端连续空房间数
mx: 连续最大空房间数
cv : = 0,全空, = 1 全满, = -1 非空非满。
2. 域的维护
开房:先用find(w, 1); 找到位置 rom, 然后用 mody(rom, rom+w-1, 0, 1); 进行插入操作
退房:进行删除操作mody(x, x-d+1, 1, 1)
因为此题区间的修改(插入和删除)很相似,所以用一个函数实现,0表示插入,1表示删除。
对cv域的维护包括 1. t[k].l == l && t[k].r == r 。 2. 根据父节点的cv值对子节点的修改(关键),find()和mody()中都需要有。
lx, rx, mx需要在回溯的过程维护:mx 为 两个子节点的mx和交叉区间和的最大值,
父节点的lx = 左子节点的lx + (右子节点的lx);
父节点的rx = 右子节点的rx + (左子节点的rx);
当左右子节点的lx,rx为整个区间长时,()需加上。
*/
#include <cstdio>
#include <iostream>
using namespace std;
#define MAXN 50010
struct SEGMENTTREE
{
int lt,rt,lval,rval,totval,state;
}tree[4*MAXN];
int n,m;
void buildsegtree(int root,int lt,int rt)
{
tree[root].lt = lt; tree[root].rt = rt;
tree[root].lval = tree[root].rval = tree[root].totval = rt - lt + 1;
tree[root].state = 0;
if(lt != rt)
{
int mid = (lt+rt)>>1;
buildsegtree(root<<1,lt,mid);
buildsegtree(root<<1|1,mid+1,rt);
}
}
void pushdown(int root)
{
tree[root<<1].state = tree[root<<1|1].state = tree[root].state;
if(tree[root].state == 0)
{
tree[root<<1].lval = tree[root<<1].rval = tree[root<<1].totval = tree[root<<1].rt - tree[root<<1].lt + 1;
tree[root<<1|1].lval = tree[root<<1|1].rval = tree[root<<1|1].totval = tree[root<<1|1].rt - tree[root<<1|1].lt +1;
}
else
{
tree[root<<1].lval = tree[root<<1].rval = tree[root<<1].totval = 0;
tree[root<<1|1].lval = tree[root<<1|1].rval = tree[root<<1|1].totval = 0;
}
tree[root].state = -1;
}
int query(int root,int lenth)
{
if(tree[root].lt == tree[root].rt)
{
if(tree[root].state == false && lenth == 1)
return tree[root].lt;
return 0;
}
if(tree[root].state != -1)
pushdown(root);
if(tree[root<<1].totval >= lenth)
return query(root<<1,lenth);
if(tree[root<<1].rval + tree[root<<1|1].lval >= lenth)
return tree[root<<1].rt - tree[root<<1].rval + 1;
if(tree[root<<1|1].totval >= lenth)
return query(root<<1|1,lenth);
return 0;
}
void update(int root,int lt,int rt,int state)
{
//printf("root:%d lt:%d rt:%d state:%d\n",root,lt,rt,state);
if(tree[root].lt == lt && tree[root].rt == rt)
{
tree[root].state = state;
if(state==1)
tree[root].lval = tree[root].rval = tree[root].totval = 0;
else if(state == 0)
tree[root].lval = tree[root].rval = tree[root].totval = rt - lt+ 1;
return ;
}
if(tree[root].state != -1)
pushdown(root);
int mid = (tree[root].lt + tree[root].rt)>>1;
if( rt <= mid )
update(root<<1,lt,rt,state);
else if(lt > mid)
update(root<<1|1,lt,rt,state);
else
{
update(root<<1,lt,mid,state);
update(root<<1|1,mid+1,rt,state);
}
tree[root].lval = tree[root<<1].lval;
tree[root].rval = tree[root<<1|1].rval;
tree[root].totval = max( max(tree[root<<1].totval,tree[root<<1|1].totval) , tree[root<<1].rval + tree[root<<1|1].lval);
if(tree[root].lval == tree[root<<1].rt - tree[root<<1].lt + 1)
tree[root].lval += tree[root<<1|1].lval;
if(tree[root].rval == tree[root<<1|1].rt - tree[root<<1|1].lt +1)
tree[root].rval += tree[root<<1].rval;
if(tree[root<<1].state == tree[root<<1|1].state)
tree[root].state = tree[root<<1].state;
}
void output(int root)
{
printf("root: %d, lt:%d rt:%d\t lval:%d rval:%d totval:%d state:%d\n",root,tree[root].lt,tree[root].rt,tree[root].lval,tree[root].rval,tree[root].totval,tree[root].state);
if(tree[root].lt != tree[root].rt)
{
output(root<<1);
output(root<<1|1);
}
}
int main()
{
int i,a,b,op;
scanf("%d%d",&n,&m);
buildsegtree(1,1,n);
while(m--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d",&a);
b = query(1,a);
printf("%d\n",b);
if(b)
{
update(1,b,b+a-1,1);
//output(1);
}
}
else
{
scanf("%d%d",&a,&b);
update(1,a,a+b-1,0);
//output(1);
}
}
return 0;
}