UVA-1611 Crane (构造)
题目大意:给一个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; }