有一個括號序列,你能夠選擇兩個位置i,j(i能夠等於j),進行交換。使得最後的循環位置(i的數目)最大。ios
循環位置:i(0<=i<len),將前i個字符移到最後,獲得的新序列是合法的括號序列。c++
這題還有個大數據範圍版本,那題思路太神仙了,我等凡人就學學暴力吧!這題有個結論,假設)爲-1,(爲+1,那麼一個括號序列的循環匹配個數等於前綴和最小值的個數。證實參考某大佬的:大數據
假設對於序列)()(
,它的前綴和是-1 0 -1 0
spa
當上述前綴值<0時,這個前綴序列必定是不合法的。而後考慮何時把括號序列的一段前綴移到後面去是合法的。code
首先你須要使得移動以後,前面的括號序列合法。也就是說你得把一段「連續的極長非合法前綴」找出來(對於樣例是)
)。這個東西剛好在前綴和第一次取得最小值時取得(前綴和取-1
)。而後實際上你還能夠在這個前綴後面接上一些「自己合法」的括號序列,像這樣:)()
。後面那個合法的序列對答案沒有影響,所以循環移位的數量就是前綴和最小值的數量。blog
而後咱們就能夠O(n^3)暴力啦!ci
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f #define ll long long const int N=200005; const int mod=1e9+7; const double eps=1e-8; const double PI = acos(-1.0); #define lowbit(x) (x&(-x)) int n; string s; int solve() { int sum=0,mi=0,cnt=0; for(int i=0; i<n; i++) { if(s[i]=='(') cnt++; else cnt--; mi=min(cnt,mi); } cnt=0; for(int i=0;i<n;i++) { if(s[i]=='(') cnt++; else cnt--; if(cnt==mi) sum++; } return sum; } int main() { std::ios::sync_with_stdio(false); cin>>n>>s; int cnt=0; for(int i=0; i<n; i++) { if(s[i]=='(') cnt++; else cnt--; } if(cnt) { cout<<"0\n1 1"<<endl; return 0; } int ans=solve(); int l=1,r=1; for(int i=0;i<n;i++) { for(int j=i+1;j<n;j++) { swap(s[i],s[j]); int tmp=solve(); if(tmp>ans) { l=i,r=j; ans=tmp; } swap(s[i],s[j]); } } cout<<ans<<endl; cout<<l+1<<" "<<r+1<<endl; return 0; }