[ AGC006 E ] Rotate 3x3
题目
思路
代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;
int n, w[4][N], to[N], st[N];
int main() {
cin >> n;
for (int i = 1; i <= 3; i++)
for (int j = 1; j <= n; j++)
cin >> w[i][j];
for (int i = 1; i <= n; i++) to[i] = 1;
for (int i = 1; i <= n; i++) {
int x = w[1][i], y = w[2][i], z = w[3][i];
if (x > z) to[i] = -1, swap(x, z);
// 最大的数一定是 3 的倍数
if (z % 3 != 0) return cout << "No" << endl, 0;
// 满足递增判断
if (z == y + 1 && y == x + 1) to[i] = to[i] * z / 3;
else return cout << "No" << endl, 0;
// 目标位置与当前位置的奇偶性判断
if ((i - abs(to[i])) & 1) return cout << "No" << endl, 0;
}
int tot[2]{};
for (int i = 1; i <= n; i++) tot[i & 1] += (to[i] < 0);
tot[0] %= 2, tot[1] %= 2;
// st 数组表示此列是不是正确位置
for (int i = 1; i <= n; i++)
if (st[i]) continue; // 已经是正确位置就跳过
// 不然就换过去, 再把新的换过去, 再接着换...直到自己和自己换就结束
// 每次循环都会换完一个, 总时间复杂度O(n)
else for (int v = abs(to[i]); !st[v]; v = abs(to[i])) {
st[v] = true, swap(to[i], to[v]);
// 注意如果自己跟自己换, 奇偶性不变
if (i != v) tot[(i & 1) ^ 1] ^= 1;
}
if (tot[0] || tot[1]) return cout << "No" << endl, 0;
cout << "Yes" << endl;
return 0;
}