Almost Regular Bracket Sequence CodeForces - 1095E (线段树,单点更新,区间查询维护括号序列)
Almost Regular Bracket Sequence
You are given a bracket sequence ss consisting of nn opening '(' and closing ')' brackets.
A regular bracket sequence is a bracket sequence that can be transformed into a correct arithmetic expression by inserting characters '1' and '+' between the original characters of the sequence. For example, bracket sequences "()()", "(())" are regular (the resulting expressions are: "(1)+(1)", "((1+1)+1)"), and ")(" and "(" are not.
You can change the type of some bracket sisi. It means that if si=si= ')' then you can change it to '(' and vice versa.
Your task is to calculate the number of positions ii such that if you change the type of the ii-th bracket, then the resulting bracket sequence becomes regular.
Input
The first line of the input contains one integer nn (1≤n≤1061≤n≤106) — the length of the bracket sequence.
The second line of the input contains the string ss consisting of nn opening '(' and closing ')' brackets.
Output
Print one integer — the number of positions ii such that if you change the type of the ii-th bracket, then the resulting bracket sequence becomes regular.
Examples
Input
6
(((())
Output
3
Input
6
()()()
Output
0
Input
1
)
Output
0
Input
8
)))(((((
Output
0
翻译:
赵老师实在是太强了,以至于他随便出的题就难倒了张老师
他给了张老师一个括号序列S,其中只包含"("和")"
他只允许张老师更改一个位置上的符号类型,如把"("变为")",从而使得整个括号序列是一个合法的括号序列
请你帮张老师计算一下有几个位置,更改了这个位置的括号类型,整个括号序列将变成合法的括号序列
思路:
https://www.cnblogs.com/qieqiemin/p/11491557.html
我这篇博客的题目是用线段树维护括号序列的最大合法匹配的子序列长度。(只有区间询问)
如果不会建议前去学习。
那么对于本题,
我们可以增加一个单点更新的功能,然后对于1到n每一个字符,单点更新为相反的字符串。
然后区间查询整个(即1~n)字符串的最大合法匹配的子序列长度是否为n,如果是就证明当前字符串是整体完美匹配的。答案+=1即可,然后将其再返过来更新,恢复成原始的字符串。再移步到下一个位置。统计最终答案即可。
还有一种是分析性质和规律的做法,推荐这篇博客:https://blog.csdn.net/tianyizhicheng/article/details/86776263
贴上我的ac代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2) { ans = ans * a % MOD; } a = a * a % MOD; b /= 2;} return ans;}
inline void getInt(int *p);
const int maxn = 1000010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
struct node {
int l, r;
int num;
int a;// (
int b;// )
} segmeng_tree[maxn << 2];
char s[maxn];
int n;
int m;
void pushup(int rt)
{
int x = min(segmeng_tree[rt << 1].a, segmeng_tree[rt << 1 | 1].b);
segmeng_tree[rt].num = x + segmeng_tree[rt << 1].num + segmeng_tree[rt << 1 | 1].num;
segmeng_tree[rt].a = segmeng_tree[rt << 1].a + segmeng_tree[rt << 1 | 1].a - x;
segmeng_tree[rt].b = segmeng_tree[rt << 1].b + segmeng_tree[rt << 1 | 1].b - x;
}
void build(int rt, int l, int r)
{
segmeng_tree[rt].l = l;
segmeng_tree[rt].r = r;
if (l == r) {
segmeng_tree[rt].a = s[l] == '(';
segmeng_tree[rt].b = s[l] == ')';
segmeng_tree[rt].num = 0;
} else {
int mid = (l + r) >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
pushup(rt);
}
}
node ask(int rt, int l, int r)
{
if (segmeng_tree[rt].l >= l && segmeng_tree[rt].r <= r) {
return segmeng_tree[rt];
}
int mid = (segmeng_tree[rt].l + segmeng_tree[rt].r) >> 1;
if (r <= mid) {
return ask(rt << 1, l, r);
} else if (l > mid) {
return ask(rt << 1 | 1, l, r);
} else {
node res1 = ask(rt << 1, l, r);
node res2 = ask(rt << 1 | 1, l, r);
node res = res1;
int x = min(res1.a, res2.b);
res.num += x;
res.b += res2.b;
res.a += res2.a;
res.num += res2.num;
res.b -= x;
res.a -= x;
return res;
}
}
void update(int rt, int x, int val)
{
if (segmeng_tree[rt].l == segmeng_tree[rt].r && segmeng_tree[rt].l == x)
{
if (val)
{
segmeng_tree[rt].a = 1;
segmeng_tree[rt].b = 0;
} else
{
segmeng_tree[rt].a = 0;
segmeng_tree[rt].b = 1;
}
} else
{
int mid = (segmeng_tree[rt].r + segmeng_tree[rt].l) >> 1;
if (x <= mid)
{
update(rt << 1, x, val);
} else
{
update(rt << 1 | 1, x, val);
}
pushup(rt);
}
}
int main()
{
//freopen("D:\\code\\text\\input.txt","r",stdin);
//freopen("D:\\code\\text\\output.txt","w",stdout);
scanf("%d",&n);
scanf("%s", s + 1);
// n = strlen(s + 1);
build(1, 1, n);
int ans = 0;
repd(i, 1, n)
{
if (s[i] == '(')
{
update(1,i,0);
int len=ask(1,1,n).num*2;
if(len==n)
{
ans++;
}
update(1,i,1);
}else
{
update(1,i,1);
int len=ask(1,1,n).num*2;
if(len==n)
{
ans++;
}
update(1,i,0);
}
}
printf("%d\n",ans );
return 0;
}
inline void getInt(int *p)
{
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
if (ch == '-') {
*p = -(getchar() - '0');
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 - ch + '0';
}
} else {
*p = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 + ch - '0';
}
}
}