CodeForces 1882E1 Two Permutations (Easy Version)

发布时间 2023-10-11 15:17:35作者: zltzlt

洛谷传送门

CF 传送门

考虑若是对一个排列进行操作,怎么做。

我们维护一个排列上的值域连续段 \([l, r]\),满足 \(a_{l + 1} = a_l + 1, a_{l + 2} = a_{l + 1} + 1\),以此类推。初始 \(l = r = 1\)

那么我们每次可以选择往外扩充一位 \(l\) 还是 \(r\)。以扩充 \(l\) 为例,我们把 \([l, r]\) 通过操作一次 \(l - 1\) 换到 \([1, r - l + 1]\),然后找到 \(a_l - 1\) 的位置 \(p\),操作 \(p\) 即可。

这样对于一个排列的操作次数是 \(2n\)

对于两个排列,我们可以分别得到它们的操作序列。

如果它们长度奇偶性相同,可以把短的一直补 \(1, n\) 直到和长的长度相等。

如果它们长度奇偶性不同:

  • 如果 \(n, m\) 有一个为奇数,不妨设 \(n\) 为奇数,那么把第一个排列的操作序列补 \(1, 2, \ldots, n\) 即可。
  • 否则无解。

可以通过找不变量(逆序对奇偶性)证明 \(n\) 为偶数时操作序列长度奇偶性固定。

当排列从 \(abc\) 变成 \(cba\) 时,变化的只有 \(a \to c\) 的贡献,\(a \to b\) 的贡献和 \(a \to c\) 的贡献。设原排列 \(a \to c\) 的逆序对数为 \(p_1\)\(a \to b\) 的逆序对数为 \(p_2\)\(b \to c\) 的逆序对数为 \(p_3\)\(a\) 部分的长度为 \(k\)。那么 \(c\) 部分的长度为 \(n - 1 - k\)

那么 \(abc \to cba\) 造成的逆序对变化为 \(k (n - 1 - k) - 2 p_1 + k - 2 p_2 + n - 1 - k - 2 p_3 = k (n - 1 - k) + n - 1 - 2 (p_1 + p_2 + p_3)\)。容易发现这个变化为奇数,所以每一次操作,逆序对奇偶性都会变化。

code
// Problem: E1. Two Permutations (Easy Version)
// Contest: Codeforces - Codeforces Round 899 (Div. 2)
// URL: https://codeforces.com/contest/1882/problem/E1
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 2520;

int n, m, a[maxn], b[maxn], c[maxn];

inline void work(int *a, int n, int p, vector<int> &ans) {
	ans.pb(p);
	for (int i = 1; i <= n; ++i) {
		c[i] = a[i];
	}
	int tot = 0;
	for (int i = p + 1; i <= n; ++i) {
		a[++tot] = c[i];
	}
	a[++tot] = c[p];
	for (int i = 1; i < p; ++i) {
		a[++tot] = c[i];
	}
}

inline bool check(int *a, int n) {
	for (int i = 1; i <= n; ++i) {
		if (a[i] != i) {
			return 0;
		}
	}
	return 1;
}

void solve() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++i) {
		scanf("%d", &a[i]);
	}
	for (int i = 1; i <= m; ++i) {
		scanf("%d", &b[i]);
	}
	vector<int> va, vb;
	int l = 1, r = 1;
	while (l != 1 || r != n) {
		int len = r - l + 1;
		if (a[l] > 1) {
			int t = a[l];
			if (l != 1) {
				work(a, n, l - 1, va);
			}
			for (int i = 1; i <= n; ++i) {
				if (a[i] == t - 1) {
					int k = a[i], p = -1;
					work(a, n, i, va);
					for (int j = 1; j <= n; ++j) {
						if (a[j] == k) {
							p = j;
							break;
						}
					}
					l = p;
					r = p + len;
					break;
				}
			}
		} else {
			int t = a[r];
			if (r != n) {
				work(a, n, r + 1, va);
			}
			for (int i = 1; i <= n; ++i) {
				if (a[i] == t + 1) {
					int k = a[i], p = -1;
					work(a, n, i, va);
					for (int j = 1; j <= n; ++j) {
						if (a[j] == k) {
							p = j;
							break;
						}
					}
					r = p;
					l = p - len;
					break;
				}
			}
		}
	}
	l = r = 1;
	while (l != 1 || r != m) {
		int len = r - l + 1;
		if (b[l] > 1) {
			int t = b[l];
			if (l != 1) {
				work(b, m, l - 1, vb);
			}
			for (int i = 1; i <= m; ++i) {
				if (b[i] == t - 1) {
					int k = b[i], p = -1;
					work(b, m, i, vb);
					for (int j = 1; j <= m; ++j) {
						if (b[j] == k) {
							p = j;
							break;
						}
					}
					l = p;
					r = p + len;
					break;
				}
			}
		} else {
			int t = b[r];
			if (r != m) {
				work(b, m, r + 1, vb);
			}
			for (int i = 1; i <= m; ++i) {
				if (b[i] == t + 1) {
					int k = b[i], p = -1;
					work(b, m, i, vb);
					for (int j = 1; j <= m; ++j) {
						if (b[j] == k) {
							p = j;
							break;
						}
					}
					r = p;
					l = p - len;
					break;
				}
			}
		}
	}
	if ((va.size() & 1) != (vb.size() & 1)) {
		if (n & 1) {
			for (int _ = 0; _ < n; ++_) {
				va.pb(1);
			}
		} else if (m & 1) {
			for (int _ = 0; _ < m; ++_) {
				vb.pb(1);
			}
		} else {
			puts("-1");
			return;
		}
	}
	int len = (int)max(va.size(), vb.size());
	printf("%d\n", len);
	bool f1 = 0, f2 = 0;
	for (int i = 0; i < len; ++i) {
		if (i < (int)va.size()) {
			printf("%d ", va[i]);
		} else {
			printf("%d ", f1 ? n : 1);
			f1 ^= 1;
		}
		if (i < (int)vb.size()) {
			printf("%d ", vb[i]);
		} else {
			printf("%d ", f2 ? m : 1);
			f2 ^= 1;
		}
		putchar('\n');
	}
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}