题目描述
给定一个带"(" “)” “?” 的括号序列,而每个"?“都可以付出一定的代价变成”(“或者”)",问将这个括号序列变成合法括号序列的最小代价?特别的,对于无法得到答案的输出"-1".
分析
一个显然的结论就是我们把"?“变成”)“后可以花费 a − b a-b a−b的代价,于是你就可以发现啊这是一个经典的返悔贪心(具有转化代价),策略也十分明显,即碰见”?“就把他先变成”)",然后边处理边计算,如果括号无法匹配{ “)“数量大于”(” }就把前面a-b最小的"?“变成”(",于是从而也知道我们还需要一个优先队列进行维护,于是这题差不多就没了
细节
我们需要一个tot来统计"("的数量,最后的有无解的判断则看tot是否为0即可
还要注意的就是我们把一个?从)变成(时tot是加2而非1
code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
ll min(ll a,ll b){if(a<b)return a;else return b;}
ll max(ll a,ll b){if(a>b)return a;else return b;}
inline ll read()
{
ll s = 0,w = 1;
char c = getchar();
while(c < '0' || c > '9')
{
if(c=='-')w = -1;c = getchar();
}
while(c >= '0' && c <= '9')
{
s = s *10 + c - '0';c = getchar();
}
return s*w;
}
inline void write(int x)
{
if(x < 0)
{
putchar('-');
x=-x;
}
if(x > 9)write(x/10);
putchar(x%10 + '0');
}
const int MAX = 5e4+10;
const int MOD = 1e9+7;
const ll INF = 0x3f3f3f3f3f3f;
string s1,s2;
struct node
{
int a,b,id;
friend bool operator < (node a,node b)
{
return a.a-a.b > b.a-b.b;
}
};
int place[MAX];
priority_queue<node>q;
ll ans;
int tot;
int main()
{
// freopen("date.in","r",stdin);
// freopen("zhengjie.out","w",stdout);
cin>>s1;
int fuck=0;
for(int i=0;i<s1.size();i++)
{
if(s1[i]=='(')s2+='(',fuck++;
if(s1[i]==')')s2+=')',fuck--;
if(s1[i]=='?')
{
ll s=read();
ll b=read();
s2+=')';
fuck--;
ans+=b;
q.push((node){s,b,i});
}
if(fuck<0)
{
if(q.empty())puts("-1"),exit(0);
node tmp=q.top();q.pop();
ans+=tmp.a-tmp.b;
s2[tmp.id]='(';
fuck+=2;
}
}
if(fuck!=0)puts("-1"),exit(0);
cout<<ans<<endl;
cout<<s2<<endl;
return 0;
}