cf1330 B. Dreamoon Likes Permutations(思维)
https://codeforces.com/contest/1330/problem/B
题意:
判断一个数组能否被分为左右两部分,左右各为一个置换(permutation)。输出所有分法。
如果在一个长度为 \(l\) 的数组中,\(1\sim l\) 的每个自然数都出现一次,就称为一个长度为 \(l\) 的置换
思路:
记数组最大值为 \(l\),则可能的分法只有左边 \(l\) 个,右边 \(n-l\) 个;或者左边 \(n-l\) 个,右边 \(l\) 个
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
int a[N];
bool flag, cnt[N];
signed main()
{
int T; cin >> T; while(T--)
{
set<pair<int, int> > ans;
int n, l = 0; cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
l = max(l, a[i]);
}
flag = 1;
fill(cnt, cnt+l+1, 0);
for(int i = 1; i <= l; i++)
{
if(!cnt[a[i]]) cnt[a[i]] = 1;
else //有重复数字
{
flag = 0; break;
}
}
if(flag)
{
fill(cnt, cnt+n-l+1, 0);
for(int i = n; i > l; i--)
{
if(!cnt[a[i]]) cnt[a[i]] = 1;
else //有重复数字
{
flag = 0; break;
}
}
}
if(flag) ans.insert({l, n-l});
flag = 1;
fill(cnt, cnt+n-l+1, 0);
for(int i = 1; i <= n-l; i++)
{
if(!cnt[a[i]]) cnt[a[i]] = 1;
else //有重复数字
{
flag = 0; break;
}
}
if(flag)
{
fill(cnt, cnt+l+1, 0);
for(int i = n; i > n-l; i--)
{
if(!cnt[a[i]]) cnt[a[i]] = 1;
else //有重复数字
{
flag = 0; break;
}
}
}
if(flag) ans.insert({n-l, l});
cout << ans.size() << '\n';
for(auto it : ans) cout << it.first << ' ' << it.second << '\n';
}
return 0;
}

浙公网安备 33010602011771号