您的位置:首页 > 其它

uva 1611:Crane(构造 Grade D)

2014-09-26 11:57 441 查看
题目链接

题意:

一个序列,你可以选择其中偶数长度的一段,然后中间切开,左右两段交换。现给你一个1~n的某个排列,求一个交换方案,使得排列最终有序。(交换次数 < 9^6)

思路:

从左到右,依次把一个个数放到位。把一个数放到正确的位置,观察发现最多两步。第i个数,若现在的位置在 [i+1, (n+i)/2] 内,则可以一次到位。若在它右边,则可以通过一次,使得其到这个范围内。

代码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cassert>
#include <algorithm>
using namespace std;
#define N 10100

int a
;
int id
;
int n;

struct Ans{
int l, r;
Ans(int _l=0, int _r =0) : l(_l), r(_r){}
}ans[2*N];
int ap;

void myswap(int l, int r) {
ans[ap++] = Ans(l,r);
//printf("l = %d, r = %d\n", l, r);
assert((r-l+1)%2 == 0);
int mid = (l+r)/2;
int lp = l;
int rp = mid+1;
while (lp <= mid) {
swap(id[a[lp]], id[a[rp]]);
swap(a[lp], a[rp]);
lp++; rp++;
}

//puts("after---");
//for (int i = 0; i < n; i++) {
//    printf("%d ", a[i]+1);
//}puts("");
}

int main() {
int t;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
a[i]--;
}
for (int i = 0; i < n; i++) {
id[a[i]] = i;
}

ap = 0;
for (int i = 0; i < n; i++) {
if (id[i] == i) continue;

int flag = (n+i)/2;
if (id[i] > flag) {
myswap( flag - (id[i]-flag-1) ,id[i] );
}
//printf("i = %d,  swap(%d->%d)\n", i, i, id[i]+(id[i]-i-1));
myswap(i, id[i] + (id[i]-i-1));
}
//for (int i = 0; i < n; i++) {
//    printf("%d ", a[i]);
//}puts("");

printf("%d\n", ap);
for (int i = 0; i < ap; i++) {
printf("%d %d\n", ans[i].l+1, ans[i].r+1);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: