题目链接
题意:
给你一个含有(,),?的序列,每个?变成(或)有一定的花费,问变成课匹配的括号的最小花费。
分析:
首先如果能变成匹配的,那么就有右括号的个数始终不多于左括号且左右括号数量相等,那就好办了,从头到尾跑一次就可以了,然后所有?变成),如果右括号多了,找一个变成左括号,当然一次最多变一个,然后用一个优先队列维护就好了。
代码:
#include <cstdio> #include <cstring> #include <queue> using namespace std; const int maxn=5e4+10; char a[maxn]; int jl[maxn]; int bz[maxn]; int by[maxn]; priority_queue<pair<int,int> > qu; int main(){ scanf("%s",a+1); int n=strlen(a+1); for(int i=1;i<=n;i++){ if(a[i]=='?') jl[i]=-1; if(a[i]==')') jl[i]=1; } for(int i=1;i<=n;i++) if(jl[i]==-1) scanf("%d%d",&bz[i],&by[i]); int z=0,y=0; long long ans=0; for(int i=1;i<=n;i++){ if(!jl[i]) z++; if(jl[i]==1) y++; if(jl[i]==-1){ y++; jl[i]=1; ans+=(long long)by[i]; qu.push(make_pair(by[i]-bz[i],i)); } if(y>z){ if(qu.empty()){ printf("-1"); return 0; } y--; z++; ans-=(long long)qu.top().first; jl[qu.top().second]=0; qu.pop(); } } if(y!=z){ printf("-1"); return 0; } printf("%lld ",ans); for(int i=1;i<=n;i++) if(jl[i]==0) printf("("); else printf(")"); return 0; }