题意:给你1到n的区间,初始都能使用,两种操作:
1 x :找到最左端的能使用的长度为x的子区间,并使占用这个子区间; 2 x k :使得从x开始长度为k的子区间又能够使用。
线段树节点维护从左边开始的最长子区间,从右边开始的最长子区间,总的最长子区间,设三个节点为空标记,全满标记,和有隔断点标记,然后合并区间就很容易了。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 51111
#define maxm 8111111
#define pl c<<1
#define pr (c<<1)|1
#define lson tree[c].l,tree[c].mid,c<<1
#define rson tree[c].mid+1,tree[c].r,(c<<1)|1
#define empty Empty
#define clear Clear
#define insert Insert
int n, m;
struct node {
int l, r, mid;
int Max, numl, numr;
bool is; //是否分割
bool full; //是否为满
bool empty; //是否为空
}tree[maxn<<4];
void pushup (int c) {
if (tree[c].l == tree[c].r)
return ;
if (!tree[pl].is) {
tree[c].numl = tree[pl].Max+tree[pr].numl;
}
else tree[c].numl = tree[pl].numl;
if (!tree[pr].is) {
tree[c].numr = tree[pr].Max+tree[pl].numr;
}
else tree[c].numr = tree[pr].numr;
tree[c].Max = max (tree[pl].numr+tree[pr].numl, max (tree[pl].Max, tree[pr].Max));
tree[c].full = (tree[pl].full&tree[pr].full);
tree[c].is = (tree[pl].is|tree[pr].is);
tree[c].empty = (tree[pl].empty&tree[pr].empty);
}
void build_tree (int l, int r, int c) {
tree[c].l = l, tree[c].r = r, tree[c].mid = (l+r)>>1;
if (l == r) {
tree[c].Max = tree[c].numl = tree[c].numr = 1;
tree[c].is = 0;
tree[c].full = 1;
tree[c].empty = 0;
return ;
}
build_tree (lson);
build_tree (rson);
pushup (c);
}
void push_down_empty (int c) {
tree[pl].Max = tree[pr].Max = tree[pl].numl = tree[pr].numl =
tree[pl].numr = tree[pr].numr = 0;
tree[pl].empty = tree[pr].empty = 1;
tree[pl].is = tree[pr].is = 1;
tree[pl].full = tree[pr].full = 0;
return ;
}
void push_down (int c) {
if (tree[c].l == tree[c].r)
return ;
if (tree[c].empty) {
push_down_empty (c);
tree[c].empty = 0;
}
if (tree[c].full) {
tree[pl].numl = tree[pl].numr = tree[pl].Max = (tree[pl].r-tree[pl].l+1);
tree[pr].numl = tree[pr].numr = tree[pr].Max = (tree[pr].r-tree[pr].l+1);
tree[pl].empty = tree[pr].empty = 0;
tree[pl].full = tree[pr].full = 1;
tree[pl].is = tree[pr].is = 0;
}
}
void clear (int l, int r, int c, int x, int y) {
if (tree[c].empty || tree[c].full)
push_down (c);
if (l == x && y == r) {
tree[c].numl = tree[c].numr = tree[c].Max = r-l+1;
tree[c].full = 1;
tree[c].is = 0;
tree[c].empty = 0;
return ;
}
else if (tree[c].mid >= y) {
clear (lson, x, y);
}
else if (tree[c].mid < x) {
clear (rson, x, y);
}
else {
clear (lson, x, tree[c].mid);
clear (rson, tree[c].mid+1, y);
}
pushup (c);
}
int query (int l, int r, int c, int len) {
if (tree[c].empty || tree[c].full)
push_down (c);
if (tree[c].Max < len)
return 0; //无解
if (tree[pl].Max >= len)
return query (lson, len);
else if (tree[pl].numr + tree[pr].numl >= len) {
return tree[c].mid-tree[pl].numr+1;
}
else return query (rson, len);
}
void insert (int l, int r, int c, int x, int y) {
if (tree[c].full)
push_down (c);
if (l == x && r == y) {
tree[c].empty = 1;
tree[c].full = 0;
tree[c].is = 1;
tree[c].Max = tree[c].numl = tree[c].numr = 0;
return ;
}
else if (tree[c].mid >= y) {
insert (lson, x, y);
}
else if (tree[c].mid < x) {
insert (rson, x, y);
}
else {
insert (lson, x, tree[c].mid);
insert (rson, tree[c].mid+1, y);
}
pushup (c);
}
void debug (int l, int r, int c) {
cout << "l:" << l << " r:" << r << " max:" << tree[c].Max
<< " numl:" << tree[c].numl << " numr:" << tree[c].numr << endl;
if (l == r)
return ;
debug (lson);
debug (rson);
}
int main () {
while (scanf ("%d%d", &n, &m) == 2) {
build_tree (1, n, 1);
for (int i = 1; i <= m; i++) {
int op;
scanf ("%d", &op);
if (op == 1) {
int k;
scanf ("%d", &k);
int pos = query (1, n, 1, k);
printf ("%d\n", pos);
if (pos) {
insert (1, n, 1, pos, pos+k-1);
}
}
else if (op == 2) {
int l, r;
scanf ("%d%d", &l, &r);
clear (1, n, 1, l, l+r-1);
}
//int tt; cin >>tt; if (tt == 100) debug (1, n, 1);
}
}
return 0;
}