当前位置: 代码迷 >> 综合 >> 【codeforces 1095E - Almost Regular Bracket Sequence】【线段树】【前缀和】【括号匹配】
  详细解决方案

【codeforces 1095E - Almost Regular Bracket Sequence】【线段树】【前缀和】【括号匹配】

热度:7   发布时间:2024-01-04 11:38:26.0

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

 

  相关解决方案