题目大意:给一个1~n的序列,每次操作可以把长度为偶数的序列交换前一半和后一半的位置。求出将这个序列变成升序的步骤。
题目分析:构造求解。
代码如下:
# include<iostream>
# include<cstdio>
# include<queue>
# include<cstring>
# include<algorithm>
using namespace std;
int a[10005],pos[10005],n;
queue<int>L,R;
void print(int ans)
{
printf("%d\n",ans);
while(!L.empty()){
printf("%d %d\n",L.front(),R.front());
L.pop(),R.pop();
}
}
void change(int l,int r)
{
L.push(l),R.push(r);
for(int i=l,j=l+(r-l)/2+1;j<=r;++i,++j){
pos[a[i]]=j,pos[a[j]]=i;
swap(a[i],a[j]);
}
}
void solve()
{
while(!L.empty()) L.pop();
while(!R.empty()) R.pop();
int l=1,ans=0;
while(l<=n)
{
for(int i=l;i<=n;++i){
if(a[i]==i){
++l;
continue;
}
++ans;
int p=pos[i];
if(2*p-i-1<=n)
change(i,2*p-i-1);
else{
if((p-i)&1)
change(i,p);
else
change(i+1,p);
}
if(a[i]==i)
++l;
break;
}
}
print(ans);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",a+i);
pos[a[i]]=i;
}
solve();
}
return 0;
}