令 $m$ 为不超过 $\lfloor \frac{n}{2} \rfloor$ 的最大奇数。
对前一半 $(1 \sim \lfloor \frac{n}{2} \rfloor)$,首先用 $m+1$ 的反转归位,到了当前位置离目标位置小于 $m+1$ 的时候,把他反转到目标 $+m$ 的位置。
对于后半部分,考虑交换任意 $u$ 和 $v$ 的位置。
你考虑同时操作 $m+1$ 和 $m-1$ 可以仅交换 $i$ 和 $i+m$ 位置上的值。
所以,当 $v$ 不等于 $u+m$ 的时候,先把他扔到 $[u,u+m]$ 里,如果他俩奇偶性不同,则执行一次交换让他俩奇偶性相同。
然后,你就直接找到一个中点反转,就能归位了。
题解做法好像反过来了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| #include<bits/stdc++.h> using namespace std; int n,a[1005],cnt; pair<int,int>b[1000005]; void print(){ for(int i=1;i<=n;++i){ cout<<a[i]<<' '; if(i%10==0)cout<<endl; } cout<<endl; } int main(){ cin>>n; for(int i=1;i<=n;++i)cin>>a[i]; if(n>10){ int m=n/4; if(!(m&1))--m; for(int i=1;i*2<=n;++i){ int j=i; while(j<n&&a[j]!=i)++j; while(j-m>=i){ reverse(a+j-m,a+j+1); b[++cnt]={j-m,j};j-=m; } if(i==j)continue; int l=i,r=i+m; if((l-j)&1){ reverse(a+j,a+j+m+1); b[++cnt]={j,j+m};j+=m; } reverse(a+(r+j)/2-(m+1)/2+1,a+(r+j)/2+(m+1)/2+1); b[++cnt]={(r+j)/2-(m+1)/2+1,(r+j)/2+(m+1)/2}; reverse(a+r-m,a+r+1); b[++cnt]={r-m,r}; } for(int i=n;i>=n/2+1;--i){ int j=i; while(j>1&&a[j]!=i)--j; while(j+m<=i){ reverse(a+j,a+j+m+1); b[++cnt]={j,j+m};j+=m; } if(j==i)continue; int l=i-m,r=i,t=0; if((r-j)&1){ reverse(a+j-m,a+j+1); b[++cnt]={j-m,j};j-=m;t=1; } reverse(a+(l+j)/2-(m+1)/2+1,a+(l+j)/2+(m+1)/2+1); b[++cnt]={(l+j)/2-(m+1)/2+1,(l+j)/2+(m+1)/2}; reverse(a+l,a+l+m+1); b[++cnt]={l,l+m}; reverse(a+l+1,a+l+m); b[++cnt]={l+1,l+m-1}; reverse(a+(l+j)/2-(m+1)/2+1,a+(l+j)/2+(m+1)/2+1); b[++cnt]={(l+j)/2-(m+1)/2+1,(l+j)/2+(m+1)/2}; if(t)reverse(a+j,a+j+m+1),b[++cnt]={j,j+m}; } cout<<m<<'\n'<<cnt<<'\n'; for(int i=1;i<=cnt;++i)cout<<b[i].first<<' '<<b[i].second<<'\n'; return 0; } cout<<3<<'\n'; for(int i=1;i<=n;++i){ if(a[i]!=i){ int id=i+1; for(int j=i+1;j<=n;++j) if(a[j]==i){id=j;break;} int j=id; for(j=id;j>=i+3;j-=3){ reverse(a+j-3,a+j+1); b[++cnt]={j-3,j}; } for(;j>i;--j){ b[++cnt]={j-1,j}; swap(a[j-1],a[j]); } } } cout<<cnt<<'\n'; for(int i=1;i<=cnt;++i)cout<<b[i].first<<' '<<b[i].second<<'\n'; return 0; }
|