威廉有一个最喜欢的括号序列。由于他最喜欢的序列相当大,他将其作为正整数序列C1, C2, ., Cn提供给你,其中c是连续括号的个数”(“如果i是奇数或连续括号的个数”)“如果I是偶数。例如,对于括号序列“((())())”,对应的数字序列为[3, 2,1,3].您需要找到连续子序列(子段)的总数[2,r] (l <正则括号序列。R)的原始括号序列,即如果在括号序列中插入字符“+”和“1”,可以得到正确的算术表达式,则称为正则括号序列。例如,序列 "(())()","()" 和 "(() (()))" 是常规,而 ") (", "(()" 和 "(())) (" 不是。输入第一行包含一个整数n (1 <n 1000),即压缩序列的大小。第二行包含一个整数序列C1, C2,..,Cn (1 <c < 10°)为压缩序列。输出输出一个整数,表示原始括号序列的子段总数,这些子段是规则的括号序列。可以证明答案符合带符号的64位整数数据类型。
Examples
input
Copy
5 4 1 2 3 1
output
Copy
5
input
Copy
6 1 3 2 1 2 4
output
Copy
6
input
Copy
6 1 1 1 1 2 2
output
Copy
7
请注意在第一个示例中,描述了sequence()))(。此括号序列包含5个子段,它们构成规则的括号序列:1. 从第3个字符到第10个字符的子序列:(()(()))2. 从第4到第5个字符的子序列:()3.第4到第9个字符的子序列:()(())4. 从第6到第9个字符的子序列:(())5. 从第7到第8个字符的子序列:()在第二个示例中,描述了sequence()))(()()))))。在第三个例子中,描述了sequence()()(())。
题解:
数据范围只有1000,我们直接暴力枚举左边界,把左边界多余的与右边多余的匹配,n^2的复杂度
具体细节在代码中均有注释
#include<iostream>
#include<string>
#include<vector>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
#define int long long
typedef pair<int,int> PII;
int a[1005];
void solve()
{
int n;
cin >> n;
for(int i = 1;i <= n;i++)
{
cin >> a[i];
}
if(n % 2)
n--;//奇数位为(
int ans = 0;
for(int i = 1;i + 1 <= n;i += 2)
{
if(a[i] < a[i+1])
{
ans += a[i];小于第一个右括号数量,只能匹配左括号数量那么多
}
else
{
ans += a[i + 1];
int last = a[i] - a[i + 1];//记录多余的右括号数量
int now = 0;
for(int j = i + 2;j + 1<=n;j += 2)
{
now += a[j + 1] - a[j];//记录多余的左括号数量
if(now >= 0)
{
ans += min(now,last) + 1;//为啥这里要加1下面有图解
last -= now;
if(last < 0)
break;
now = 0;
}
}
}
}
cout << ans;
}
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);cout.tie(0);
int t = 1;
// cin >> t;
// scanf("%lld",&t);
while (t--)
{
solve();
}
return 0;
}
本身右边一些
已经能匹配的算一种