[题解] 优先队列优化贪心&$CF2C$

[题解] 优先队列优化贪心&\(CF2C\)

原题链

做法

因为处理这个问号的时候具有不确定性,所以我们干脆把所有的问号在一开始的时候全部初始化成右括号,这个时候再来看如果右括号多了,就可以把一些问号变成的右括号转换成左括号,这个操作的代价就是\(a[i] - b[i]\)\(a[i],b[i]\)分别表示把第\(i\)个括号换成左括号和右括号的代价,那么就把所有的问号都用这种形式放到小根堆里即可。

这样做的一个好处就是不需要考虑一个括号是变成左括号还是右括号,转而只要考虑是否变成左括号,只需要在计算权值的时候稍微处理一下即可

代码

#include <bits/stdc++.h>
using namespace std;
priority_queue < pair < int , int > > q;//小根堆
int a[50010],b[50010];
string s;
string ss;
int main(){
    cin>>s;
    int cnt = 0,l = 0,r = 0;
    ss = s;
    for (int i = 0;i < s.length();i++) {
        if (s[i] == '(')l++;
        else if (s[i] == ')')r++;
        if (s[i] == '?') {
            ss[i] = ')';
            cin>>a[i]>>b[i];
            cnt++;
        }
    }
    if (s[0] == ')' || s[s.length() - 1] == '(' || abs(l - r) > cnt) {
        cout<<-1<<endl;
        return 0;
    }
    long long ans = 0;
    l = 0,r = 0;
    if (s[0] != '(')ss[0] = '(';//如果一开始就是问号那么一定改为左括号
    l++;
    for (int i = 1;i < ss.length();i++) {
        if (s[i] == '?')q.push(make_pair (b[i] - a[i],i));
        if (ss[i] == '(')l++;
        if (ss[i] == ')')r++;
        if (r > l) {
            pair < int , int > tmp = q.top();
            q.pop();
            int x = tmp.second;
            r--;l++;
            ss[x] = '(';
        }
    }
    if (l != r) {
        cout<<-1<<endl;
        return 0;
    }
    if (ss[ss.length() - 1] != ')') {
        cout<<-1<<endl;
        return 0;
    }
    for (int i = 0;i < s.length();i++) {
        if (s[i] == '?') {
            if (ss[i] == '(')ans += a[i];
            else if (ss[i] == ')')ans += b[i];
        }
    }
    cout<<ans<<endl;
    cout<<ss<<endl;
    return 0;
}
posted @ 2020-11-26 16:36  czyczy  阅读(114)  评论(0编辑  收藏  举报