思路分析:其实刚刚看到这道题时想到的是从两边向中间以此修改问号,但是由于问号可能存在嵌套情况,于是这样做显然不行。
这道题需要用到的是贪心的思路,当我们处理到一个位置时,统计一下它左边的未匹配的‘(’数量,如果当前位置是问号并且左边存在未匹配的‘(’,那么我们就把问号变成‘)’并把它变为‘(’需要的花费作为排列标准放入优先队列,当我们处理到一个问号或‘)’而左边不存在未匹配‘(’时,我们就看一下队列是否为空,空的话直接输出-1即可,如果不为空,那么取出队首元素,并把它变为‘(’,那么当前位置未匹配‘(’的数量就增加了2,这样处理完成后,如果左边还有未处理的‘(’直接输出-1就行了,否则就输出过程中填出的字符串。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 typedef long long ll; 7 const int N=1e6+10; 8 char c1[N],c2[N]; 9 struct Node{ 10 int l,r,num; 11 Node(int a,int b,int c){ 12 l=a;r=b;num=c; 13 } 14 bool operator < (const Node &a)const{ 15 return (a.l-a.r)<(l-r);//用l-r的值进行排列 16 } 17 }; 18 priority_queue<Node>q; 19 int main(){ 20 scanf(" %s",c1);//原数列 21 ll ans=0,cnt=0;//答案和左边'('数量 22 for(int i=0;i<strlen(c1);++i){ 23 if(c1[i]=='('){ 24 cnt++; 25 c2[i]='('; 26 } 27 else{ 28 cnt--;//'('被匹配,cnt-- 29 c2[i]=')'; 30 if(c1[i]=='?'){ 31 int x,y; 32 scanf("%d%d",&x,&y); 33 ans+=(ll)y; 34 q.push(Node(x,y,i)); 35 } 36 if(cnt<0){//左边没有'(' 37 if(q.empty()){//队列为空直接输出-1 38 printf("-1 "); 39 return 0; 40 } 41 cnt+=2;//原来被匹配的'('也腾了出来 42 Node u=q.top();q.pop(); 43 c2[u.num]='('; 44 ans+=(ll)(u.l-u.r); 45 } 46 } 47 } 48 if(cnt!=0) printf("-1 ");//得不出答案 49 else{ 50 printf("%lld %s ",ans,c2); 51 } 52 return 0; 53 }