题目大意:通过一系列操作使一个1~n的序列变为升序,每次操作可以选一个长度为偶数的连续区间,交换前一半和后一半。
思路:从序列第一位开始,查找对应值(若为第一位则查找1,第二位查找2,以此类推)。若查找位置与查找到的值的位置相距长度为偶数,则以查找位置与查找到的值得位置的中心进行交换操作;若查找到的位置与查找到的值的位置相距长度为奇数,则以查找位置的后一位与查找到的值的位置的中心进行交换操作。如此不断循环,知道对应位置与对应值符合。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n,a[10005],sum=0,t;
vector<int> v;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
{
if(a[i]==i) continue;
for(int j=i;j<=n;j++)
{
if(a[j]!=i) continue;
int f,x=j;
while(x>i)
{
if((x-i)%2==1)
{
f=(x-i+1)/2;
for(int k=0;k<f;k++)
{
t=a[i+k];a[i+k]=a[i+k+f];a[i+k+f]=t;
}
v.push_back(i);
v.push_back(x);
sum++;
x-=f;
}
else if((x-i)%2==0)
{
f=(x-i)/2;
for(int k=0;k<f;k++)
{
t=a[i+1+k];a[i+1+k]=a[i+1+k+f];a[i+1+k+f]=t;
}
v.push_back(i+1);
v.push_back(x);
sum++;
x-=f;
}
}
}
}
cout<<sum<<endl;
for(int i=0;i<v.size();i+=2)
{
cout<<v[i]<<" "<<v[i+1]<<endl;
}
}
}