P10115 题解(2023 激励计划评分 7)
_XHY20180718_ · · 题解
本来觉得这题挺不错的,但数据被暴力草过去了,所以给
简要题意:
给你一个括号序列和
每个组的权值:若括号序列合法,则为
求组的权值之和的最大值。
主要思路:
先写暴力,设
易得转移方程:
我们将合法与不合法情况分开来讨论:
当我们从不合法情况来转移时:
由于
而当我们从合法的情况来转移时:
于是我们将
对于每一个
将上面两种情况比较即可,也就是说:
接下来要讨论的问题是如何快速算出
设
对于作为一个右括号的
所以,对于一个
而对于第三种情况,由于两个括号序列可以合成一个新序列,那我们的
所以:
结合:
于是这题我们就做完了。
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e6+5,inf=1e18;
int n,a[N],lst[N],r;
int f[N],st[N],c[N];
bool b[N];
string S;
signed main(){
// freopen("test.in","r",stdin);
// freopen("std.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>S;
for(int i=1; i<=n; ++i)
cin>>a[i],b[i]=(S[i-1]=='(');
for(int i=1; i<=n; ++i)
if(!b[i]&&r)lst[i]=st[r--];
else if(b[i])st[++r]=i;
for(int i=0; i<=n; ++i)
f[i]=c[i]=-inf;f[0]=0;
for(int i=1; i<=n; ++i){
f[i]=f[i-1];
if(lst[i]){
c[i]=max(c[lst[i]-1],f[lst[i]-1]-a[lst[i]]);
f[i]=max(c[i]+a[i],f[i]);
}
}cout<<f[n];
return 0;
}