AT_abc223_f [ABC223F] Parenthesis Checking 题解
思路
首先,括号串匹配当切仅当左括号和右括号数量相等,且任意子串 \([1,x]\)(\(1\le x\le |S|\))左括号数量减右括号数量都 \(\ge 0\)。
令左括号贡献值为 \(1\),右括号贡献值为 \(-1\),\(sum_i\) 代表子串 \([1,i]\) 贡献的和。
那对于任意子串,其为合法括号匹配串的充分必要条件为:
- 串内左括号和右括号数量相等,即 \(sum_r = sum_{l-1}\);
- 对于任意 \(i\)(\(l \le i \le r\)),都有 \(sum_i \ge 0\),即 $$\begin{aligned} \min _ {l \le i \le r}sum_i \ge 0\end{aligned}$$。
那我们就可以用线段树维护贡献前缀和的最小值。对于第一个性质,每次单点查询 \(2\) 次,然后看是否相等。对于第 \(2\) 个性质,区间查询 \([l, r]\) 的最小值。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 5;
int n, q;
int t[N];
char s[N];
struct seg_tree
{
struct node
{
int l, r, minn, lazy;
} tr[4 * N];
void push_up(int p)
{
tr[p].minn = min(tr[p * 2].minn, tr[p * 2 + 1].minn);
}
void push_down(int p)
{
if (tr[p].lazy)
{
tr[p * 2].lazy += tr[p].lazy;
tr[p * 2 + 1].lazy += tr[p].lazy;
tr[p * 2].minn += tr[p].lazy;
tr[p * 2 + 1].minn += tr[p].lazy;
tr[p].lazy = 0;
}
}
void build(int p, int l, int r)
{
tr[p] = {l, r, (int)(2e9), 0};
if (l == r)
{
tr[p].minn = t[l];
return;
}
int mid = (l + r) >> 1;
build(p * 2, l, mid);
build(p * 2 + 1, mid + 1, r);
push_up(p);
}
void update(int p, int l, int r, int x)
{
if (tr[p].r < l || tr[p].l > r) return;
if (tr[p].l >= l && tr[p].r <= r)
{
tr[p].minn += x;
tr[p].lazy += x;
return;
}
push_down(p);
int mid = (l + r) >> 1;
if (l <= mid) update(p * 2, l, r, x);
if (r > mid) update(p * 2 + 1, l, r, x);
push_up(p);
}
int query(int p, int l, int r)
{
if (tr[p].r < l || tr[p].l > r) return (int)(2e9);
if (tr[p].l >= l && tr[p].r <= r) return tr[p].minn;
push_down(p);
int mid = (tr[p].l + tr[p].r) >> 1, res = (int)(2e9);
if (l <= mid) res = min(res, query(p * 2, l, r));
if (r > mid) res = min(res, query(p * 2 + 1, l, r));
return res;
}
} ST;
signed main()
{
scanf("%lld%lld%s", &n, &q, s + 1);
for (int i = 1; i <= n; i++)
{
if (s[i] == '(') t[i] = t[i - 1] + 1;
else t[i] = t[i - 1] - 1;
}
ST.build(1, 1, n);
while (q--)
{
int op, l, r;
scanf("%lld%lld%lld", &op, &l, &r);
if (op == 1)
{
if (s[l] == s[r]) continue;
if (s[l] == '(')
{
ST.update(1, l, n, -2);
ST.update(1, r, n, 2);
}
else
{
ST.update(1, l, n, 2);
ST.update(1, r, n, -2);
}
swap(s[l], s[r]);
}
else
{
int k1 = 0, k2 = ST.query(1, r, r), k3 = ST.query(1, l, r);
if (l == 1) k1 = 0;
else k1 = ST.query(1, l - 1, l - 1);
if (k1 == k2 && k3 >= k1) puts("Yes");
else puts("No");
}
}
return 0;
}

浙公网安备 33010602011771号