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.

(nleq 5 imes 10^4).

题解

https://ksmeow.moe/lcbs_cf3d_sol/

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

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

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

由于堆有每次(O(log n))的操作复杂度,算法总复杂度为(O(nlog 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
%s",ans,s+1);
	return 0;
}
原文地址:https://www.cnblogs.com/autoint/p/12895532.html