[题解]CF1374F Cyclic Shifts Sorting

与 @Zelotz duel,苦战 129min AC。

思路

(本文中默认字符的大小顺序为:a<b<c<

首先发现不关心最后两个数是否合法,将前 n2 个位置变得递增是容易的。具体的,对于每一个位置 i,在最终的序列中的值记为 ti,那么在当前序列中找到一个位置 x,使得 ax=ti。这时候我们就可以将 x 暴力往前跳,需要注意的是当 x,i 奇偶不同时,在最后一步需要操作两次。

若现在最后两个数 ab 则直接合法了,否则只需考虑将最后两个数交换一下。手玩一下 n=3 的样例,注意到形如 aba 的串只需操作一次 1 即可合法。推广到 n3,若最后三位形如 aba 则通过操作一次 n2 即可。

其次,观察最后一个样例,它出现了形如 aacb 的结构,通过操作两次 1,两次 2 将串变成了 aabc。这启示我们如果能让 cb 贴上一个 aa,就可以换成 bc

不妨找到一个 id 使得 aid1=aid,若找不到一定无解。我们只需将最后两个数移动到 id+1,id+2 的位置上,做一次 aacb,然后再移回去。

具体的,你发现若两个点 xy 奇偶性相同,则 y 能通过一直操作达到 x;否则,需要调整一下 y 的奇偶再移动。若 id+1n1 奇偶不同,操作两次 n2,即可将最后两个数分别移到 n2,n1,此时可以直接移动。

若回来的时候奇偶不同,同理操作两次 id 再移动即可。因为前面将 n2 个数操作的步数带 12 的常数,所以若有解按照上述操作方式一定能在 n2 次操作中变化成功。

Code

#include <bits/stdc++.h>
#define re register

using namespace std;

const int N = 510;
int n;
int arr[N],tmp[N];
vector<int> ans;

inline int read(){
    int r = 0,w = 1;
    char c = getchar();
    while (c < '0' || c > '9'){
        if (c == '-') w = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9'){
        r = (r << 3) + (r << 1) + (c ^ 48);
        c = getchar();
    }
    return r * w;
}

inline void move(int x){
    ans.push_back(x);
    int a = arr[x],b = arr[x + 1],c = arr[x + 2];
    arr[x] = c; arr[x + 1] = a; arr[x + 2] = b;
}

inline void gopre(int a,int b){
    while (a - 2 >= b) move(a - 2),a -= 2;
    if (a != b) move(b),move(b);
}

inline void gonxt(int a,int b){
    while (a != b) move(a),move(a),a += 2;
}

inline void solve(){
    ans.clear(); n = read();
    for (re int i = 1;i <= n;i++) arr[i] = tmp[i] = read();
    sort(tmp + 1,tmp + n + 1);
    for (re int i = 1;i <= n - 2;i++){
        int id = 0;
        for (re int j = i;j <= n;j++){
            if (arr[j] == tmp[i]){
                id = j; break;
            }
        }
        gopre(id,i);
    }
    if (arr[n - 1] > arr[n]){
        if (arr[n] == arr[n - 2]) move(n - 2);
        else{
            int id = -1;
            for (re int i = 1;i < n;i++){
                if (arr[i] == arr[i + 1]) id = i + 2;
            }
            if (!~id) return puts("-1"),void();
            int a = n - 1,b = n;
            if ((n - 1) % 2 != id % 2){
                move(n - 2); move(n - 2);
                a = n - 2; b = n - 1;
            }
            gopre(a,id); gopre(b,id + 1);
            move(id - 2); move(id - 2);
            move(id - 1); move(id - 1);
            if ((n - 1) % 2 == id % 2){
                gonxt(id + 1,n); gonxt(id,n - 1);
            }
            else{
                move(id - 1); move(id - 1);
                gonxt(id,n); gonxt(id - 1,n - 1);
            }
        }
    }
    if (ans.size() > n * n) puts("-1");
    else{
        printf("%d\n",ans.size());
        for (int x:ans) printf("%d ",x); puts("");
    }
}

int main(){
    int T; T = read();
    while (T--) solve();
    return 0;
}

作者:WaterSun

出处:https://www.cnblogs.com/WaterSun/p/18575320

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   WBIKPS  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示