2018 Multi-University Training Contest 1:1002-Balanced Sequence(思维)

                                            Balanced Sequence

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


 

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≤10^5) -- the number of strings.
Each of the next n lines contains a string si (1≤|si|≤10^5) consisting of `(' and `)'.
It is guaranteed that the sum of all |si| does not exceeds 5×10^6.

 

 

Output

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

 

 

Sample Input

2

1

)()(()(

2

)

)(

Sample Output

4

2

思路:对于只包含'('或者只包含')'的字符串,肯定得把它放到最前面或最后面。

而对于既包含')' 也包含'('的字符串,预处理出每个字符串的最长合法序列,累加到答案。

因为对于这些字符串的最长合法序列,其它字符串不会对其产生影响。

经过预处理之后,每个字符串就是类似...))))(((((...这样的字符串了。

接下来就是贪心,如何安排顺序使答案最大。

有三种排序方法。

1.对于字符串x,y。如果按x在前,y在后,得到的合法序列更长,那么x就在y前面;否则y在x前面。

2.对于字符串x,y。如果x的'('个数大于y的'('个数,那么x在前面;否则y在前面;

3.对于字符串x,y。如果x的')'个数小于y的')'个数,那么x在前面;否则y在前面;

然后对字符串分别进行以上三种排序,取最大值作为答案。

#include<bits/stdc++.h>
using namespace std;
const int MAX=1e6+10;
typedef long long ll;
char s[MAX];
int num[MAX][2];//预处理记录左右括号的个数
int c[MAX];     //用于排序
int cmp1(const int&x,const int &y)
{
    if(min(num[x][0],num[y][1])>min(num[y][0],num[x][1]))return 1;
    return 0;
}
int cmp2(const int&x,const int &y)
{
    if(num[x][0]==num[y][0])return num[x][1]<num[y][1];
    return num[x][0]<num[y][0];
}
int cmp3(const int&x,const int &y)
{
    if(num[x][1]==num[y][1])return num[x][0]>num[y][0];
    return num[x][1]<num[y][1];
}
int m;
int cal(int L,int R,int ans)
{
    for(int i=1;i<=m;i++)
    {
        ans+=2*min(L,num[c[i]][1]);
        L-=min(L,num[c[i]][1]);
        L+=num[c[i]][0];
    }
    return ans+2*min(L,R);
}
stack<char>p;
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int n;
        scanf("%d",&n);
        int ans=0,L=0,R=0;
        m=0;
        for(int i=1;i<=n;i++)
        {
            c[i]=i;
            num[i][0]=0;
            num[i][1]=0;
            scanf("%s",s);
            int len=strlen(s);
            for(int j=0;j<len;j++)
            {
                if(p.empty()||s[j]=='(')p.push(s[j]);
                else
                {
                    if(p.top()=='(')ans+=2,p.pop();
                    else p.push(s[j]);
                }
            }
            while(!p.empty())
            {
                if(p.top()=='(')num[i][0]++;
                else num[i][1]++;
                p.pop();
            }
            if(num[i][0]==0&&num[i][1]==0)continue;
            if(num[i][0]&&num[i][1]==0)L+=num[i][0]; //单独处理只有'('或只有')'的字符串
            else if(num[i][0]==0&&num[i][1])R+=num[i][1];
            else c[++m]=i;
        }
        int tot=0;
        sort(c+1,c+m+1,cmp1);
        tot=max(tot,cal(L,R,ans));
        sort(c+1,c+m+1,cmp2);
        tot=max(tot,cal(L,R,ans));
        sort(c+1,c+m+1,cmp3);
        tot=max(tot,cal(L,R,ans));
        printf("%d\n",tot);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值