题目大意: 随机一段排列(n<2022且n为奇数) , 你必须在不超过5*n/2次操作的次数,将该排列变为单调递增。如果存在方法则输出操作次数以及每次操作的数,不存在则输出-1。
每次操作选择一个x(x为奇数)将1~x的数逆转 即 2 3 4 1 5 ->5 1 4 3 2。
思路
为什么要规定n为奇数并且x也为奇数呢?
纸上画一画会发现 每次逆转时,奇数位置上的数还是在奇数位置上,偶数位置上的数还是在偶数位置上。那么很明显对应的奇数位上的数必须是奇数,对应的偶数位上的数也是偶数。那么不存在的情况就显而易见了。
现在想想为什么会给5*n/2次操作次数?
会是每五次操作就可以让俩位数回归原位吗?
红色为最大值,蓝色为次大值。
这样子这道题就解决了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[2222];
vector<int>v;
int findmin(int m){
for(int i=1;i<=m;i++){
if(a[i]==m-1)return i;
}
return -1;
}
int findmax(int m){
for(int i=1;i<=m;i++){
if(a[i]==m)return i;
}
return -1;
}
void update(int x){
for(int i=1;i<=x;i++){
if(i==x-i+1)return;
swap(a[i],a[x-i+1]);
}
}
void solve(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
if((i&1)!=(a[i]&1)){
puts("-1");
return ;
}
}
int indexmi,indexmx;
for(int i=n;i>=3;i-=2){
indexmx=findmax(i);
update(indexmx);
v.push_back(indexmx);
indexmi=findmin(i);
update(indexmi-1);
v.push_back(indexmi-1);
update(indexmi+1);
v.push_back(indexmi+1);
update(3);
v.push_back(3);
update(i);
v.push_back(i);
}
cout<<v.size()<<endl;
for(int i=0;i<v.size();i++){
printf("%d ",v[i]);
}puts("");
v.clear();
}
int main(){
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}