首先观察数据可以发现答案
≤
2
\le 2
≤2(别问我怎么发现的
首先判掉
a
n
s
=
0
ans=0
ans=0 的情况
考虑
a
n
s
=
1
ans=1
ans=1 的情况(下面把
n
n
n 当做
n
∗
2
n*2
n∗2)
把
(
(
( 当成
1
1
1,
)
)
) 当成
−
1
-1
−1,令
s
i
s_i
si 为其前缀和
那么首先可以找到最小的
s
i
<
0
s_i<0
si<0 的
i
i
i 和最大的
s
n
−
s
i
−
1
<
0
s_n-s_{i-1}<0
sn−si−1<0 的
i
i
i,可以发现
s
n
=
0
s_n=0
sn=0,所以需要找到第一个和最后一个满足
s
i
<
0
s_i<0
si<0 的
i
i
i,令其分别为
L
,
R
L,R
L,R
那么一个合法的操作区间
[
l
,
r
]
[l,r]
[l,r] 需要满足
L
≤
l
≤
r
≤
R
L\le l\le r\le R
L≤l≤r≤R
考虑
[
1
,
l
−
1
]
[1,l-1]
[1,l−1] 和
[
r
+
1
,
n
]
[r+1,n]
[r+1,n] 的前缀和一定
≥
0
\ge 0
≥0
现在考虑
[
l
,
r
]
[l,r]
[l,r] 中
i
i
i 位置的前缀和会变成什么?即为
s
r
−
s
i
−
1
+
s
l
−
1
s_r-s_{i-1}+s_{l-1}
sr−si−1+sl−1
所以我们的目标是找到
[
1
,
L
]
[1,L]
[1,L] 中最大的
s
l
−
1
s_{l-1}
sl−1 的
l
l
l 以及
[
R
,
n
]
[R,n]
[R,n] 中最大的
s
r
s_{r}
sr 的
r
r
r,直接判断是否合法即可
考虑
a
n
s
=
2
ans=2
ans=2 的情况
我们只要找到最大
s
i
s_i
si ,交换
[
1
,
i
]
[1,i]
[1,i] 和
[
i
+
1
,
n
]
[i+1,n]
[i+1,n] 即可
为什么?
考虑对于
x
∈
[
1
,
i
]
x\in[1,i]
x∈[1,i],
s
x
s_x
sx 会变成
s
i
−
s
x
−
1
s_i-{s_{x-1}}
si−sx−1,因为
s
i
s_i
si 最大,所以这个值一定
≥
0
\ge 0
≥0
对于
x
∈
[
i
+
1
,
n
]
x\in [i+1,n]
x∈[i+1,n],同理
s
x
s_x
sx 会变成
s
n
−
s
x
−
1
+
s
i
=
s
i
−
s
x
−
1
≥
0
s_n-s_{x-1}+s_{i}=s_i-s_{x-1}\ge 0
sn−sx−1+si=si−sx−1≥0
时间复杂度 O ( n ) O(n) O(n)
#include
using namespace std;
const int N=200100;
int n,pref[N];
char str[N];
inline int read(){
int FF=0,RR=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
return FF*RR;
}
bool check(){
int s=0;
for(int i=1;i<=n;i++){
if(str[i]=='(') s++;
else s--;
if(s<0) return false;
}
return true;
}
void work(){
n=read();n<<=1;
scanf("%s",str+1);
for(int i=1;i<=n;i++){
if(str[i]=='(') pref[i]=pref[i-1]+1;
else pref[i]=pref[i-1]-1;
}
if(check()){ puts("0");return;}
int L,R;
for(int i=1;i<=n;i++) if(pref[i]<0){ L=i;break;}
for(int i=n;i;i--) if(pref[n]-pref[i-1]>0){ R=i;break;}
int mxr=R,mnl=L-1;
for(int i=R+1;i<=n;i++) if(pref[i]>pref[mxr]) mxr=i;
for(int i=0;i<L;i++) if(pref[i]>pref[mnl]) mnl=i;
mnl++;
reverse(str+mnl,str+mxr+1);
if(check()){
puts("1");printf("%d %d\n",mnl,mxr);
return;
}
int mxp=1;
for(int i=2;i<=n;i++) if(pref[i]>pref[mxp]) mxp=i;
puts("2");printf("%d %d\n%d %d\n",1,mxp,mxp+1,n);
}
int main(){
int T=read();
while(T--) work();
fprintf(stderr,"%d ms\n",int(1e3*clock()/CLOCKS_PER_SEC));
return 0;
}