给出一个序列,能否把序列分成两段分别长L1和L2 \colorbox{Pink}{给出一个序列,能否把序列分成两段分别长L1和L2} 给出一个序列,能否把序列分成两段分别长L1和L2
满足前面那段[1,L1]的数刚好都出现1次,后面那段[1,L2]的数刚好出现一次 \colorbox{Pink}{满足前面那段[1,L1]的数刚好都出现1次,后面那段[1,L2]的数刚好出现一次} 满足前面那段[1,L1]的数刚好都出现1次,后面那段[1,L2]的数刚好出现一次
其 实 就 是 分 成 两 个 全 排 列 其实就是分成两个全排列 其实就是分成两个全排列
思 路 \color{Purple}{思路} 思路
用 一 个 L 数 组 表 示 i 前 的 数 是 否 能 形 成 一 个 全 排 列 用一个L数组表示i前的数是否能形成一个全排列 用一个L数组表示i前的数是否能形成一个全排列
用 一 个 R 数 组 表 示 i 后 的 数 是 否 能 形 成 全 排 列 用一个R数组表示i后的数是否能形成全排列 用一个R数组表示i后的数是否能形成全排列
那 么 统 计 答 案 时 只 要 L [ i ] 和 R [ i + 1 ] 同 时 为 真 就 可 行 那么统计答案时只要L[i]和R[i+1]同时为真就可行 那么统计答案时只要L[i]和R[i+1]同时为真就可行
如 何 判 断 是 否 为 全 排 列 呢 \color{Red}{如何判断是否为全排列呢} 如何判断是否为全排列呢
比 如 判 断 前 i 个 数 是 否 为 全 排 列 比如判断前i个数是否为全排列 比如判断前i个数是否为全排列
Ⅰ . 前 i 个 数 的 m a x x ( 最 大 数 ) 等 于 i Ⅰ.前i个数的maxx(最大数)等于i Ⅰ.前i个数的maxx(最大数)等于i
Ⅱ . 当 一 个 小 于 m a x x 的 数 出 现 且 没 有 标 记 Ⅱ.当一个小于maxx的数出现且没有标记 Ⅱ.当一个小于maxx的数出现且没有标记
那 就 标 记 起 来 , 同 时 n u m + + 那就标记起来,同时num++ 那就标记起来,同时num++
Ⅲ . 当 n u m = = m a x x 且 m a x x = = i 即 为 可 行 Ⅲ.当num==maxx且maxx==i即为可行 Ⅲ.当num==maxx且maxx==i即为可行
优 化 ( 正 解 ) \color{Red}{优化(正解)} 优化(正解)
其 实 每 种 样 例 只 有 两 种 情 况 其实每种样例只有两种情况 其实每种样例只有两种情况
由 于 两 个 段 必 定 有 一 个 包 含 m a x x ( a 数 组 的 最 大 值 ) 由于两个段必定有一个包含maxx(a数组的最大值) 由于两个段必定有一个包含maxx(a数组的最大值)
所 以 必 定 有 一 个 段 长 度 为 m a x x , 另 一 个 段 长 度 为 n − m a x x 所以必定有一个段长度为maxx,另一个段长度为n-maxx 所以必定有一个段长度为maxx,另一个段长度为n−maxx
然 后 只 需 要 判 断 两 次 即 可 , 暴 力 判 断 即 可 然后只需要判断两次即可,暴力判断即可 然后只需要判断两次即可,暴力判断即可
#include <bits/stdc++.h>
using namespace std;
const int maxn=200009;
int t,n,a[maxn],vis[maxn];
bool L[maxn],R[maxn];
void init(){
for(int i=0;i<=n;i++) vis[i]=0;
}
int main()
{
cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int num=0,maxx=0;
for(int i=1;i<=n;i++)
{
maxx=max(maxx,a[i]);
if(vis[a[i]]) continue;
if(a[i]<=maxx)
vis[a[i]]=1,num++;
if(num==maxx&&num==i) L[i]=true;
}
num=0,maxx=0;
init();
for(int i=n;i>=1;i--)
{
maxx=max(maxx,a[i]);
if(vis[a[i]]) continue;
if(a[i]<=maxx)
vis[a[i]]=1,num++;
if(num==maxx&&num==(n-i+1)) R[i]=true;
}
init();
int ans=0;
for(int i=1;i<=n-1;i++)
if(L[i]&&R[i+1]) ans++;
cout<<ans<<endl;
for(int i=1;i<=n-1;i++)
if(L[i]&&R[i+1]) cout<<i<<" "<<n-i<<endl;
for(int i=0;i<=n;i++) L[i]=R[i]=false;
}
}