题目大意

给定一个长度为 $n$ 的字符序列,初始全是 L

有 $q$ 次操作,每次将 $a_x$ 在 LR 中切换。

求每次操作后字符串中最长交错序列的长度。

分析

首先需要逐位异或,把交错序列变成相同元素。我想到的是另一种办法,如果 $a_i$ 相对与 $a_{i-1}$ 是变化的,那么 $b_i$ 为 $1$。原问题即被转化为维护最长 $1$ 的个数。

用线段树维护每一层的信息,其中 $l$ 表示左边界上的最长长度,$r$ 表示右边界上的最长长度,$val$ 表示整个区间上的最长长度。

关键在于如何编写 pull 合并信息。

  • 如果整块区域都是 $1$,那么可以和另一块区域合并。
  • 合并后的 $val$ 应该考虑在左边界、右边界、左子树、右子树和中间中取。
struct SegmentTree {
	vector<int> l, r, val;

	int N;
	SegmentTree(int n) {
		N = 2 << std::__lg(n);
		l.resize(N * 2, 0);
		r.resize(N * 2, 0);
		val.resize(N * 2, 0);
	}
	void pull(int p, int len) {
		int ls = p * 2, rs = p * 2 + 1;
		l[p] = l[ls], r[p] = r[rs];
		if (l[ls] == len)
			l[p] += l[rs];
		if (r[rs] == len)
			r[p] += r[ls];
		val[p] = max({l[p], r[p], val[ls], val[rs], r[ls] + l[rs]});
	}
	void modify(int i) {
		i += N;
		l[i] = r[i] = val[i] = !val[i];
		int len = 1;
		for (int k = i / 2; k >= 1; k /= 2, len *= 2) {
			pull(k, len);
		}
	}
};