线段树区间合并(模板)
poj3667
#include<cstdio> #include<algorithm> #define lid id << 1 #define rid id << 1 | 1 using namespace std; const int mx = 50010; struct tree{ int l, r; int ls, rs, ms; int lazy; }tree[mx<<2]; void build(int l, int r, int id){ tree[id].l = l; tree[id].r = r; tree[id].ls = tree[id].rs = tree[id].ms = r-l+1; tree[id].lazy = -1; if (l == r) return; int mid = (l+r) >> 1; build(l, mid, lid); build(mid+1, r, rid); } void pushdown(int id){ if (tree[id].lazy != -1){ tree[lid].lazy = tree[rid].lazy = tree[id].lazy; tree[lid].ls = tree[lid].rs = tree[lid].ms = tree[id].lazy ? 0 : tree[lid].r-tree[lid].l+1; tree[rid].ls = tree[rid].rs = tree[rid].ms = tree[id].lazy ? 0 : tree[rid].r-tree[rid].l+1; tree[id].lazy = -1; } } void pushup(int id){ tree[id].ls = tree[lid].ls; tree[id].rs = tree[rid].rs; int mid = (tree[id].l + tree[id].r) >> 1; if (tree[id].ls == mid-tree[id].l+1) tree[id].ls += tree[rid].ls; if (tree[id].rs == tree[id].r-mid) tree[id].rs += tree[lid].rs; tree[id].ms = max(max(tree[lid].ms, tree[rid].ms), tree[lid].rs+tree[rid].ls); } void upd(int l, int r, int id, bool x){ if (tree[id].l == l && tree[id].r == r){ tree[id].lazy = x; tree[id].ls = tree[id].rs = tree[id].ms = x ? 0 : r-l+1; return; } pushdown(id); int mid = (tree[id].l + tree[id].r) >> 1; if (r <= mid) upd(l, r, lid, x); else if (mid < l) upd(l, r, rid, x); else { upd(l, mid, lid, x); upd(mid+1, r, rid, x); } pushup(id); } int query(int l, int r, int id, int x){ if (l == r) return l; pushdown(id); int mid = (l+r) >> 1; if (tree[lid].ms >= x) return query(l, mid, lid, x); else if (tree[lid].rs + tree[rid].ls >= x) return mid-tree[lid].rs+1; return query(mid+1, r, rid, x); } int main(){ int n, m; scanf("%d%d", &n, &m); build(1, n, 1); while (m--){ int op, a, b; scanf("%d%d", &op, &a); if (op == 1){ if (tree[1].ms < a) printf("0\n"); else { b = query(1, n, 1, a); printf("%d\n", b); upd(b, b+a-1, 1, 1); } } else { scanf("%d", &b); upd(a, a+b-1, 1, 0); } } return 0; }