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;
}