[CF3D] Least Cost Bracket Sequence

题目

原题地址

解说

被自己选的题卡了两节课……
首先,问号的状态会影响能否匹配,那么我们不妨就先让所有问号都为右括号,什么时候右括号太多了就把前面的问号改成左括号即可。
那么前面有多个问号的时候我们应该选择哪个?显然我们应该运用贪心思想,哪个问号改变后为我们减少的花费多我们就选哪个,这就需要我们维护一个优先队列,排序的依据是\(-b+a\)的大小(\(b\)是该问号改为右括号的价值,\(a\)是该问号改为左括号的价值)。我们每遇到一个问号就把它推进队列里,以备之后选用。每选用一个括号就把它改为左括号,同时修改我们的\(answer\)和计数器。
当然,在这个过程中我们还需要判断能否匹配。不匹配的情况总共两种:
1.发现右括号比左括号还多后前面却没有问号用来抵消
2.到最后发现左括号比右括号和问号的和还多
这时输出\(-1\)即可。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=50000+3;
typedef long long ll;
char s[maxn];
struct inf{//记录问号的位置和价值
	int loc;
	ll a,b;
	inf(int d,ll e,ll f){
		loc=d; a=e; b=f;
	}
	bool operator<(const inf &x)const{//排序依据
		return -b+a>-x.b+x.a;
	}
};
priority_queue<inf> q;
int main(){
	scanf("%s",s);
	int len=strlen(s),js=0;//js为计数器
	ll ans=0;
	for(int i=0;i<len;i++){
		if(s[i]=='(') js++;
		if(s[i]==')') js--;
		if(s[i]=='?'){
			js--;
			ll a,b;
			scanf("%lld%lld",&a,&b);
			q.push(inf(i,a,b));
			ans+=b;//默认为右括号
			s[i]=')';
		}
		if(js<0){//右括号太多了
			if(q.empty()){//解说里输出-1的情况一
				printf("-1");
				return 0;
			}
			inf k=q.top();
			ans=ans-k.b+k.a;//改为左括号
			js+=2;
			q.pop();
			s[k.loc]='(';
		}
	}
	if(js!=0){//解说里输出-1的情况二
		printf("-1");
		return 0;
	}
	printf("%lld\n",ans);
	printf("%s",s);
	return 0;
} 

幸甚至哉,歌以咏志。

posted @ 2020-05-17 18:10  DarthVictor  阅读(152)  评论(0编辑  收藏  举报
莫挨老子!