我是靠谱客的博主 有魅力橘子,这篇文章主要介绍ATcoder-[AGC048B]Bracket Score【结论,贪心】正题,现在分享给大家,希望可以做个参考。

正题

题目链接:https://atcoder.jp/contests/agc048/tasks/agc048_b


题目大意

长度为 n n n的合法括号序列可以包含 [ . . . ] [...] [...] ( . . . ) (...) (...)

如果在第 i i i个位置是 ′   (   ′ ' ( '  (  或者 ′   )   ′ ' ) '  ) 那么可以获得 a i a_i ai的权值,否则获得 b i b_i bi的权值。

求一个合法的括号序列使得权值最大。


解题思路

首先对于每对匹配的括号肯定是一奇一偶的,有一个结论就是只要两种括号的奇和偶数上括号的个数相同,那么就一定有一种合法匹配。

大致的理解方法就是,对于每一种方案至少存在一对相邻的同种括号,否则就不满足以上性质,然后就可以将这对括号删去。重复以上过程就可以证明该结论

那么考虑贪心选取,对于每个位置我们先默认选择小括号,那么如果转换的话就会获得 w i = a i − b i w_i=a_i-b_i wi=aibi的价值。然后每次选取一奇一偶的 w i w_i wi,把奇偶的 w i w_i wi分开排序选取即可。

时间复杂度 O ( n log ⁡ n ) O(nlog n) O(nlogn)


c o d e code code

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define ll long long using namespace std; const ll N=1e5+10; ll n,a[N],b[N],sum,ans; vector<ll > v[2]; int main() { scanf("%lld",&n); for(ll i=1;i<=n;i++)scanf("%lld",&a[i]); for(ll i=1;i<=n;i++)scanf("%lld",&b[i]),sum+=b[i]; for(ll i=1;i<=n;i++) v[i&1].push_back(a[i]-b[i]); sort(v[0].begin(),v[0].end()); sort(v[1].begin(),v[1].end()); ans=sum; for(ll i=v[0].size()-1;i>=0;i--) sum+=v[0][i]+v[1][i],ans=max(ans,sum); printf("%lldn",ans); }

最后

以上就是有魅力橘子最近收集整理的关于ATcoder-[AGC048B]Bracket Score【结论,贪心】正题的全部内容,更多相关ATcoder-[AGC048B]Bracket内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(109)

评论列表共有 0 条评论

立即
投稿
返回
顶部