zoukankan      html  css  js  c++  java
  • UVA 1611 Crane 起重机 (子问题)

    题意:给一个1~n排列,1<=n<=10000,每次操作选取一个长度为偶数的连续区间。交换前一半和后一半,使它变成升序。

    题解:每次只要把最小的移动到最左边,那么问题规模就缩小了。假设当前区间为[l,r],不难发现,只要最小的数字在[l,l+(r+1-l)/2]这个区间内,一定可以通过一次交换把最小的数字移动到l处,否则,先一定可以一次交换把最小的数字移动到上述区间中。

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e4+5;
    int a[maxn],pos[maxn];
    
    inline void exchange(int s1,int s2)
    {
        int len = s2 -s1;
        for(int i = s1, maxi = s1+len; i < maxi; i++){
            swap(pos[a[i]],pos[a[i+len]]);
            swap(a[i],a[i+len]);
        }
    }
    
    int L[maxn<<1],R[maxn<<1];
    
    #define OUT(a,b)
    printf("%d %d
    ",a,b)
    
    #define ADDANS(l,r) L[cnt] = l;R[cnt++] = r
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        int T; scanf("%d",&T);
        while(T--){
            int n; scanf("%d",&n);
            for(int i = 1; i <= n; i++){
                scanf("%d",a+i);
                pos[a[i]] = i;
            }
            int cnt = 0;
            for(int i = 1,tmp = n+1; i < n; i++ )if(pos[i]!=i) {
                if( pos[i]<<1 > tmp+i ){
                    int len = tmp - i;
                    if(len&1){
                        ADDANS(i+1,n);
                        exchange(i+1,i+1+(len>>1));
                    }else {
                        ADDANS(i,n);
                        exchange(i,i+(len>>1));
                    }
                }
                ADDANS(i,(pos[i]<<1)-i-1);
                exchange(i,pos[i]);
            }
            printf("%d
    ",cnt);
            for(int i = 0; i < cnt; i++){
                OUT(L[i],R[i]);
            }
        }
        return 0;
    }
  • 相关阅读:
    自己回答自己的问题
    作业5 四则运算 测试与封装 5.1 5.2
    2015430 加法阶段一的封装测试
    20150423 提问2
    Java 泛型中的<? super T>和<? extends T>
    ssh 查看端口占用
    Java 回调
    SpringMVC4+MyBaits3配置
    Selenium 远程执行和监听类
    Intellij idea主题
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4700329.html
Copyright © 2011-2022 走看看