括号序列问题

湘潭邀请赛

codeforces#3D. Least Cost Bracket Sequence

题意

给一个未完全填好的括号序列,每一个可填充的位置,填(的花费为a,填)的花费为b,求使其成合法序列的最小花费


 分析

合法的括号序列有一个特点:对于任意位置 i ,它的左括号的数量不能少于 ceil ((i+1)/2)。首先强制将所有都变为),然后从前往后模拟这个过程,用一个优先队列维护即可。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 5e4+10;

struct node
{
    int id, ans;
    bool friend operator < (node a, node b)
    {
       // if(a.ans != b.ans)
        return a.ans < b.ans;


    }
}k[maxn];
priority_queue<node>q;
bool vis[maxn];
ll sum = 0;
int a[maxn];
int b[maxn];
int n;

int main()
{
    string s;
    cin>>s;
    int len = s.size();
    int num = 0;
    int cnt = 0;
    for(int i = 0 ; i < len; i++)
    {
        if(s[i] == '?')
            n++;
       else if(s[i] == ')')
        cnt++;
    }
    for(int i = 1; i <= n; i++)
    {
        scanf("%d%d", &a[i], &b[i]);
        sum += 1ll*b[i];
    }
    int kl = 0;
    int oo = 0;
    for(int i = 0; i < len; i++)
    {
        if(s[i] == '(')
            kl++;

        else
        {
            if(s[i] == '?')
            {
            ++oo;
            k[++num].id = i;
            k[num].ans = b[oo]-a[oo];
            q.push(k[num]);
            }
            while(kl < (ceil((1.0*(i+1))/2.0)) && q.size()>0)
            {
                node kk = q.top();
                q.pop();
                sum -= 1ll*kk.ans;
                vis[kk.id]=1;
                kl++;
            }
        }
    }
    int num1 = 0, num2 =  0;
    for(int i = 0; i < len; i++)
    {
        if(s[i] == '(')
            num1++;
        else if(s[i] == ')')
            num2++;
        else
        {
            if(vis[i] == 1)
                num1++;
            else
                num2++;
        }
        if(num2 > num1)
        {
            cout<<"-1"<<endl;
            return 0;
        }
    }
    if(num1 != num2)
    {
        cout<<"-1"<<endl;
        return 0;
    }
    printf("%I64d\n", sum);
    for(int i = 0; i < len; i++)
    {
        if(s[i]!='?')
            cout<<s[i];
        else
        {
            if(vis[i] == 1)
                cout<<'(';
            else
                cout<<')';
        }
    }
    return 0;
}
View Code

 

posted @ 2017-11-17 13:38  Superwalker  阅读(496)  评论(0编辑  收藏  举报