2018杭电多校第一场补题1002 Balanced Sequence 流水线排序

Balanced Sequence

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


 

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个字符串按照一定顺序连接起来,进行括号匹配,每匹配一对括号得到的值就加2(括号的长度啦),问你能得到的最大的值为多少。

思路

(⊙o⊙)…首先肯定是对它给的每个串预处理啦,然后,咱们得到的新的串就是左边只有右括号,右边只有左括号的串啦,如下示意

)))((就像酱紫滴

然后,每个字符串就能有一个结构体或者pair表示了,存两个值,一个是右括号的数量,一个是左括号的数量,将这些连接起来时候就左右相消,我们需要找到一个方法让它们连接起来后消的尽量的多。

然后吧,说下菜鸡我当时的想法,当时想把它们按照左括号的数量或者右括号的数量多少不同进行排序,这样总共有2^2=4种排序,然后吧,果断WA了,赛后网传将每种排序都试下,emmmm,发现还有个左括号数量减右括号数量,这样的话就有2^3=8种排序方案,已经肝了4种的我对这种做法表示怀疑(懒得去试),之后看dls直播时候发现,woc,他们就一种排序就解决了,orz,仔细研究下排序方法,发现这个排序方法叫做流水线排序。

bool friend operator < (node a, node b){
        if ( a.l >= a.r && b.l<b.r){
            return false;
        }
        if ( a.l < a.r && b.l >= b.r){
            return true;
        }
        if (a.l >= a.r && b.l>= b.r){
            return a.r > b.r;
        }
        return a.l < b.l;
    }

如果当前任务前驱大于等于后驱并且和他比较的任务前驱小于后驱,那么,我们给当前任务放在后面,如果当前任务前驱小于后驱并且和他比较的任务前驱大于等于后驱,那么,我们把当前任务放在后面,如果两个任务的前驱都大于等于后驱,那么我们把后驱大的放前面,最后把前驱小的放前面,就酱紫,理解了一会才明白~

AC代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
struct node{
    int l,r;
    bool friend operator < (node a, node b){
        if ( a.l >= a.r && b.l<b.r){
            return false;
        }
        if ( a.l < a.r && b.l >= b.r){
            return true;
        }
        if (a.l >= a.r && b.l>= b.r){
            return a.r > b.r;
        }
        return a.l < b.l;
    }
} a[maxn];
char s[maxn];
char st[maxn];
int preans, n;
void read_init(int x){
    scanf("%s",s);
    int len=strlen(s);
    int tail=0, ltail=0;
    char cc;
    stack<char> z;
    for(int i=0;i<len;++i){
        if (tail==0){
            st[tail]=s[i];
            tail++;
            if (s[i]==')'){
                ltail=tail;
            }
            continue;
        }
        if (st[tail-1]=='('&&s[i]==')'){
            tail--;
            preans++;
            continue;
        }
        st[tail]=s[i];  tail++;
        if (s[i]==')'){
                ltail=tail;
        }
    }
    a[x].l=ltail;
    a[x].r=tail-ltail;
    return ;
}

void read(){
    scanf("%d",&n);
    preans=0;
    for (int i=0;i<n;++i){
        read_init(i);
    }
    return ;
}
void solve(){
    sort(a,a+n);
    int left=a[0].l, right=a[0].r, ans=0;
    for (int i=1;i<n;++i){
        if (right<a[i].l){
            ans+=right;
            left=left+a[i].l-right;
            right=a[i].r;
        }else{
            ans+=a[i].l;
            right=right-a[i].l+a[i].r;
        }
    }
    printf("%d\n",(ans+preans)*2);
    return ;
}
int main(){
    //freopen("in.txt","r",stdin);
    int T;
    while(~scanf("%d",&T)){
        while(T--){
            read();
            solve();
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/AC_hunter/article/details/81178604