hdu 6299 Balanced Sequence (贪心)

Balanced Sequence

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6311    Accepted Submission(s): 1648

Problem Description

Chiaki has n strings s1,s2,…,sn consisting of ‘(‘ and ‘)‘. A string of this type is said to be balanced:

+ if it is the empty string
+ if A and B are balanced, AB is balanced,
+ if A is balanced, (A) is balanced.

Chiaki can reorder the strings and then concatenate them get a new string t. Let f(t) be the length of the longest balanced subsequence (not necessary continuous) of t. Chiaki would like to know the maximum value of f(t) for all possible t.

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line contains an integer n (1≤n≤105) -- the number of strings.
Each of the next n lines contains a string si (1≤|si|≤105) consisting of `(‘ and `)‘.
It is guaranteed that the sum of all |si| does not exceeds 5×106.

Output

For each test case, output an integer denoting the answer.

Sample Input

2
1
)()(()(
2
)
)(

Sample Output

4
2

题目大意:

给你n个由‘(‘和‘)‘组成的括号序列。要你将这n个序列整体排序使得匹配的子序列(不一定相连)最长。求最长子序列。匹配条件如下:

+ if it is the empty string
+ if A and B are balanced, AB is balanced,
+ if A is balanced, (A) is balanced.

贪心。

首先将每个序列中匹配的括号计数并剔除。可以看到,剩下的序列都行如")))(((((",用结构体存储r,l,排序,就可以贪心了。

贪心方法是(其实我并不能证明,大概是基于左括号尽量往左放,vice versa的思想):

1、"))))((((" 中 ‘)‘ < ‘(‘ 的 , 按 ‘)‘ 从小到大排序 ;

2、"))))((((" 中 ‘)‘ >= ‘(‘ 的 , 按 ‘(‘ 从大到小排序 ;

//优先级排序:
//1、"))))((((" 中 ‘)‘ < ‘(‘ 的 , 按 ‘)‘ 从小到大排序 ;
//2、"))))((((" 中 ‘)‘ >= ‘(‘ 的 , 按 ‘(‘ 从大到小排序 ;

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<stack>

using namespace std;

const int maxn=100000;

char s[maxn+10];

struct tstr
{
    int r,l;
};
tstr str[maxn+10];

bool cmp(tstr a,tstr b)
{
    if(a.r<a.l&&b.r>=b.l)
        return true;
    if(b.r<b.l&&a.r>=a.l)
        return false;
    if(a.r<a.l&&b.r<b.l)
        return a.r<b.r;
    else
        return a.l>b.l;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);

        int ans=0;
        for(int i=0;i<n;i++)
        {
            scanf("%s",s);
            stack<char> sta;
            sta.push(‘)‘);//在栈底放一个‘)‘,方便后续操作
            for(int j=0;s[j]!=‘\0‘;j++)
            {
                if(s[j]==‘)‘&&sta.top()==‘(‘)
                    ans+=2,sta.pop();
                else
                    sta.push(s[j]);
            }
            str[i].r=-1;str[i].l=0;
            while(!sta.empty())
            {
                if(sta.top()==‘(‘)
                    str[i].l++,sta.pop();
                if(sta.top()==‘)‘)
                    str[i].r++,sta.pop();
            }
        }

        sort(str,str+n,cmp);
        stack<char> sta;
        sta.push(‘)‘);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<str[i].r;j++)
            {
                if(sta.top()==‘(‘)
                    ans+=2,sta.pop();
                else
                    sta.push(‘)‘);
            }
            for(int j=0;j<str[i].l;j++)
            {
                sta.push(‘(‘);
            }
        }

        printf("%d\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/acboyty/p/9684014.html

时间: 2024-08-20 06:00:53

hdu 6299 Balanced Sequence (贪心)的相关文章

HDU 6299 Balanced Sequence &lt;&lt;贪心

题意 给出至多1e5个长度不超过1e5的括号序列,问将他们排序重组后最多能有多少对合法括号 思路 先将已经匹配的括号全部去掉,然后我们的序列就只会剩下三种形式——$"((((("$,$"))))((("$,$"))))"$,然后这时候就只有序列的左右括号的数量起作用了,所以我们只需通过这个条件来对他们进行排序,具体来讲,全是左括号的放最左边,全是右括号的放最右边,中间的看他怎么拼起来多怎么放.代码实现上,如果直接按这个思路写的话会re到死...具

hdu 6299 Balanced Sequence( 2018 Multi-University Training Contest 1 )

1 #include <stdio.h> 2 #include <iostream> 3 #include <cstdlib> 4 #include <cmath> 5 #include <string> 6 #include <cstring> 7 #include <algorithm> 8 #include <stack> 9 #include <queue> 10 #include <

HDU 5014 Number Sequence 贪心 2014 ACM/ICPC Asia Regional Xi&#39;an Online

尽可能凑2^x-1 #include <cstdio> #include <cstring> const int N = 100005; int a[N], p[N]; int init(int x) { int cnt = 0; while(x > 1) { x /= 2; cnt ++; } return cnt + 1; } int main() { int n; while(~scanf("%d", &n)){ for(int i = 0;

hdu 4915 Parenthese sequence (贪心+模拟)

题目大意: 一个序列中有左括号和右括号,还有问号,问号可以任意转换成左右括号. 问这个序列有多少种情况的转变使得这个序列变成合法的括号匹配序列. 思路分析: 首先我们分析一下,如何使得一个序列是合法的括号匹配序列. 我们很容易想到的是用栈模拟匹配过程. 当遇到左括号就进栈,当遇到右括号就让栈顶的左括号出栈. 那么在模拟的过程中,造成这个序列的不合法的原因只有当右括号来的时候,此时的栈已经为空. 这里补充一句,一旦一个序列给定,那么这里面的问号有多少变成左括号,多少变成右括号,是一定的. 看完以上

hdu 5014 Number Sequence(贪心)

题目链接:hdu 5014 Number Sequence 题目大意:给定n,表示有0~n这n+1个数组成的序列a,要求构造一个序列b,同样是由0~n组成,要求∑ai⊕bi尽量大. 解题思路:贪心构造,对于n来说,找到n对应二进制的取反对应的数x,那么从x~n之间的数即可两两对应,然后x-1即是一个子问题. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; con

HDU 5014 Number Sequence(贪心)

当时想到了贪心,但是不知为何举出了反列....我是逗比,看了点击打开链接.才发现我是逗比. Problem Description There is a special number sequence which has n+1 integers. For each number in sequence, we have two rules: ● ai ∈ [0,n] ● ai ≠ aj( i ≠ j ) For sequence a and sequence b, the integratin

HDU 6047 Maximum Sequence(贪心+线段树)

题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=6047 题目: Maximum Sequence Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 90    Accepted Submission(s): 44 Problem Description Steph is extremely o

HDU 6047 Maximum Sequence (贪心+单调队列)

题意:给定一个序列,让你构造出一个序列,满足条件,且最大.条件是 选取一个ai <= max{a[b[j], j]-j} 析:贪心,贪心策略就是先尽量产生大的,所以就是对于B序列尽量从头开始,由于数据比较大,采用桶排序,然后维护一个单调队列,使得最头上最大. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #i

hdu多校1002 Balanced Sequence

Balanced Sequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3280 Accepted Submission(s): 846 Problem Description Chiaki has n strings s1,s2,…,sn consisting of '(' and ')'. A string of this t