Minimize Permutation Subarrays

题意

本题要求从数组中任选两个数交换一次,使得数组中所有子段中排列的数量最少。

其中,排列指长度为 的数组包含 所有元素。

解析

首先, 本身就是一个排列,原数组本身也是一个排列,这都是无法改变的。

那么,对于剩下的排列,其中必须包含 。我们只需要让 之间的距离尽可能的远就可以了。夸张一下, 在最左端, 在最右端,那么所有的子串(除了 和原数组本身)都会因为少 或少 而导致无法组成排列。

可惜题目指允许交换一次,这种情况不一定能实现,但我们仍然可以往这条路上想。

除了 以外的排列,都必须包含 ,同时不能包含比该数组长度大的数。因此,我们将一个大数 放在 中间,这样一个子串若同时包含 ,就也包含这个 了。这种时候,除非该串的长度大于等于 ,否则它都不是一个排列。

我们直接拿原数组中最大的数 。这样,只需要使得 三者之间的相对位置符合 中间即可。在这种情况下,只有 与原数组能组成排列,将排列数控制在了最小的

至于根据相对位置交换,可以暴力解决。若原来的数组就符合这个条件,随便找两个数跟自己交换就能保持这个样子不变。

源码

#include<bits/stdc++.h>
using namespace std;
using ui=unsigned int;
int main(void){
    ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    size_t T;
    cin>>T;
    while (T--){
        size_t n;
        cin>>n;
        vector<ui> a(n);
        size_t onepos,twopos,npos;
        for (size_t i=0;i<n;i++) 
            cin>>a[i],
            a[i]==1?onepos=i+1  //记录1, 2, n的位置,用三目压行
            :a[i]==2?twopos=i+1
            :a[i]==n?npos=i+1
            :0;
        if (onepos < twopos && twopos < npos) cout<<twopos<<' '<<npos;
        if (onepos < npos && npos < twopos)   cout<<1<<' '<<1;
        if (twopos < onepos && onepos < npos) cout<<onepos<<' '<<npos;
        if (twopos < npos && npos < onepos) cout<<1<<' '<<1;
        if (npos < onepos && onepos < twopos) cout<<onepos<<' '<<npos;
        if (npos < twopos && twopos < onepos) cout<<twopos<<' '<<npos;
        cout.put('\n');
    }
    return 0;
}
posted @ 2023-07-04 19:49  MrPython  阅读(8)  评论(0)    收藏  举报  来源