这道题应该算是比较经典的线段树了
题意是:
这座巨型宾馆在一条超长走廊上有N(1 ≤ N ≤ 50000)个排成一排的房间,每个房间都能欣赏到苏必利尔湖的好景色。现在所有的房间都是空的。
现在Bessie等旅客们正在不断地发出订房和退房要求。你需要接受M(1 ≤ M < 50000)条指令:
每条指令的第一个数字为1或2。如果是1,后面将有一个整数D表示顾客要预定的房间数。注意,这些房间必须是连续的。如果能够满足旅客的订房要求, 输出满足要求的第一个房间的编号(例如,要订房6间,输出3表示3, 4, 5, 6, 7, 8是满足要求的),这样的编号必须是可能的编号里面最靠前的。如果不能满足要求,输出0。
如果是2,后面将有两个整数X和D表示顾客要退掉X, X + 1, X + 2, ... , X + D - 1这D间房。对于这样的指令什么都不输出
线段树保存的信息有,cover代表是否有人,msum代表区间内最大的连续长度,lsum是从左结点往右的连续长度,rsum是从右结点往左的连续长度。
/*
ID: sdj22251
PROG: inflate
LANG: C++
*/
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#define MAXN 50005
#define INF 10000000000000000LL
#define L(x) x<<1
#define R(x) x<<1|1
#define PI acos(-1.0)
#define eps 1e-7
using namespace std;
struct node
{
int left, right, mid;
int cover, lsum, rsum, msum;
}tree[4 * MAXN];
void down(int C)
{
if(tree[C].cover != -1)
{
int p = tree[C].right - tree[C].left + 1;
tree[L(C)].cover = tree[R(C)].cover = tree[C].cover;
tree[L(C)].lsum = tree[L(C)].rsum = tree[L(C)].msum = tree[C].cover ? 0 : p - (p >> 1);
tree[R(C)].lsum = tree[R(C)].rsum = tree[R(C)].msum = tree[C].cover ? 0 : (p >> 1);
tree[C].cover = -1;
}
}
void up(int C)
{
int p = tree[C].right - tree[C].left + 1;
tree[C].lsum = tree[L(C)].lsum;
tree[C].rsum = tree[R(C)].rsum;
if(tree[C].lsum == p - (p >> 1)) tree[C].lsum += tree[R(C)].lsum;
if(tree[C].rsum == (p >> 1)) tree[C].rsum += tree[L(C)].rsum;
tree[C].msum = max(tree[R(C)].lsum + tree[L(C)].rsum, max(tree[L(C)].msum, tree[R(C)].msum));
}
void make_tree(int s, int e, int C)
{
tree[C].left = s;
tree[C].right = e;
tree[C].mid = (s + e) >> 1;
tree[C].cover = -1;
tree[C].lsum = tree[C].rsum = tree[C].msum = e - s + 1;
if(s == e) return;
make_tree(s, tree[C].mid, L(C));
make_tree(tree[C].mid + 1, e, R(C));
}
void update(int s, int e, int p, int C)
{
if(tree[C].left >= s && tree[C].right <= e)
{
tree[C].msum = tree[C].lsum = tree[C].rsum = p ? 0: tree[C].right - tree[C].left + 1;
tree[C].cover = p;
return;
}
down(C);
if(tree[C].mid >= s) update(s, e, p, L(C));
if(tree[C].mid < e) update(s, e, p, R(C));
up(C);
}
int query(int p, int C)
{
if(tree[C].left == tree[C].right) return tree[C].left;
down(C);
if(tree[L(C)].msum >= p) return query(p, L(C));
else if(tree[L(C)].rsum + tree[R(C)].lsum >= p) return tree[C].mid - tree[L(C)].rsum + 1;
else return query(p, R(C));
}
int main()
{
int n, m, op, x, y;
scanf("%d%d", &n, &m);
make_tree(1, n, 1);
while(m--)
{
scanf("%d", &op);
if(op == 1)
{
scanf("%d", &x);
if(tree[1].msum < x) puts("0");
else
{
int p = query(x, 1);
printf("%d\n", p);
update(p, p + x - 1, 1, 1);
}
}
else
{
scanf("%d%d", &x, &y);
update(x, x + y - 1, 0, 1);
}
}
return 0;
}