线段树题, 操作有:
1. 找到线段树中从左数第一段长度大于等于L的连续的0, 返回这段0的左边第一个元素的下标, 如果没有返回0.
2. 更新一段区间, 使这段区间全为0或者全为1.
从上述操作可以看出, 关键点在于第一个操作.
设置线段树结点结构为:
struct Node { int left, right; int stat; int lmax, rmax, amax; };
stat = 0 表示区间中的元素全为0, stat = 1 表示区间中的元素全为1, stat = 2 表示区间中既有1也有2.
lmax 表示包括最左边的元素, 最长的连续为0段的长度.
rmax 表示包括最右边的元素, 最长的连续为0段的长度.
amax 表示区间中最长的连续为0段的长度.
#include <iostream> 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; }