CF_3D_LeastCostBracketSequence

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
()()


给出一个括号序列

其中某些括号被?代替了

这些位置需要补充(或者)

并且补充时权重不同

现在问一个最小权重的合法括号序列(可加入若干1和+组成一个算式即合法)

输出最小权值和 这样的一个合法的括号序列


首先判断括号序列合法有这样一个方法

做一个前缀和(则+1,)则-1

如果前缀和在任何地方大等零,结束时等于零则这个括号序列合法

因此可以想象 如果全写(可以保证过程中全部合法……

换言之 中间)是造成序列不合法的关键


于是,我们可以通过假设所有?处全部为)之后对其进行更正的方法(贪心)

试想如果我们从前向后算前缀和走到)时会使前缀和变成负数(-1)

此时如果前方没有可以改变方向的)则这个序列不可能合法,因为无法保证整个序列前缀和为非负

否则,我们可以取之前所有能改动的)中的一个,这一个是使权值和增加最少的一个,改成(

此时我们保证了前缀和又回到了非负,使得扫过的区间合法

于是我们可以使用优先队列实现这个任务


由于对所有?部分的两种括号的数目其实是固定的,由其外部决定(最终前缀和应为0)

而每部分由部分前缀和有更强的约束

因此我们对每次局部前缀和非法,总从最小的权值增加的)开始修改是可以得到最优解的


注意ans范围

#include <iostream>
#include <stdio.h>
#include <queue>
#include <string.h>
using namespace std;

typedef long long LL;
const int M=5e4+5;
char s[M];//,anss[M];直接在原来的串上修改就可以了

struct Node
{
    int s,p;
    Node(){}
    Node(int ss,int pp):s(ss),p(pp){}
    bool operator<(Node a)const
    {
        return s>a.s;
    }
};
priority_queue<Node> qu;

int main()
{
    scanf("%s",s);
    int sl=strlen(s);
    int psu=0;
    LL ans=0;  //有超int的
    for(int i=0;i<sl;i++)
    {
        if(s[i]=='(')
            psu++;
        else if(s[i]==')')
            psu--;
        else
        {
            int a,b;
            scanf("%d%d",&a,&b);
            psu--;
            ans+=b;
            qu.push(Node(a-b,i));
            s[i]=')';
        }
        //cout<<"i "<<i<<" "<<psu<<endl;
        if(psu<0)
        {
            if(qu.empty())
            {
                ans=-1;
                break;       //单组数据可以在输入过程中跳出
            }
            psu+=2;
            Node t=qu.top();
            qu.pop();
            ans+=t.s;
            s[t.p]='(';
        }
    }
    if(psu)
        ans=-1;
    printf("%I64d\n",ans);
    if(ans!=-1)
        printf("%s\n",s);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值