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\n",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\n",cnt);
        for(int i = 0; i < cnt; i++){
            OUT(L[i],R[i]);
        }
    }
    return 0;
}
时间: 2024-10-12 12:41:13

UVA 1611 Crane 起重机的相关文章

Uva 1611 Crane

Thinking about it: 对于一个长度为N的序列,最大的数字为N,那么如果要将它放回到第N个位置,那么最多需要2步. 先用例子简单证明一下: 假设序列:1 2 3 6 5 4,当前最大数为6,需要和4交换位置,那么可以看作:* * * 6 * 4,因为6和4之间有一个数,而6之前有三个数,那么可以之间把6之后的部分,与6(包括)之前的     等长部分交换,可得 : 1 2 5 4 3 6,此时只需要一步,即可.   若如果,6之前的数 小于 6与4之间的数呢,如 1 6 2 3 4

UVa 1611 Crane (构造+贪心)

题意:给定一个序列,让你经过不超过9的6次方次操作,变成一个有序的,操作只有在一个连续区间,交换前一半和后一半. 析:这是一个构造题,我们可以对第 i 个位置找 i 在哪,假设 i  在pos 位置,那么如果 (pos-i)*2+i-1 <= n,那么可以操作一次换过来, 如果不行再换一种,如果他们之间元素是偶数,那么交换 i - pos,如果是奇数,交换 i - pos+1,然后再经过一次就可以换到指定位置. 代码如下: #pragma comment(linker, "/STACK:1

UVA - 1611 Crane 推理 + 贪心

题目大意:输入一个1-n的排列,要求经过操作将其变换成一个生序序列.操作的规则如下 每次操作时,可以选一个长度为偶数的连续区间,交换前一半和后一半 提示:2n次操作就足够了 解题思路:这句提示是关键,2n次操作,表明每个数最多只需要两次操作. 应该从左到右依次操作过去,先将前面的数安定好了,就可以不用管前面的数了 假设操作到第i个位置,而i这个数刚好在pos这个位置上,现在就要判断一下能否直接将pos上的i经过操作调到i这个位置上 如果 i + (pos - i) * 2 - 1 <= n 就表

uva 1611:Crane(构造 Grade D)

题目链接 题意: 一个序列,你可以选择其中偶数长度的一段,然后中间切开,左右两段交换.现给你一个1~n的某个排列,求一个交换方案,使得排列最终有序.(交换次数 < 9^6) 思路: 从左到右,依次把一个个数放到位.把一个数放到正确的位置,观察发现最多两步.第i个数,若现在的位置在 [i+1, (n+i)/2] 内,则可以一次到位.若在它右边,则可以通过一次,使得其到这个范围内. 代码: #include <cstdio> #include <cstring> #include

UVa 1611 (排序 模拟) Crane

假设数字1~i-1已经全部归位,则第i到第n个数为无序区间. 如果i在无序区间的前半段,那么直接将i换到第i个位置上. 否则先将i换到无序区间的前半段,再将i归位.这样每个数最多操作两次即可归位. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 10000 + 10; 5 int a[maxn]; 6 vector<pair<int, int> > ans; 7 8 void

物流专业术语修正版

第一节 基本概念术语 1 article 物品 2 logistics 物流 3 logistics activity 物流活动 4 logistics operation 物流作业 5 logistics modulus 物流模数 6 logistics technology 物流技术 7 logistics cost 物流成本 8 logistics management 物流管理 9 logistics center 物流中心 10 logistics network 物流网络 11 lo

UVA 562 Dividing coins --01背包的变形

01背包的变形. 先算出硬币面值的总和,然后此题变成求背包容量为V=sum/2时,能装的最多的硬币,然后将剩余的面值和它相减取一个绝对值就是最小的差值. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 50007 int c[102],d

UVA 10341 Solve It

Problem F Solve It Input: standard input Output: standard output Time Limit: 1 second Memory Limit: 32 MB Solve the equation: p*e-x + q*sin(x) + r*cos(x) + s*tan(x) + t*x2 + u = 0 where 0 <= x <= 1. Input Input consists of multiple test cases and te

UVA 11014 - Make a Crystal(容斥原理)

UVA 11014 - Make a Crystal 题目链接 题意:给定一个NxNxN的正方体,求出最多能选几个整数点.使得随意两点PQ不会使PQO共线. 思路:利用容斥原理,设f(k)为点(x, y, z)三点都为k的倍数的点的个数(要扣掉一个原点O).那么全部点就是f(1),之后要去除掉共线的,就是扣掉f(2), f(3), f(5)..f(n).n为素数.由于这些素数中包括了合数的情况,而且这些点必定与f(1)除去这些点以外的点共线,所以扣掉.可是扣掉后会扣掉一些反复的.比方f(6)在f