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;
}

  

posted @ 2015-10-18 13:13  20143605  阅读(192)  评论(0编辑  收藏  举报