P3215 括号修复 题解

Statement

维护一个括号序列,有以下操作:

  • 区间覆盖
  • 区间翻转
  • 区间反转(左括号变右括号,右括号变左括号)
  • 区间问最少改多少位能使括号序列合法,保证有解

Solution

单纯没想到答案怎么算。。。

首先一段括号序,如果消除中间的所有匹配,最终一定形如 ))))(((,这个信息是可合并的

设这时左括号数为 \(a\),右括号数为 \(b\),答案等于 \(\lceil\frac a2\rceil+\lceil\frac b2\rceil\)

对于区间翻转和区间反转,再维护一下翻转、反转后的 \(a\)\(b\) 即可。

套上 FHQ 做完了。

Code

#include <bits/stdc++.h>
using namespace std;
#define rep(i, j, k) for (int i = (j); i <= (k); ++i)
#define reo(i, j, k) for (int i = (j); i >= (k); --i)
typedef long long ll;
const int N = 1e5 + 10;
struct Item {
	int x, y;
	Item operator+ (const Item& rhs) const {
		return (Item){x + max(0, rhs.x - y), rhs.y + max(0, y - rhs.x)};
	}
} a[N], ai[N], as[N], asi[N], V[N], Vi[N];
int n, q, tot, rt, A, B, C, b[N], sz[N], co[N], sw[N], in[N], ch[N][2];
mt19937 rnd(251);
string s;

int New(char c) {
	sz[++tot] = 1, b[tot] = rnd(), co[tot] = 2;
	V[tot].x = Vi[tot].y = a[tot].x = ai[tot].y = as[tot].x = asi[tot].y = c == ')';
	V[tot].y = Vi[tot].x = a[tot].y = ai[tot].x = as[tot].y = asi[tot].x = !a[tot].x;
	return tot;
}
void up(int u) {
	sz[u] = sz[ch[u][0]] + 1 + sz[ch[u][1]];
	a[u] = a[ch[u][0]] + V[u] + a[ch[u][1]];
	ai[u] = ai[ch[u][0]] + Vi[u] + ai[ch[u][1]];
	as[u] = as[ch[u][1]] + V[u] + as[ch[u][0]];
	asi[u] = asi[ch[u][1]] + Vi[u] + asi[ch[u][0]];
}
void Cov(int u, int o) {
	co[u] = o, in[u] = 0;
	if (o) V[u].x = Vi[u].y = 1, a[u].x = ai[u].y = as[u].x = asi[u].y = sz[u], V[u].y = Vi[u].x = a[u].y = ai[u].x = as[u].y = asi[u].x = 0;
	else V[u].y = Vi[u].x = 1, a[u].y = ai[u].x = as[u].y = asi[u].x = sz[u], V[u].x = Vi[u].y = a[u].x = ai[u].y = as[u].x = asi[u].y = 0;
}
void Swp(int u) {
	swap(a[u], as[u]), swap(ai[u], asi[u]), swap(ch[u][0], ch[u][1]), sw[u] ^= 1;
}
void Inv(int u) {
	swap(a[u], ai[u]), swap(as[u], asi[u]), swap(V[u], Vi[u]), in[u] ^= 1;
}
void down(int u) {
	if (co[u] != 2) Cov(ch[u][0], co[u]), Cov(ch[u][1], co[u]), co[u] = 2;
	if (sw[u]) Swp(ch[u][0]), Swp(ch[u][1]), sw[u] = 0;
	if (in[u]) Inv(ch[u][0]), Inv(ch[u][1]), in[u] = 0;
}
void spl(int u, int k, int &x, int &y) {
	if (!u) return (void)(x = y = 0);
	down(u);
	if (k <= sz[ch[u][0]]) y = u, spl(ch[u][0], k, x, ch[u][0]);
	else x = u, spl(ch[u][1], k - sz[ch[u][0]] - 1, ch[u][1], y);
	up(u);
}
int mer(int u, int v) {
	if (!u || !v) return u | v;
	down(u), down(v);
	if (b[u] < b[v]) return ch[u][1] = mer(ch[u][1], v), up(u), u;
	else return ch[v][0] = mer(u, ch[v][0]), up(v), v;
}

int F(int x) {
	return x / 2 + (x % 2 == 1);
}

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	cin >> n >> q >> s;
	rep(i, 0, n - 1) rt = mer(rt, New(s[i]));
	while (q--) {
		string op;
		int l, r;
		char c;
		cin >> op >> l >> r;
		spl(rt, l - 1, A, B), spl(B, r - l + 1, B, C);
		if (op[0] == 'R') cin >> c, Cov(B, c == ')');
		if (op[0] == 'S') Swp(B);
		if (op[0] == 'I') Inv(B);
		if (op[0] == 'Q') cout << F(a[B].x) + F(a[B].y) << '\n';
		rt = mer(mer(A, B), C);
	}
	return 0;
}
posted @ 2024-10-07 09:26  Laijinyi  阅读(4)  评论(0编辑  收藏  举报