UVa #1611 Crane (习题8-6)

86 篇文章 0 订阅

是不是很像摊煎饼那道例题,唯一的区别是这次是从中间开始交换左右两边的元素,而两边各自元素的顺序不变。


因此尝试每次将一个元素摆到正确的位置。尝试后发现,(稍微分奇偶讨论下)每个元素最多用两次就可以归位,所以复杂度最坏情况下是O(2n)


像其他需要交换元素位置的题目一样,这道题也需要注意一下边界。另外起始位置是0还是1也要小心。其他的就没有特别的了


Run Time: 0.768s

#define UVa  "8-6.1611.cpp"    //Crane
char fileIn[30] = UVa, fileOut[30] = UVa;

#include<cstring>
#include<cstdio>
#include<vector>
#include<ctime>

using namespace std;

//Global Variables. Reset upon Each Case!
const int maxn = 10000 + 10;
const int lim = 531441;
int T, n, A[maxn], P[maxn];
vector<int> ans[2];
int anscnt;
/

void swp(int* a, int l, int r) {
    int tmp[maxn];
    for(int i = 0; i < (r+1-l)/2; i ++) {
        int &a1 = a[l + i], &a2 = a[l + i + (r+1-l)/2];
        swap(a1, a2);
        swap(P[a1-1], P[a2-1]);
    }
}

int main() {
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for(int i = 0; i < n ; i ++) {
            scanf("%d", &A[i]);
            P[A[i]-1] = i;
        }

        anscnt = 0;
        ans[0].clear();
        ans[1].clear();

        for(int i = 0; i < n; i ++) {
            int p = P[i];
            if(i != p) {
                if(2*p-i-1 < n) {
                    swp(A, i, 2*p-i-1);
                    ans[0].push_back(i);
                    ans[1].push_back(2*p-i-1);
                    anscnt ++;
                }
                else {
                    if((p-i)%2 == 1) {
                        swp(A, i+2, p);
                        swp(A, i, p);
                        ans[0].push_back(i+2);
                        ans[1].push_back(p);
                        ans[0].push_back(i);
                        ans[1].push_back(p);
                        anscnt += 2;
                    }
                    else {
                        swp(A, i+1, p);
                        swp(A, i, p-1);
                        ans[0].push_back(i+1);
                        ans[1].push_back(p);
                        ans[0].push_back(i);
                        ans[1].push_back(p-1);
                        anscnt += 2;
                    }
                }
            }
        }
        printf("%d\n", anscnt);
        for(int i = 0; i < ans[0].size(); i ++) {
            printf("%d %d\n", ans[0][i]+1, ans[1][i]+1);
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值