括号序列问题

湘潭邀请赛

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;
}

时间: 2024-08-05 16:38:32

括号序列问题的相关文章

数据结构(括号序列,线段树):ZJOI 2007 捉迷藏

[题目描述] Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋子都互相可达. 游戏是这样进行的,孩子们负责躲藏,Jiajia负责找,而Wind负责操纵这N个屋子的灯.在起初的时候,所有的灯都没有被打开.每一次,孩子们只会躲 藏在没有开灯的房间中,但是为了增加刺激性,孩子们会要求打开某个房间的电灯或者关闭某个房间的电灯.为了评估某一次

【UOJ】【UR #2】猪猪侠再战括号序列(splay/贪心)

http://uoj.ac/problem/31 纪念伟大的没有调出来的splay... 竟然那个find那里写错了!!!!!!!!!!!!! 以后要记住:一定要好好想过! (正解的话我就不写了,太简单了.. #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #

喵哈哈村的括号序列

描述 喵哈哈村的括号序列和外界的括号序列实际上是一样的. 众所周知"()"这样的,就是一个标准的括号序列:"()()()()"这样也是括号序列:"((()))()"这样也是一个合法的括号序列.但是"((("这样,就不是一个合法的括号序列了. 现在沈宝宝非常好奇,给你一个字符串,请从中找出最长的合法括号序列出来. 不知道你能找到吗? 输入 第一行一个T,表示有T组数据.接下来T行,每一行都是一个字符串.保证字符串的长度小于100

3295: 括号序列 -(序列DP)

描述 给定一串字符串,只由 “[”.“]” .“(”.“)”四个字符构成.现在让你尽量少的添加括号,得到一个规则的序列. 例如:“()”.“[]”.“(())”.“([])”.“()[]”.“()[()]”,都是规则的序列.这几个不是规则的,如:“(”.“[”.“]”.“)(”.“([()”. 输入 输入有多组测试数据.输入一串字符串序列,长度不大于255. 输出 输出最少添加的括号数目. 样例输入 () ( ([() [[(([] 样例输出 0 1 2 4 题目来源 椒江校区第一届C语言编程大

BZOJ2209: [Jsoi2011]括号序列

传送门 splay练习. 考虑把括号序列转化成类似于区间最大/最小值的情况. 显然我们可以知道括号序列消完的情况肯定是$a$个)和$b$个(,那么把这些括号全部合法化的代价显然就是$\frac{a+1}{2}+\frac{b+1}{2}$. 接着我们可以把'('变为1,把')'变为-1,然后每次取左区间的连续最小值,右区间的连续最大值,就是$a$与$b$的大小. 因为存在区间翻转,所以需要把左/右区间的连续最大/小值都搞出来. splay即可. //BZOJ2209 //by Cydiater

九度oj 题目1337:寻找最长合法括号序列

题目描述: 给你一个长度为N的,由’(‘和’)’组成的括号序列,你能找出这个序列中最长的合法括号子序列么?合法括号序列的含义便是,在这个序列中,所有的左括号都有唯一的右括号匹配:所有的右括号都有唯一的左括号匹配.例如:((()))()()便是一个长度为10的合法括号序列,而(()))( 则不是. 需要你求解的是,找出最长的合法括号子序列的长度,同时找出具有这样长度的序列个数. 输入: 测试数据包括多个,每个测试数据包含两行: 第一行为一个整数N,其中N不会超过10^6. 第二行为一个长度为N的字

uoj #31. 【UR #2】猪猪侠再战括号序列 贪心

#31. [UR #2]猪猪侠再战括号序列 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://uoj.ac/problem/31 Description 大家好我是来自百度贴吧的_叫我猪猪侠,英文名叫_CallMeGGBond. 我不曾上过大学,但这不影响我对离散数学.复杂性分析等领域的兴趣:尤其是括号序列理论,一度令我沉浸其中,无法自拔.至于OI算法竞赛,我年轻时确有参加,虽仅获一枚铜牌,但我素性淡泊,毫不在意,毕竟那所谓FFT.仙人掌之类

1478 括号序列的最长合法子段

1478 括号序列的最长合法子段 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 这里有另一个关于处理合法的括号序列的问题. 如果插入“+”和“1”到一个括号序列,我们能得到一个正确的数学表达式,我们就认为这个括号序列是合法的.例如,序列"(())()", "()"和"(()(()))"是合法的,但是")(", "(()"和"(

Bzoj4350 括号序列再战猪猪侠

Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 97  Solved: 44 Description 括号序列与猪猪侠又大战了起来. 众所周知,括号序列是一个只有(和)组成的序列,我们称一个括号 序列S合法,当且仅当: 1.( )是一个合法的括号序列. 2.若A是合法的括号序列,则(A)是合法的括号序列. 3.若A,B是合法的括号序列,则AB是合法的括号序列. 我们考虑match[i]表示从左往右数第i个左括号所对应的是第几个右 括号,现在他得到了

codevs 2058 括号序列

2058 括号序列 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题解 题目描述 Description 定义满足以下规则字符串为规则序列,否则不是规则序列: 1.空序列是规则序列: 2.如果S是规则序列,那么(S),[S],{S}和<S>也是规则序列: 3.如果A和B都是规则序列,那么AB也是规则序列. 例如,下面的字符串都是规则序列: (),[],(()),([]),()[],()[()],{{}}<>,([]<>{{}}),