1 条题解
-
0
自动搬运
来自洛谷,原作者为

XHY20180718
不拿 7 级钩不改个签搬运于
2025-08-24 22:54:49,当前版本为作者最后更新于2024-01-29 13:55:40,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
本来觉得这题挺不错的,但数据被暴力草过去了,所以给 分。
简要题意:
给你一个括号序列和 数组,将其分成连续的若干组。
每个组的权值:若括号序列合法,则为 ,否则为 。
求组的权值之和的最大值。
主要思路:
先写暴力,设 表示在当前位置 后分组 之间所有组的最大权值。
易得转移方程:
我们将合法与不合法情况分开来讨论:
当我们从不合法情况来转移时:
由于 本身单调递增,所以说:
而当我们从合法的情况来转移时:
$$f_i=(\max_{[j+1,i]\text{为合法区间}}\{f_j-a_{j+1}\})+a_i $$于是我们将 打包,因为其对于每个 都是不变的。
对于每一个 ,用 来维护他:
将上面两种情况比较即可,也就是说:
接下来要讨论的问题是如何快速算出 :
设 , 为合法括号序列,则所有合法括号序列满足以下情况:
- ,最基本的括号序列。
- ,一个括号将一个合法括号序列括起来依然是合法括号序列。
- ,两个合法括号序列拼起来依然是合法括号序列。
对于作为一个右括号的 来说,我们完全可以通过栈找出与他合起来的最近左括号,其位置记为 。
所以,对于一个 ,我们完全可以找出 ,除了第三种情况都可以解决,然后就能套上面的式子,给 赋初值:。
而对于第三种情况,由于两个括号序列可以合成一个新序列,那我们的 就能从 转移过来,因为集合 将严格包含集合 ,唯一多的元素便是 。
所以:
结合:
于是这题我们就做完了。
代码:
#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; }
- 1
信息
- ID
- 9439
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者