线段树题, 操作有:
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;
}