【51Nod1476】括号序列的最小代价

来源:互联网 发布:淘宝懒人软件靠谱么 编辑:程序博客网 时间:2024/05/22 15:27

这里有一个关于合法的括号序列的问题。
如果插入“+”和“1”到一个括号序列,我们能得到一个正确的数学表达式,我们就认为这个括号序列是合法的。例如,序列”(())()”, “()”和”(()(()))”是合法的,但是”)(“, “(()”和”(()))(“是不合法的。我们这有一种仅由“(”,“)”和“?”组成的括号序列,你必须将“?”替换成括号,从而得到一个合法的括号序列。
对于每个“?”,将它替换成“(”和“)”的代价已经给出,在所有可能的变化中,你需要选择最小的代价。

Input
第一行是一个非空的偶数长度的字符串,它仅由“(”,“)”和“?”组成。它的长度不大于 50000。接着是m行,m是字符串中“?”的个数。每一行包含两个整数 ai和bi ( 1<=ai,bi<=1000000), ai是将第i个“?”替换成左括号的代价, bi是将第i个“?”替换成右括号的代价。
Output
在一行中输出合法的括号序列的最小代价。
如果没有答案,输出-1。
Input示例
(??)
1 2
2 8
Output示例
4

题解
先把所有问号填成),从左往右扫,弄个计数器tot,判断当前左括号多还是右括号多,当右括号多时贪心修改之前代价最小的括号,用堆维护。

代码

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<set>#include<ctime>#include<vector>#include<cmath>#include<algorithm>#include<map>#include<queue>#define mod 1000000007 #define ll long long  #define inf 1e9using namespace std;inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}priority_queue<int,vector<int>,greater<int> >q;int len,a[50005],b[50005];ll ans=0LL;char s[50005];int main(){    scanf("%s",s);    len=strlen(s);    for (int i=0;i<len;i++)        if (s[i]=='?')        {            scanf("%d%d",&a[i],&b[i]);            ans+=b[i];        }    int tot=0;    for (int i=0;i<len;i++)    {        if (s[i]=='(') tot++;        else tot--;        if (s[i]=='?') q.push(a[i]-b[i]);        if (tot<0)        {            if (q.empty()) return printf("-1"),0;            ans+=q.top();q.pop();tot+=2;        }    }    if (tot>0) return printf("-1"),0;    printf("%lld",ans);    return 0;}
原创粉丝点击