题目
题解思路
连续的两个数字组成的每对合法的括号对(())的贡献等于 合法匹配对的个数 + 和之前的连续合法对的组合(即加上之前的数量)
(())() 第2对个的贡献是 1 + 1
()()() 第3对个的贡献是 1 + 2
()(()) 第2个对的贡献是 2 + 1
还有一些不等的对的情况
()((())())
((())这种不匹配的时候要将它之后的连续贡献取成1,但是在它和之后多的右括号合并之后又有可能连上之前的连续括号对,然后连续贡献又边大了。
所以这里用到了两个栈。
一个栈存多的右括号
另一个存贡献。
即将有潜力的压入栈中。
())当右括号多的时候我们去栈中的多的括号看看能不能匹配。即将栈中有潜力的左括号和此时多的右括号合并。
结合以上规律
利用两个栈来模拟这个过程即可。
括号匹配写少了。
AC代码
#include <bits/stdc++.h>
//#include <unordered_map>
//priority_queue
#define PII pair<int,int>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1000010 ;
stack <long long > cs ;
stack <long long > yu ;
long long a[N] ;
long long ans ;
void slo(int x )
{
while (yu.size())
{
long long tp = yu.top() ;
yu.pop() ;
if ( tp == x )
{
ans += tp ;
if (cs.size())
{
int d = cs.top() ;
cs.pop();
ans += d ;
cs.push(d+1);
}else
cs.push(1);
return ;
}else
{
if ( tp > x )
{
ans += x ;
tp -= x ;
yu.push(tp);
cs.push(1);
return ;
}else
{
ans += tp ;
x -= tp ;
if (cs.size())
{
ans += cs.top() ;
cs.pop();
}
}
}
}
}
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int n ;
cin >> n ;
for (int i = 1 ; i <= n ; i++ )
cin >> a[i] ;
for (int i = 1 ; i <= n ; i++ )
{
if (i%2)
{
yu.push(a[i]);
}else
slo(a[i]);
}
cout << ans << "\n" ;
return 0 ;
}