【题目链接】
失踪人口回归
题意分析
每一个问号 都可以被填为左括号或者右括号 并且有相应的代价
要求使用最小的代价使得最后的序列左右括号是匹配的 如果实在无法匹配就输出"-1"
这里的话 有一个非常有意思的思路 一开始把所有问号都填成右括号 然后顺序扫描 遇到无法匹配的情况的话 就把问号修改为左括号
那么如果做到代价最小呢 只要我们维护一下之前问号情况 看看哪一个由右括号变成左括号需要的代价是最小的就可以了 这个我们可以使用堆来维护
那么什么情况是硬核无法匹配呢?
1.问号全部填成左括号或者右括号 还是无法满足数量差
2.初始字符串开头就是右括号或者末尾就是左括号
3.最后填完之后无法做到数量相当
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#define M 1008611
#define Pa pair<int,int>
using namespace std;
int len,nl,nr,tot;
long long ans;
char s1[M],s2[M];
int cdy[M],wzy[M];
priority_queue<Pa,vector<Pa >,greater<Pa > > que;
int main()
{
scanf("%s",s1+1);len=strlen(s1+1);
for(int i=1;i<=len;++i)
{
if(s1[i]=='?')
{
scanf("%d%d",&cdy[i],&wzy[i]);
s2[i]=')';
++tot;
}
else
{
s2[i]=s1[i];
if(s1[i]=='(') nl++;
if(s2[i]==')') nr++;
}
}
if(s1[1]==')'||s1[len]=='(')
{
printf("-1");
return 0;
}
if(abs(nl-nr)>tot)
{
printf("-1");
return 0;
}
if(s1[1]=='?') s2[1]='(';
nl=nr=0;
for(int i=1;i<=len;++i)
{
if(s2[i]=='(') ++nl;
if(s2[i]==')') ++nr;
if(s1[i]=='?'&&i!=1) que.push(make_pair(cdy[i]-wzy[i],i));
if(nr>nl)
{
int now=que.top().second;que.pop();
s2[now]='(';
--nr;++nl;
}
}
if(nl!=nr)
{
printf("-1");
return 0;
}
for(int i=1;i<=len;++i)
if(s1[i]=='?')
{
if(s2[i]=='(') ans+=cdy[i];
if(s2[i]==')') ans+=wzy[i];
}
printf("%lld
",ans);
for(int i=1;i<=len;++i) putchar(s2[i]);
return 0;
}