题意:给定n个只有左右括号的序列,要求将它们重新排序使得匹配的括号对数最大。
n<=1e5
s[i]<=1e5
sum s[i]<=5e6
思路:
先把每个串内部的匹配数量减去,剩下的就是不匹配的左右括号数量
对于左括号数量大于右括号的串,按右括号数量从小到大排序
对于右括号数量大于左括号的串,按左括号数量从大到小排序
1 #include<cstdio> 2 #include<cstring> 3 #include<string> 4 #include<cmath> 5 #include<iostream> 6 #include<algorithm> 7 #include<map> 8 #include<set> 9 #include<queue> 10 #include<vector> 11 using namespace std; 12 typedef long long ll; 13 typedef unsigned int uint; 14 typedef unsigned long long ull; 15 typedef pair<int,int> PII; 16 typedef vector<int> VI; 17 #define fi first 18 #define se second 19 #define MP make_pair 20 21 int read() 22 { 23 int v=0, f=1; 24 char c=getchar(); 25 while (c<48||57<c) {if(c=='-') f=-1; c=getchar();} 26 while (48<=c&&c<=57) v=(v<<3)+v+v+c-48, c=getchar(); 27 return v*f; 28 } 29 30 const int N=110000; 31 int a[N],b[N],n,ans; 32 char ch[N]; 33 PII A[N],B[N],C[N]; 34 35 bool cmp1(const PII &a,const PII &b) 36 { 37 return a.fi<b.fi; 38 } 39 40 bool cmp2(const PII &a,const PII &b) 41 { 42 return a.se>b.se; 43 } 44 45 int main() 46 { 47 48 int cas=read(); 49 while(cas--) 50 { 51 n=read(); 52 int ans=0; 53 for(int i=1;i<=n;i++) 54 { 55 scanf("%s",ch+1); 56 a[i]=b[i]=0; 57 int now=0; 58 for(int j=1;ch[j];j++) 59 if(ch[j]==')') 60 { 61 if(now) now--,ans++; 62 else a[i]++; 63 } 64 else now++; 65 b[i]=now; 66 for(int j=1;ch[j];j++) ch[j]=0; 67 } 68 for(int i=1;i<=n;i++) A[i]=MP(a[i],b[i]); 69 int len1=0,len2=0; 70 for(int i=1;i<=n;i++) 71 if(a[i]<b[i]) B[++len1]=A[i]; 72 else C[++len2]=A[i]; 73 sort(B+1,B+len1+1,cmp1); 74 sort(C+1,C+len2+1,cmp2); 75 int now=0; 76 for(int i=1;i<=len1;i++) 77 { 78 ans+=min(now,B[i].fi); 79 now-=min(now,B[i].fi); 80 now+=B[i].se; 81 } 82 for(int i=1;i<=len2;i++) 83 { 84 ans+=min(now,C[i].fi); 85 now-=min(now,C[i].fi); 86 now+=C[i].se; 87 } 88 printf("%d ",ans*2); 89 } 90 return 0; 91 }