zoukankan      html  css  js  c++  java
  • 括号序列问题

    湘潭邀请赛

    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
    ", 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
    要么优秀要么生锈
  • 相关阅读:
    牌库读取的修复
    法术迸发(Spellburst)
    传染孢子的探索
    降低电脑功耗——降低笔记本风扇噪音
    Playfield 类方法的注释
    大陆争霸( 最短路变形)
    POJ 2406 Power String
    括号匹配
    HDU 1003 最大子段和
    6.19noip模拟赛总结
  • 原文地址:https://www.cnblogs.com/Superwalker/p/7851153.html
Copyright © 2011-2022 走看看