题目大意:
有n个数字的某种排列方式,每一次可以交换某个偶数长度区间左右两部分,比如341256可以交换前四个数字,交换后为123456,最终形成1、2、3、4……n的排列,要求步骤数不能超过9^6=531441,输出方案
这道题其实模拟一下就行了,依次按顺序把1、2、3、4等等换入对应位置
有两种情况要考虑,第一种:
2 1 3 4
可以直接通过交换前两个数字,把1换入第一个位置
第二种:
2 3 4 1
1的位置比较靠后,无法一步完成,比如先交换到第一种情况,再利用第一种换入正确的位置
step1:4 1 2 3 step2:1 4 2 3
需要留意下标的计算!!
按照这个思路 每个数字最多2步操作,时间复杂度大约是n方的,可以AC
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
int n;
int a[10001];
void work()
{
vector<int> l,r;
for(int i=1;i<=n;i++)
{
if(a[i]==i) continue;
int k=i+1;
while(a[k]!=i) k++;
int rest=n+1-i;
if((k-i)*2>rest)
{
int half=rest/2;
for(int p=n+1-half*2,q=n+1-half;q<=n;p++,q++)
{
swap(a[p],a[q]);
}
k-=half;
l.push_back(n+1-half*2);
r.push_back(n);
}
for(int p=i,q=k;p<k;p++,q++) swap(a[p],a[q]);
l.push_back(i);
r.push_back(k+k-i-1);
}
printf("%d\n",l.size());
for(int i=0;i<l.size();i++) printf("%d %d\n",l[i],r[i]);
}
int main()
{
//freopen("in.txt","r",stdin);
int tc;
scanf("%d",&tc);
while(tc--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",a+i);
work();
}
return 0;
}