CF1558 C. Bottom-Tier Reversals

https://codeforces.com/problemset/problem/1558/C

题意:

给出一个长为n(奇数)的排列,要求通过翻转奇数前缀的方式,使排列升序

至多可以做 n*5/2 次翻转

n为奇数,翻转不会改变数字所在位置的奇偶性

所以有解的前提是值为奇数的数在奇数位置,偶数在偶数位置

根据次数限制,可以猜测是用5次翻转使2个归位

考虑n(奇数)和n-1(偶数)

1、把n翻到第1个位置

2、把n翻到n-1的前面

3、翻转前n-1所在位置的后一个位置,即把n-1和n分别反转到第2、3位置

4、翻转前3个位置

5、翻转前n个位置

#include<bits/stdc++.h>

using namespace std;

#define N 2023

int n,a[N];
int sum,ans[N*3];

void ok(int x)
{
    ans[++sum]=x;
    reverse(a+1,a+x+1);
}

void solve(int x,int y)
{
    for(int i=1;i<=n;i+=2)
        if(a[i]==y)
        {
            ok(i);
            break;
        }
    for(int i=2;i<=n;i+=2)
        if(a[i]==x)
        {
            ok(i-1);
            ok(i+1);
            ok(3);
            ok(y);
            break;
        }
    
}

int main()
{
    int T;
    bool tag;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        tag=true;
        for(int i=1;i<=n;++i) 
        {
            scanf("%d",&a[i]);
            if((a[i]&1)!=(i&1)) tag=false;
        }
        if(!tag)
        {
            printf("-1
");
            continue;
        }
        sum=0;
        for(int i=n;i>1;--i) 
            solve(i-1,i);
        printf("%d
",sum);
        for(int i=1;i<=sum;++i) printf("%d ",ans[i]);
        printf("
"); 
    }
} 
作者:xxy
本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/15243464.html