题意:
给定括号串s,串中有若干问号?
每个问号可以选填(或者),代价分别为a[i]和b[i],
问将括号串变成合法串的最小代价,输出方案
数据范围: |s|<=5e4
解法:
妙啊:
默认所有括号都是右括号,然后从左往右遍历:
如果左括号不够了,就从左边问号的地方贪心地取出一个最优的变成左括号.
取最优可以用堆实现,做法显然正确!
code:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxm=5e4+5;
char s[maxm];
int a[maxm],b[maxm];
int n;
typedef pair<int,int> PI;
signed main(){
scanf("%s",s+1);
n=strlen(s+1);
ll ans=0;
for(int i=1;i<=n;i++){
if(s[i]=='?'){
scanf("%d%d",&a[i],&b[i]);
ans+=b[i];
}
}
priority_queue<PI,vector<PI>,greater<PI> >q;
int sum=0;
for(int i=1;i<=n;i++){
if(s[i]=='('){
sum++;
}else if(s[i]==')'){
sum--;
}else if(s[i]=='?'){
s[i]=')';
sum--;
q.push({-b[i]+a[i],i});
}
if(sum<0){
if(q.empty()){
puts("-1");
return 0;
}else{
int x=q.top().first;
int id=q.top().second;
q.pop();
s[id]='(';
ans+=x;
sum+=2;//少了一个')',多了一个'(',所以是+=2
}
}
}
if(sum!=0){//这里别忘了
puts("-1");
return 0;
}
printf("%lld\n",ans);
puts(s+1);
return 0;
}