D. Least Cost Bracket Sequence

D. Least Cost Bracket Sequence
time limit per test1 second
memory limit per test64 megabytes
inputstandard input
outputstandard output
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.

Input
The first line contains a non-empty pattern of even length, consisting of characters “(”, “)” and “?”. Its length doesn’t exceed 5·104. Then there follow m lines, where m is the number of characters “?” in the pattern. Each line contains two integer numbers a i and b i (1 ≤ a i,  b i ≤ 106), where a i is the cost of replacing the i-th character “?” with an opening bracket, and b i — with a closing one.

Output
Print the cost of the optimal regular bracket sequence in the first line, and the required sequence in the second.

Print -1, if there is no answer. If the answer is not unique, print any of them.

Examples
input
(??)
1 2
2 8
output
4
()()


题解:题目大意将给定的字符串中的**?**全部都换成左括号或者右括号,保证使所有的括号都可以配对且要求代价最低,输入样例参数表示第i个括号 左括号和右括号的代价。

思路,要求最小代价且要保证所有括号都可以配对,首先想想是否可以贪心。
将字符串中所有的?全部换成)。遍历一遍字符串,如果是(,待配对参数a++,如果是?,将?换成),待配对参数a–,并且将该点保存起来,如果a<0时,则说明此时?前面没有多余的(让我们用来配对了,此时要把之前?变成)的位置找一个合适的出来转化成(。重点是要找一个合适的位置将)变成(,而我们在当时存储点的时候,需要记录左括号的代价和右括号的代价,每次需要将)变成(的时候我们都要取它俩差值最大的那个位置用来变化,这样就可以使得我们最后的代价最小。
所有可以用数据结构中的优先队列来存储我们需要的数据。


#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<stack>
const int maxn=1e5+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
using namespace std;
char str[maxn];
int a;
ll res;
priority_queue< pair<ll,int> >q;
int main(){
	ll x,y;
	scanf("%s",&str);
	for(int i=0;i<strlen(str);i++){
		if(str[i]=='('){
			a++;
		}
		else if(str[i] == ')'){
			a--;
		}	
		else{
			scanf("%lld %lld",&x,&y);
			str[i] = ')';
			a--;
			res += y;
			q.push(make_pair(y-x,i));
		}
		if(a<0){
			if(q.size() == 0 ) break;
			pair<ll,int> temp = q.top();
			q.pop();
			res -= temp.first;
			str[temp.second] = '(';
			a+=2;
		}
	} 
	if(a!=0){
		cout<<"-1"<<endl;
	}
	else{
		cout<<res<<endl;
		cout<<str<<endl;
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值