CF3D Least Cost Bracket Sequence

题目

题意翻译
给一个序列,序列里面会有左括号、问号、右括号。对于一个‘?’而言,可以将其替换为一个‘(’,也可以替换成一个‘)’,但是都有相应的代价。问:如何替换使得代价最小。前提是替换之后的序列中,括号是匹配的。如果不能替换为一个括号匹配的序列则输出-1。
输入
第一行是序列,序列长度不超过5.10^4,下面m(m是?的数量)行有每行2个数据,第一个是’(‘的代价,第2个是’)'的代价

输出:第一行打印代价,第二行打印替换后的序列。不行输出-1
Translated by @liyifeng

题目描述
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.

输入输出格式
输入格式:
The first line contains a non-empty pattern of even length, consisting of characters “(”, “)” and “?”. Its length doesn’t exceed 5·10^{4} 5⋅10
4
. Then there follow m m lines, where m m is the number of characters “?” in the pattern. Each line contains two integer numbers a_{i} a
i
​ and b_{i} b
i
​ ( 1<=a_{i},b_{i}<=10^{6} 1<=a
i
​ ,b
i
​ <=10
6
), where a_{i} a
i
​ is the cost of replacing the i i -th character “?” with an opening bracket, and b_{i} b
i
​ — with a closing one.

输出格式:
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.

输入输出样例
输入样例#1: 复制
(??)
1 2
2 8
输出样例#1: 复制
4
()()

思路

首先)肯定匹配最近的没有匹配的(,不然一定出现没有匹配的或者交替匹配的。

可以把(入栈,遇到)出栈,而两个()之间的括号序列一定是匹配的。

于是可以把(的位置入栈,出栈时计算即可知道当前括号序列的长度。

但题意里表明了除了(…),(…)(…)也是合法的括号序列。

于是设ans数组管理到目前位置的合法括号序列长度,每次出栈时更新相应位置的值,使用了动态规划的思想。

最后输出的答案1即是ans数组里的最大值,答案2即是答案1在ans数组里出现的次数。

答案1的计算可以在遍历字符串时计算,也可以在遍历字符串之后计算。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int sum,tot,l,r,len,w,ans,stack[1001003],top;
bool a[1001003];
char s[1000103];
int main()
{
	scanf("%s",s);
	len=strlen(s);
	for (int i=0;i<len;i++)
	{
	 if (s[i]=='(') stack[++top]=i;
	 else {if (top){a[stack[top]]=true;a[i]=true;top--;}}
	}
	for (int i=0;i<=len;i++)
	 if (a[i]) w++;
	 else {ans=max(w,ans);w=0;}
	 for (int i=0;i<=len;i++)
	 if (a[i]) w++;
	 else {if (w==ans)tot++;w=0;}
 	if (ans)
	printf("%d %d\n",ans,tot);
	 else puts("0 1\n");
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值