经典类型,求一块满足条件的最左边的空间。成段更新
下面的代码有点冗余。
(代码里面stat标记整段线段是否为0/1/混合,但这里没必要,这里只需对整段线段置0或1操作打懒标记,记录此操作执行到哪里,方便下次如果要访问它的子区间时进行此操作)
#include <iostream> #include <stdio.h> using namespace std; const int maxn = 50000 * 3; struct Node { int left, right; int stat; // 0:区间全为0,1:区间全为1,2:区间有部分为0部分为1 int lmax, rmax, amax; // lmax:包含最左边元素最长0的长度,rmax:包含最右边元素最长0的长度 } tree[maxn]; // amax:区间中最长0的长度 void Build(int l, int r, int id) { tree[id].left = l; tree[id].right = r; tree[id].stat = 0; tree[id].lmax = tree[id].rmax = tree[id].amax = r - l + 1; if (l == r) return; int m = (l + r) / 2; Build(l, m, id * 2); Build(m + 1, r, id * 2 + 1); } void UpdateStatus(int id) { if (tree[id].stat == 2) { if (tree[id*2].stat == tree[id*2+1].stat && tree[id*2].stat != 2) tree[id].stat = tree[id*2].stat; } } void UpdateLength(int id) { if (tree[id].stat == 0) tree[id].lmax = tree[id].rmax = tree[id].amax =tree[id].right - tree[id].left + 1; else if (tree[id].stat == 1) tree[id].lmax = tree[id].rmax = tree[id].amax = 0; else { tree[id].amax = max(max(tree[id*2].amax, tree[id*2+1].amax), tree[id*2].rmax + tree[id*2+1].lmax); tree[id].lmax = tree[id*2].lmax; tree[id].rmax = tree[id*2+1].rmax; if (tree[id*2].stat == 0) tree[id].lmax += tree[id*2+1].lmax; if (tree[id*2+1].stat == 0) tree[id].rmax += tree[id*2].rmax; } } void Update(int l, int r, int v, int id) // v = 0:更新一段区间为0, v = 1:更新一段区间为1 { if (tree[id].stat == v) return; if (tree[id].left == l && tree[id].right == r) { tree[id].stat = v; UpdateLength(id); return; } if (tree[id].stat != 2) { tree[id*2].stat = tree[id*2+1].stat = tree[id].stat; tree[id].stat = 2; UpdateLength(id*2); UpdateLength(id*2+1); } int m = (tree[id].left + tree[id].right) / 2; if (r <= m) Update(l, r, v, id * 2); else if (l > m) Update(l , r, v, id * 2 + 1); else Update(l, m, v, id * 2), Update(m + 1, r, v, id * 2 + 1); UpdateStatus(id); UpdateLength(id); } int Query(int len, int id) { if (tree[id].stat == 0) return tree[id].left; if (tree[id*2].amax >= len) return Query(len, id * 2); else if (tree[id*2].rmax + tree[id*2+1].lmax >= len) return tree[id*2].right - tree[id*2].rmax + 1; else return Query(len, id * 2 + 1); } int main() { int N, M; int cmd, len, x; scanf("%d %d", &N, &M); Build(1, N, 1); for (int i = 0; i < M; i++) { scanf("%d", &cmd); if (cmd == 1) { scanf("%d", &len); if (tree[1].amax < len) printf("0\n"); else { x = Query(len, 1); Update(x, x + len - 1, 1, 1); printf("%d\n", x); } } else { scanf("%d %d", &x, &len); Update(x, x + len - 1, 0, 1); } } return 0; }