【貪心】【CF3D】 Least Cost Bracket Sequence
阿新 • • 發佈:2018-11-11
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
可能需要貪心時,尋找題目的特殊性質,按照特殊性質進行貪心。