Codeforces Round #529 (Div. 3) E. Almost Regular Bracket Sequence

You are given a bracket sequence ?s consisting of ?n 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 ??si. It means that if ??=si= ')' then you can change it to '(' and vice versa.

Your task is to calculate the number of positions ?i such that if you change the type of the ?i-th bracket, then the resulting bracket sequence becomes regular.

Input

The first line of the input contains one integer ?n (1≤?≤1061≤n≤106) — the length of the bracket sequence.

The second line of the input contains the string ?s consisting of ?n opening '(' and closing ')' brackets.

Output

Print one integer — the number of positions ?i such that if you change the type of the ?i-th bracket, then the resulting bracket sequence becomes regular.

Examples

input

Copy

6
(((())

output

Copy

3

input

Copy

6
()()()

output

Copy

0

input

Copy

1
)

output

Copy

0

input

Copy

8
)))(((((

output

Copy

0

题意:

给你一串括号序列,允许改动一个位置的括号(也就是‘(’改为‘)’,反过来也行),问你共有多少种方法,使得最终得到的括号合法。

思路:

我们从第一个字符跑到最后一个字符,对于每一个位置,我们只需要判断该位置之前的‘(’的数目和该位置之后的‘)’的数目,只有二者之差为1,该位置的字符才能改动,进而得到合法的序列。

另外,要注意的是在计算某个位置之前的‘(’的数目的时候,如果出现左括号数量已经小于右括号数量,那么后面所有的数目都要设置为-1;

代码中有更针对性的解释:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 1e6 + 100;

char st[maxn];
int dl[maxn], dr[maxn];

int main()
{
	//freopen("in.txt", "r", stdin);
	int n;
	while(cin >> n && n)
	{
		scanf("%s", st + 1);
		dl[0] = dr[n + 1] = 0;       //先初始化两边界
		int num = 0;
		for(int i = 1; i <= n; ++ i)
		{
			if(st[i] == '(')
				num ++;
			else 
				num --;
			if(num < 0 || dl[i - 1] < 0)    //判断是否出现不可挽回的非法现象,也就是中途是否出现num < 0 的情况,只要出现一次,之后也就全都是非法现象了
				dl[i] = -1;
			else 
				dl[i] = num;
		}
		num = 0;
		for(int i = n; i >= 1; -- i)   //同理
		{
			if(st[i] == ')')
				num ++;
			else 
				num --;
			if(num < 0 || dr[i + 1] < 0)
				dr[i] = -1;
			else 
				dr[i] = num;
		}
		int ans = 0;
		for(int i = 1; i <= n; ++ i)
		{
			if(dl[i - 1] >= 0 && dr[i + 1] >= 0)   //只有两端都没有出现过非法现象才行
			{
				int t = dl[i - 1] - dr[i + 1];
				if(t == 1 && st[i] == '(')       //只有差为1,或者-1才行
					ans ++;
				else if(t == -1 && st[i] == ')')
					ans ++;
			}
		}
		cout << ans << endl;
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值