题意
给出至多1e5个长度不超过1e5的括号序列,问将他们排序重组后最多能有多少对合法括号
思路
先将已经匹配的括号全部去掉,然后我们的序列就只会剩下三种形式——$"((((("$,$"))))((("$,$"))))"$,然后这时候就只有序列的左右括号的数量起作用了,所以我们只需通过这个条件来对他们进行排序,具体来讲,全是左括号的放最左边,全是右括号的放最右边,中间的看他怎么拼起来多怎么放。代码实现上,如果直接按这个思路写的话会re到死。。。具体在下面代码里说明,最后我是借鉴网上大佬的。最后把排好序的序列们扫一边即可。细节上,记得cin关同步,因为输入量还是挺大的。
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+7; 4 struct Point{ 5 int l,r; 6 bool operator <(const Point &a) const{ 7 //if(r==0||a.l==0) return true; 原本的写法 8 //if(l==0||a.r==0) return false; 在sort的时候会出错 9 //return r+a.l>l+a.r; 10 if(min(l,a.r)==min(r,a.l)) return l>a.l; 11 return min(l,a.r)>min(r,a.l); 12 } 13 }pt[maxn]; 14 15 int main() 16 { 17 std::ios::sync_with_stdio(false); 18 cin.tie(NULL); 19 int T; 20 cin>>T; 21 while(T--) 22 { 23 int n; 24 cin>>n; 25 string str; 26 int ans=0; 27 for(int i=0;i<n;i++) 28 { 29 pt[i].l=pt[i].r=0; 30 cin>>str; 31 for(int j=0;j<str.length();j++) 32 { 33 if(str[j]=='(') 34 pt[i].l++; 35 else{ 36 if(pt[i].l) 37 pt[i].l--,ans++; 38 else pt[i].r++; 39 } 40 } 41 } 42 sort(pt,pt+n); 43 int ansl=0,ansr=0; 44 for(int i=0;i<n;i++) 45 { 46 if(ansl) 47 { 48 ans+=min(ansl,pt[i].r); 49 ansl-=pt[i].r; 50 if(ansl<0) ansl=0; 51 } 52 ansl+=pt[i].l; 53 } 54 cout<<ans*2<<endl; 55 } 56 return 0; 57 }