1. 程式人生 > >【貪心】【CF3D】 Least Cost Bracket Sequence

【貪心】【CF3D】 Least Cost Bracket Sequence

傳送門

Description

給一個序列,序列裡面會有左括號、問號、右括號。對於一個\(?\)而言,可以將其替換為一個\((\),也可以替換成一個\()\),但是都有相應的代價。問:如何替換使得代價最小。前提是替換之後的序列中,括號是匹配的。如果不能替換為一個括號匹配的序列則輸出-1。

Input

第一行是序列,序列長度不超過\(5~\times10^4\),下面m(m是\(m\)的數量)行有每行\(2\)個數據,第一個是\((\)的代價,第2個是\()\)的代價

Output

第一行輸出最小代價

第二行輸出被轉換的序列

Sample Input

(??)
1 2
2 8

Sample Output

4
()()

Solution

顯然DP可做,然而資料範圍太大。

DP不能就嘗試一下貪心。

考慮一個特殊性質:對於一個括號序列,如果想要保證他合法,則必須保證在任意一個位置,其字首左括號數必須不小於右括號數。否則一定不合法。同時這個條件是括號序列合法的充要條件。於是考慮按照這個性質貪心,對於任意一個可以修改的位置,貪心的修改成右括號。當序列不合法時,貪心選取修改代價最小的位置改成左括號。因為修改左括號不會使序列不合法,所以這個貪心使正確的。

Code

#include<queue>
#include<cstdio>
#include<cstring>
#define rg register
#define ci const int
#define cl const long long int

typedef long long int ll;

namespace IO {
    char buf[90];
}

template<typename T>
inline void qr(T &x) {
    rg char ch=getchar(),lst=' ';
    while(ch>'9'||ch<'0') lst=ch,ch=getchar();
    while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    if(lst=='-') x=-x;
}

template<typename T>
inline void qw(T x,const char aft,const bool pt) {
    if(x<0) x=-x,putchar('-');
    int top=0;
    do {
        IO::buf[++top]=x%10+'0';
        x/=10;
    } while(x);
    while(top) putchar(IO::buf[top--]);
    if(pt) putchar(aft);
}

template<typename T>
inline T mmax(const T a,const T b) {return a > b ? a : b;}
template<typename T>
inline T mmin(const T a,const T b) {return a < b ? a : b;}
template<typename T>
inline T mabs(const T a) {return a < 0 ? -a : a;}

template<typename T>
inline void mswap(T &a,T &b) {
    T temp=a;a=b;b=temp;
}

const int maxn = 50010;

struct M {
    int l,r;
};
M MU[maxn];

struct Zay {
    int pos,v;
    inline bool operator<(const Zay &_others) const {
        return this->v > _others.v;
    }
    Zay (ci _a=0,ci _b=0) {pos=_a,v=_b;}
};

char st[maxn];
std::priority_queue<Zay>Q;

int main() {
    scanf("%s",st+1);
    int l=strlen(st+1);
    if(l&1) return puts("-1")&0;
    for(rg int i=1;i<=l;++i) if(st[i] == '?') {
        qr(MU[i].l);qr(MU[i].r);
    }
    rg int cnt=0;ll _ans=0;
    for(rg int i=1;i<=l;++i) {
        if(st[i] == '(') ++cnt;
        else if(st[i] == ')') --cnt;
        else {
            --cnt;Q.push(Zay(i,MU[i].l-MU[i].r));
            st[i]=')';_ans+=MU[i].r;
        }
        while(cnt<0) {
            if(Q.empty()) return puts("-1")&0;
            int h=Q.top().pos;Q.pop();
            _ans+=MU[h].l-MU[h].r;
            st[h]='(';
            cnt+=2;
        }
    }
    if(cnt > 0) return puts("-1")&0;
    qw(_ans,'\n',true);
    printf("%s",st+1);
    return 0;
}

Summary

可能需要貪心時,尋找題目的特殊性質,按照特殊性質進行貪心。