0718题解-FOIWC实在是太美

Posted dqk2003

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了0718题解-FOIWC实在是太美相关的知识,希望对你有一定的参考价值。

题目描述

艾斯洛克希望你送给她一个长度为(N)的合法括号序列,保证(N)是偶数。你在序列的第(i)位放左括号的代价为(A_i) ,放右括号的代价为(B_i)。艾斯洛克不想让你太麻烦,所以希望你支付最小的代价。不过才不是担心你呢!真的不是哦!虽然众所周知,但艾斯洛克还是给了你合法括号序列的定义,以防你这个八嘎会错意了:

  1. 空序列是合法括号序列;

  2. 如果(A)是合法括号序列,那么((A))是合法括号序列;

  3. 如果(A,B)都是合法括号序列,那么(AB)是合法括号序列。

"知......知道了的话就快去准备吧!虽然我也不是很期待就是了!!”艾斯洛克说。

思路&题解

(n^2)的dp很简单,主要是思考怎么贪心,我在考场上已经想到了带反悔贪心,并且用堆实现,但是没有想到正确的贪心决策方法。
我自己在考场上想到是先贪心选择小的代价,如果左括号不够的话再反悔前面的价值大的右括号,最后如果左括号多了的话,再反悔处理
最后反悔我是找最右边的反悔,然后删去左侧最大反悔代价的括号。但是是错的,可以举出反例,比如最后一个匹配了最大的,次大的在最大的右边,
且中间还有一些比较小代价的括号。我们可以把当前最右侧的和次大的匹配,然后后面的匹配最大的,否则的话,次大的可能要反悔但是不优。
其实这里贪心没有想到一个重要的性质
一个合法的括号序列,如果一个右括号变成左括号,一定可以在它的后边(包括自己)把一个左括号再变回右括号形成一个新的合法括号序列。可以考虑折线图来证明
我们考虑增量法来贪心,假设当前构造好了长度为i的且合法的最小代价的括号序列,我们增加两个位置怎么办。
由于要求合法,所以最后一个是右括号,而倒数第二个可以是右括号,也可以是左括号。右括号直接就是合法的,左括号的话要从前面再找一个右括号进行反悔,肯定是找最小的代价反悔
所以我们把右括号的A-B放入小根堆,然后贪心的选择即可。(看来增量法应该是和反悔贪心有联系的)

#include<bits/stdc++.h>
using namespace std;
#define LL long long 
const int N = 3e5 + 11;
int n;
LL A[N], B[N];
priority_queue<LL, vector<LL>, greater<LL> > q;
int main(){
	freopen("beautiful.in", "r", stdin);
	freopen("beautiful.out", "w", stdout);
	cin>>n;
	for(int i = 1;i <= n; i++){
		scanf("%lld", &A[i]);
	}
	for(int i = 1;i <= n; i++){
		scanf("%lld", &B[i]);
	}
    LL ans = A[1] + B[2];
    q.push(A[2] - B[2]);
    for(int i = 3;i <= n; i += 2){
        LL cur = q.top(); 
        if(cur + B[i] + B[i+1] <= A[i] + B[i+1]){
            ans += cur + B[i] + B[i+1];
            q.pop(); q.push(A[i] - B[i]); q.push(A[i+1] - B[i+1]);
        }
        else{
            ans += A[i] + B[i+1];
            q.push(A[i+1] - B[i+1]);
        }
    }
    cout<<ans<<endl;
	return 0;
}








以上是关于0718题解-FOIWC实在是太美的主要内容,如果未能解决你的问题,请参考以下文章

又一次发现Oracle太美之orainstRoot.sh

灵蓄助力太美医疗构建行业SaaS平台

web前端开发JQuery常用实例代码片段(50个)

那句子太美,我不敢看

我无法从 firebase 获取下载网址()。请任何人帮助这是我的代码和错误。 (我正在使用片段)[重复]

[西湖论剑2022]Misc-机你太美