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;
}

posted @ 2021-10-21 23:37  Bellala  阅读(66)  评论(0)    收藏  举报