CF1095E Almost Regular Bracket Sequence 题解
Almost Regular Bracket Sequence
题意
有一个长度为
求有多少个位置使得改变了该位置的括号种类可以使得括号序列合法。
思路
令左括号为
首先分为三种情况。
,那么说明左括号多了一个(一个右括号变一个左括号会使得 减少 ),要选择一个左括号变成右括号。 ,那么说明右括号多了一个,要选择一个右括号变成左括号。 或 或 ,答案必将为 ,可以直接输出。
对于情况一
设前
首先,我们来观察一个图:
在这种情况里,虽然
合法的括号序列,有一个条件,那就是在任何时候,左括号的数量都不能比右括号少!
所以,我们可以推出第一个条件:
- 可以作为答案的位置
必然要满足
那么,当我们第一次发现
再来观察一个图:
位置
虽然我们知道,位置
手推一下,我们会发现:把位置
那么就好办了,只要
对于情况二
同理,只要
总结
- 如果
,答案必为 。 - 如果
,答案为满足要求的 的个数。 。 且 。
- 如果
,答案为满足要求的 的个数。 。 且 。
用前缀和思想处理出
Code
点击查看代码
#include <iostream> #include <string> using namespace std; const int N = 1e6 + 10; string s; int n, sum[N], mi[N], ans; // sum 为前缀和,mi 为 sum 的后缀最小值 int main () { ios::sync_with_stdio(0), cin.tie(0); cin >> n >> s; for (int i = 1; i <= n; i++) { sum[i] = sum[i - 1]; if (s[i - 1] == '(') { // 处理好前缀和 sum[i]++; } else { sum[i]--; } } mi[n] = sum[n]; for (int i = n - 1; i; i--) { // 处理后缀最小值 mi[i] = min(mi[i + 1], sum[i]); } for (int i = 1; i <= n; i++) { if (sum[n] == 2 && mi[i] >= 2 && s[i - 1] == '(') { // 判断,情况 1 ans++; } else if (sum[n] == -2 && mi[i] >= -2 && s[i - 1] == ')') { // 判断,情况 2 ans++; } if (sum[i] < 0) { // 处理 i + 1 时,sum[i] < 0,结束循环 break; } } cout << ans; return 0; }
本文作者:wnsyou の blog
本文链接:https://www.cnblogs.com/wnsyou-blog/p/17409624.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步