题解:P7015 [CERC2013] Crane

· · 题解

题意

翻译其实蛮清楚了,每次选择一段区间,将其前半部分与后半部分直接交换,从而把序列从小到大排序。构造一个操作序列即可。

这里补充一下原题面的点:序列是个 1n 的排列。

思路

对于每组数据:

具体可以见代码。

复杂度和操作分析

对于每组数据:

注意本题的多测限制。

Code

#include<bits/stdc++.h>
using namespace std;
int t,n,m,a[10005],b[10005];//b数组存位置
int s,l[114514],r[114514];
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>t;
    while(t--){
        cin>>n,m=1,s=0;
        for(int i=1;i<=n;++i) cin>>a[i],b[a[i]]=i;
        while(1){
            while(b[m]==m) ++m;
            if(m>n) break;
            while(b[m]!=m){//还没归位
                ++s,l[s]=m+(b[m]-m+1)%2,r[s]=b[m];
                int w=(l[s]+r[s])/2;
                for(int i=l[s];i<=w;++i){
                    swap(a[i],a[i+w-l[s]+1]);
                    swap(b[a[i]],b[a[i+w-l[s]+1]]);
                }
            }
        }
        cout<<s<<'\n';
        for(int i=1;i<=s;++i) cout<<l[i]<<' '<<r[i]<<'\n';
    }
    return 0;
}