题意略。
思路:
我们先把所有字符串处理成 ")))((((" 这样的形式。然后我们把这些字符串排个序,按照min(l,r)来排,小的在前,在我的代码中,l为 ( 的个数,r 为 ) 的个数。
然后我们从头到尾扫,l > r的,我们把它放在左边;l < r的,我们把它放在右边。这样排的原因是,我希望 (,((,)),) 这样比较纯的单向字符串排在两边,
像 )))(( 这样两头都有的我们放中间。
本题除了排序外还有一个难点,就是在安排好新的字符串后,我们怎么计算答案。
我们从左向右遍历这个总的字符串,用一个temp来维护当前没有被匹配过的 ( 有多少个,然后每到下一个子字符串,我查看当前子字符串 ) 的个数。
能与之前的 ( 匹配多少就用多少。
详见代码:
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 5; struct node{ int l,r; node(int a = 0,int b = 0){ l = a,r = b; } }; node store[maxn]; node depot[maxn]; char str[maxn]; bool cmp(const node& n1,const node& n2){ return min(n1.l,n1.r) < min(n2.l,n2.r); } int main(){ int T,n; scanf("%d",&T); while(T--){ scanf("%d",&n); int ans = 0; for(int i = 0;i < n;++i){ scanf("%s",str); int len = strlen(str); int l = 0,r = 0; for(int j = 0;j < len;++j){ if(str[j] == '(') ++l; else{ if(l > 0){ --l; ans += 2; } else ++r; } } store[i] = node(l,r); } sort(store,store + n,cmp); for(int i = 0,l = 0,r = n - 1;i < n;++i){ if(store[i].l > store[i].r) depot[l++] = store[i]; else depot[r--] = store[i]; } int temp = 0; for(int i = 0;i < n;++i){ ans += 2 * min(temp,depot[i].r); temp = max(0,temp - depot[i].r); temp += depot[i].l; } printf("%d ",ans); } return 0; }