奶牛贝茜逃跑了,躲在了长满高草的山脊上。
农夫约翰为了抓回贝茜,决定在草地中匍匐前行,从而不被贝茜发现。
不幸的是,发现贝茜并没有那么容易。
约翰面前的草看起来像是一个长度为 NN 的括号字符串,例如:
)((()())())
约翰清楚贝茜的后腿看上去就像一对相邻的左括号 ((
,她的前腿看上去就像一对相邻的右括号 ))
。
因此,贝茜的位置可以用一对索引 x<yx<y 来描述,使得 ((
在位置 xx 处被找到,))
在位置 yy 处被找到。
请计算贝茜可能站立的不同位置的数量。
输入格式
共一行,包含一个长度为 NN 的括号字符串。
输出格式
输出贝茜可能站立的不同位置的数量。
数据范围
1≤N≤500001≤N≤50000
输入样例:
)((()())())
输出样例:
4
样例解释
44 种可能的站立位置如下所示:
1. )((()())())
^^ ^^
2. )((()())())
^^ ^^
3. )((()())())
^^ ^^
4. )((()())())
^^ ^^
思路:
贝茜的位置可以用一对索引 x<y 来描述,使得 ((
在位置 x 处被找到,))
在位置 y 处被找到。
所以每个((
乘它后面出现过的))
的数量,相加即是答案。
代码如下:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
typedef long long ll;
const int N = 5e4 + 10;
int cnt1, cnt2;
string a;
int res1[N], res2[N];
ll ans;
int main() {
ios::sync_with_stdio(false);
cout.tie(0);
cin >> a;
for(int i = 0; i < a.size() - 1; i ++) {
if(a[i] == '(' && a[i + 1] == '(') {
cnt1 ++;
res1[i + 1] = 1; // 记录后腿的位置
}
if(a[i] == ')' && a[i + 1] == ')') {
cnt2 ++;
res2[i + 1] = 1; // 记录前腿的位置
}
}
for(int i = a.size() - 1; i >= 0; i --)
res2[i] += res2[i + 1]; // 对每个位置前腿的数量进行预处理
for(int i = 0; i < a.size(); i ++)
ans += res1[i] * res2[i]; // 统计答案
cout << ans;
return 0;
}