前言
t
a
g
:
tag :
tag: 括号序列
思维
难
传送门 :
题意 :
给定一个括号序列,询问有多少个合法位置,使得修改之后任然满足条件
条件 :
-
s
s
s中的
(
和)
数量相同 - 对于
s
s
s的任意前缀字符串,其中包含的
(
的数量均不少于)
的数量
思路 :
考虑操作的只有两种 :
- 将
(
改为)
, R = L + 2 R=L+2 R=L+2 - 将
)
改为(
, L = R + 2 L=R+2 L=R+2
L , R 指 的 是 字 符 串 中 左 右 括 号 的 数 量 L,R指的是字符串中左右括号的数量 L,R指的是字符串中左右括号的数量
我们考虑第一种操作 :
我们认为(
是向上的,)
是向下的
因为我们需要满足第二个条件
所以当
y
<
0
y<0
y<0的时候,必然是要做更改的
这时候我们发现我们更改前面任意一个)
都可以使得其满足条件,因此总共有
r
r
r个位置
因为操作只有一次,所以我们只需要判断后面的位置是否合法即可
如果不合法,显然是不能再操作了的,所以 0 0 0
否则总操作次数就是 r r r
我们考虑第二种操作 :
因为字符串是可翻转的,因此我们翻转之后同第一种情况
code:
int n;
string s;
int work(){
int cnt =0 ,r = 0 ;
for(int i = 0;i<n;i++){
if(s[i] == '(') cnt++;
else{
cnt -- ;
r++;//前面的右括号 序列
if(cnt < 0){//负数的时候开始统计答案
cnt += 2;//改变之后 开始判断是否合法
for(int j =i+1;j<n;j++){
if(s[j] =='(') cnt++;
else{
cnt -- ;
if(cnt <0) return 0;//如果后面不合法
}
}
return r;
}
}
}
return 0;
}
void solve(){
cin>>n>>s;
int l = 0 ,r = 0 ;
for(int i = 0 ;i<n; i++ )
if(s[i] == '(') l++;
else r ++;
if(r == l+2) cout<<work()<<endl;
else if(l == r+2){
reverse(all(s));
for(int i = 0;i<n;i++)
s[i] = (s[i] == '(')?')':'(';
cout<<work()<<endl;
}else cout<<0<<endl;
}