Description
给出一个括号序列,中间有一些问号,将第i个问号换成左括号代价是a[i],换成右括号代价是b[i],问如果用最少的代价将这个括号序列变成一个合法的括号序列
Input
第一行一个括号序列,假设其中有m个问号,则之后输入m行,每行两个整数a[i]和b[i]表示把第i个问号换成左括号或右括号的代价(括号序列长度不超过5e4,1<=a[i],b[i]<=1e6)
Output
如果不存在一种合理的替换方案使得该序列变成一个合法的括号序列则输出-1,否则输出最小代价和替换后的合法括号序列
Sample Input
(??) 1 2 2 8
Sample Output
4 ()()
分析
先把问号变成右括号,如果有问题就再把之前的问号变的右括号变成左括号,之前的代价是b[i]现在的代价是a[i],为使总代价最小我们从中选取a[i]-b[i]最小,也就是b[i]-a[i]最大的去重新变,所以用优先队列维护出现过的问号的b[i]-a[i]的值和其位置即可。
代码
#include<cstdio> #include<cstring> #include<stack> #include<queue> using namespace std; #define ll long long const int INF = 0x3f3f3f3f; const int maxn = 5e5+10; char s[maxn]; int a[maxn],b[maxn]; priority_queue<pair<int,int> >que; int main(){ while(~scanf("%s",s)){ int len=strlen(s); ll ans=0; for(int i=0;i<len;i++) if(s[i]=='?'){ scanf("%d%d",&a[i],&b[i]); ans+=b[i]; } int cnt=0,g=0; while(!que.empty())que.pop(); for(int i=0;i<len;i++){ if(g)break; if(s[i]=='(')cnt++; else{ cnt--; if(s[i]=='?')que.push(pair<int,int>(b[i]-a[i],i)),s[i]=')'; if(cnt<0){ if(que.empty())g=1; else{ pair<int,int> temp=que.top(); que.pop(); ans-=temp.first; cnt+=2; s[temp.second]='('; } } } } if(cnt!=0)g=1; if(g)printf("-1 "); else printf("%lld %s ",ans,s); } return 0; }