题意:给你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; }