jzoj 6307. 安排

Description

详见OJ

Solution

感觉\(OJ\)上的那个题解讲得很详细。
我们可以用分治(类似归并排序的思想)来解决问题。
详见题解,感觉自己也描述不清。
大概极限操作次数在\(O(n*log^2n/2)\),而且很难达到,所以不会爆。

Code

#include <cstdio>
#include <algorithm>
#define N 5010
#define mem(x, a) memset(x, a, sizeof x)
#define mpy(x, y) memcpy(x, y, sizeof y)
#define fo(x, a, b) for (int x = a; x <= b; x++)
#define fd(x, a, b) for (int x = a; x >= b; x--)
using namespace std;
int n, a[N], b[N], c[400010][2], tot = 0, tot1;

inline int read()
{
	int x = 0; char c = getchar();
	while (c < '0' || c > '9') c = getchar();
	while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
	return x;
}

void solve(int *q, int l1, int r1, int l2, int r2)
{
	if (l1 == r2) return;
	int l = r1, r = l2;
	while (q[l] > q[r] && l > l1 && r < r2) l--, r++;
	if (q[l] < q[r]) l++, r--;
	for (int a = l, b = r1; a < b; a++, b--)
		c[++tot][0] = a, c[tot][1] = b, swap(q[a], q[b]);
	for (int a = l2, b = r; a < b; a++, b--)
		c[++tot][0] = a, c[tot][1] = b, swap(q[a], q[b]);
	if (l <= r1 && r >= l2)
	{
		for (int a = l, b = r; a < b; a++, b--)
			c[++tot][0] = a, c[tot][1] = b, swap(q[a], q[b]);
	}
	if (l > l1 && l <= r1) solve(q, l1, l - 1, l, r1);
	if (r >= l2 && r < r2) solve(q, l2, r, r + 1, r2);
}

void merge(int *x, int l, int r)
{
	if (l == r) return;
	int mid = l + r >> 1;
	merge(x, l, mid), merge(x, mid + 1, r);
	solve(x, l, mid, mid + 1, r);
}

int main()
{
	freopen("swap.in", "r", stdin);
	freopen("swap.out", "w", stdout);
	n = read();
	fo(i, 1, n) a[i] = read();
	fo(i, 1, n) b[i] = read();
	merge(a, 1, n);
	tot1 = tot;
	merge(b, 1, n);
	printf("%d\n", tot);
	fo(i, 1, tot1) printf("%d %d\n", c[i][0], c[i][1]);
	fd(i, tot, tot1 + 1) printf("%d %d\n", c[i][0], c[i][1]);
	return 0;
}
posted @ 2019-08-17 22:27  jz929  阅读(154)  评论(0编辑  收藏  举报