[ AGC006 E ] Rotate 3x3

题目

Atcoder

思路

006E01.png 006E02.png
006E03.png

代码

#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;
}
posted @ 2021-05-29 12:34  Protein_lzl  阅读(36)  评论(0编辑  收藏  举报