Codeforces Beta Round #3 D. Least Cost Bracket Sequence

24 篇文章 0 订阅
D. Least Cost Bracket Sequence
time limit per test
1 second
memory limit per test
64 megabytes
input
standard input
output
standard 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 ai and bi(1 ≤ ai,  bi ≤ 106), where ai is the cost of replacing the i-th character "?" with an opening bracket, and bi — 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[i] , b[i],问说把所有的问号替换以后,使得这个字符串是一个合法的括号匹配的最小代价是多少,如果无解输出-1

这道题一到手马上想到一O(n²)的dp,因为n是5e4,而且cf上的机子跑的很快(薅资本主义的羊毛),加一点优化好像还可以。

把"("替换成1,把")"替换成-1,dp[i][j] 代表前i个字符串的前缀和为j的时候的最小代价,dp[i][j] = min(dp[i -1 ][j - 1 ]+ a[i] ,dp[ i - 1][ j +1 ] + b[i ]) ;用滚动数组代替二维数组即可,跑了几组数据发现可以求最小代价,然而题目还要求输出路径,请教了很多dalao之后发现dp滚动数组好像不容易打印路径!!所以这个dp并没有什么卵用。

然后看q神的题解,先把所有的问号换成右括号,然后从左到右,同样记左括号为1,右括号为-1,那么如果到某一个位置中,前缀和sum<0,那么在这个前缀中必须有一个右括号替换成左括号,我们把那个(a[i] - b[i ])最小的拿出来替换,这里可以用堆优化降到O(n log n)。这样就可以了,注意最后前缀和sum必须=0 ,否则是无解的。

#pragma GCC optimize ("03")
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<time.h>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<iostream>
using namespace std;
#define  LONG long long
const int   INF=0x3f3f3f3f;
const int MOD=1e9+7;
const double PI=acos(-1.0);
#define clrI(x) memset(x,-1,sizeof(x))
#define clr0(x) memset(x,0,sizeof x)
#define clr1(x) memset(x,INF,sizeof x)
#define clr2(x) memset(x,-INF,sizeof x)
#define EPS 1e-10
char str[60000];
struct Node
{
    LONG  a, b ;
    LONG  cost ;
    int p ;
    bool operator < (const Node &x) const
    {
        if(cost == x.cost )return p<x.p ;
        else return cost > x.cost ;
    }
}node[60000];
int main()
{
    scanf("%s",str);
    int len = strlen(str);
    int m = 0;
    LONG ans = 0 ;
    for(int i = 0 ; i < len ;++i)
    {
        if(str[i] == '?')
        {
            ++ m ;
            scanf("%lld%lld",&node[i].a,&node[i].b);
            ans += node[i].b ;
        }
        node[i].cost = node[i].a - node[i].b ;
        node[i].p = i;
    }
    priority_queue <Node > que ;
    while(!que.empty()) que.pop();
    int sum = 0 ;
    int judge = 1 ;
    for(int i = 0 ; i< len ;++ i)
    {
        if(str[i] == '?' )
        {
            que.push(node[i]) ;
            str[i] = ')';
            sum ++ ;
        }
        else if(str[i] == '(')
            sum --;
        else if(str[i] == ')')
            sum ++ ;
        if( sum > 0)
        {
            if(que.empty())
            {
                judge = 0 ;
                break ;
            }
            Node tmp = que.top() ;
            que.pop() ;
            str[tmp.p] = '(';
            ans += tmp.cost ;
            sum -= 2 ;
        }
//        printf("%s\n",str);
    }
    if(!judge || sum != 0 )
    {
        cout<<-1<<endl;
        return 0;
    }
    cout<<ans<<endl;
    printf("%s\n",str);
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值