题意:将问号变为左、右括号(代价分别为为left[i],right[i])使得原序列合法,合法即为如题所述;
思路:贪心
先不考虑问号:判断一个一串括号合不合法:设置变量ans=0;遇到')',ans--,遇到')',ans++;最后判断ans中途中是否出现ans=-1&&最后ans是否为0即可;
对于有问号,先尝试将所有?变为),如果ans=-1时,判断前面是否有可用的“ 由问号变为的')' ”,如果有(包括其本身),选一个代价最小的变为'(',如果没有,直接flag=1标记为此序列不合法;
可用优先队列维护差值;
坑点:当)变为(,ans+=2;爆int
AC代码
#include <iostream>
#include <queue>
using namespace std;
typedef long long ll;
const int maxn=1e5;
struct point {
ll id;
ll cha;
friend bool operator < (point a,point b)
{
return a.cha>b.cha;
}
};
priority_queue<point>q;
char sto[maxn];
int main()
{
string st;
int flag=0;
cin>>st;
int ans=0,k=0;
ll sum=0,l,r;
point v,ss;
for (int i=0;i<st.length();i++)
{
if (st[i]=='?'||st[i]==')')
{
if (st[i]=='?')
{
cin>>l>>r;
v.cha=l-r;v.id=i;
q.push(v);
sum+=r;
}
sto[k++]=')';
ans--;
if (ans==-1)
{
if (q.empty())
flag=1;
else
{
ss=q.top();
q.pop();
sum+=ss.cha;
sto[ss.id]='(';
ans+=2;
}
}
}
else if (st[i]=='(')
{
ans+=1;
sto[k++]='(';
}
}
if (ans!=0||flag)
cout<<"-1"<<endl;
else
{
cout<<sum<<endl;
for (int i=0;i<k;i++)
cout<<sto[i];
cout<<endl;
}
return 0;
}