CF3D Least Cost Bracket Sequence

Least Cost Bracket Sequence

This is yet another problem on regular bracket sequences.

A bracket sequence is called regular, if by inserting "+" and "1" into it we get a correct mathematical expression. For example, sequences "(())()", "()" and "(()(()))" are regular, while ")(", "(()" and "(()))(" are not. You have a pattern of a bracket sequence that consists of characters "(", ")" and "?". You have to replace each character "?" with a bracket so, that you get a regular bracket sequence.

For each character "?" the cost of its replacement with "(" and ")" is given. Among all the possible variants your should choose the cheapest.

\(n\leq 5\times 10^4\).

题解

https://ksmeow.moe/lcbs_cf3d_sol/

解决的方法是使用贪心来做这个题。我们先贪心地让每个"?"变成右括号,当变成右括号时没有左括号与之匹配时,存在两个解决方法:把当前位置变为左括号或把当前位置之前的某一个"?"调整为左括号。实际上这两个问题是同一个问题,从当前位置往前统计所有没变成左括号的"?",并选择变为左括号产生的花费最少的一个转变即可。实现时维护一个存储"?"信息的堆即可选出最小值。

当最终仍然存在未匹配的左括号或需要左括号却无法产生时,即为无解的情况。

可以这样思考贪心算法的正确性:在贪心的情境下,问题可以看做将"?"全替换为")",并从原来的"?"位置里选出一些改为"(",并付出一定的花费,求花费最少的能将序列改为完全匹配序列的方案。这两个问题的答案是一致的,因为新问题可以看成原问题中,改成")"的花费为\(0\)而改成"("的花费为\(a_i-b_i\)后的问题,最小化后者同时也是最小化前者。每次从一个合法序列末尾放进一个")"时,需要找一个"("与之匹配,这个"("要么已经存在,要么需要从")"变过来,而变过来的时候上述方法实现了最小化。因此上述方法对新问题有正确性,对原问题也有正确性。

由于堆有每次\(O(\log n)\)的操作复杂度,算法总复杂度为\(O(n\log n)\),且空间为\(O(n)\),可以通过本题。

CO int N=5e4+10;
char s[N];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > pq;

int main(){
	scanf("%s",s+1);
	int n=strlen(s+1);
	int cnt=0;
	int64 ans=0;
	for(int i=1;i<=n;++i){
		if(s[i]=='?'){
			int a=read<int>(),b=read<int>();
			s[i]=')';
			ans+=b,pq.push({a-b,i});
		}
		if(cnt==0 and s[i]==')'){
			if(pq.empty()) {puts("-1"); return 0;}
			pair<int,int> x=pq.top();pq.pop();
			s[x.second]='(';
			if(x.second<i) cnt+=2;
			ans+=x.first;
		}
		cnt+=s[i]=='('?1:-1;
	}
	if(cnt!=0) {puts("-1"); return 0;}
	printf("%lld\n%s",ans,s+1);
	return 0;
}

posted on 2020-05-15 16:08  autoint  阅读(120)  评论(0编辑  收藏  举报

导航