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\n"); continue; } sum=0; for(int i=n;i>1;--i) solve(i-1,i); printf("%d\n",sum); for(int i=1;i<=sum;++i) printf("%d ",ans[i]); printf("\n"); } }