https://codeforces.com/problemset/problem/1095/E
【题意】
问有多少的个位置,更换一个括号,就能使括号匹配
【思路】
线段树维护。
遍历每一个位置,单点修改。建一棵线段树,树上节点维护两个信息:左括号数,右括号数
区间合并:
假设左儿子为:))(((,右儿子为:))(((,合并消除()之后就变成了))((((
所以我可以从1枚举到n,在线段树中改变第 i 个位置的括号,如果线段树根节点的tl=tr=0,那么答案就++。
暴力修改,线段树维护
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
char s[maxn];
int tl[maxn * 4], tr[maxn * 4];
void push(int p, int ls, int rs)
{
if (tr[ls] >= tl[rs])
{
tl[p] = tl[ls];
tr[p] = tr[rs] + tr[ls] - tl[rs];
}
else
{
tr[p] = tr[rs];
tl[p] = tl[ls] + tl[rs] - tr[ls];
}
}
void build(int p, int l, int r)
{
if (l == r)
{
if (s[l] == '(')
tr[p] = 1;
else tl[p] = 1;
return;
}
int m = (l + r) / 2, ls = p * 2, rs = p * 2 + 1;
build(ls, l, m);
build(rs, m + 1, r);
push(p, ls, rs);
}
void up(int p, int l, int r, int k)
{
if (l == r)
{
tl[p] = !tl[p];
tr[p] = !tr[p];
return;
}
int m = (l + r) / 2, ls = p * 2, rs = p * 2 + 1;
if (k <= m)up(ls, l, m, k);
else up(rs, m + 1, r, k);
push(p, ls, rs);
}
int main()
{
int n;
while (~scanf("%d", &n)) {
int ans = 0;
scanf("%s", s + 1);
build(1, 1, n);
for (int i = 1; i <= n; i++)
{
up(1, 1, n, i);
if (tl[1] == 0 && tr[1] == 0)ans++;
up(1, 1, n, i);
}
cout << ans;
}
}