题目大意:
有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; }