比赛链接:https://atcoder.jp/contests/abc213/tasks

A - Bitwise Exclusive Or

题意

给出两个值在 \([0, 255]\) 间的数 \(a,b\) ,找到一个非负数 \(c\) 使得 \(a \oplus c = b\)

题解

由异或的性质,输出 \(a \oplus b\) 即可。

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int a, b;
    cin >> a >> b;
    cout << (a ^ b) << "\n";
    return 0;
}
B - Booby Prize

题意

给出 \(n\) 个不同的数,输出第二大的数的位置。

题解

模拟。

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    vector<int> a(n);
    for (auto& x : a) {
        cin >> x;
    }
    vector<int> p(n);
    iota(p.begin(), p.end(), 0);
    sort(p.begin(), p.end(), [&](int x, int y) {
        return a[x] > a[y];
    });
    cout << p[1] + 1 << "\n";
    return 0;
}
C - Reorder Cards

题意

给出 \(n\) 个平面上的点,输出它们离散化后的相对行列位置。

题解

模拟。

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int h, w, n;
    cin >> h >> w >> n;
    vector<int> a(n), b(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i] >> b[i];
    }
    map<int, int> row, col;
    auto my_unique = [&](vector<int> v, bool map_row) {
        sort(v.begin(), v.end());
        v.resize(unique(v.begin(), v.end()) - v.begin());
        for (int i = 0; i < (int)v.size(); i++) {
            (map_row ? row : col)[v[i]] = i;
        }
    };
    my_unique(a, true);
    my_unique(b, false);
    for (int i = 0; i < n; i++) {
        cout << row[a[i]] + 1 << ' ' << col[b[i]] + 1 << "\n";
    }
    return 0;
}
D - Takahashi Tour

题意

给出一棵有 \(n\) 个结点的树,从根节点 \(1\) 出发,每次优先遍历序号较小的结点,如无结点可遍历则返回上一结点,试模拟该过程。

题解

即模拟一次带回溯的 \(dfs\) 过程。

代码

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    vector<set<int>> G(n);
    for (int i = 0; i < n - 1; i++) {
        int u, v;
        cin >> u >> v;
        --u, --v;
        G[u].insert(v);
        G[v].insert(u);
    }
    vector<int> path;
    function<void(int, int)> dfs = [&](int u, int p) {
        path.push_back(u);
        for (auto v : G[u]) {
            if (v != p) {
                dfs(v, u);
                if (G[u].size() >= 2 or u == 0) {
                    path.push_back(u);
                }
            }
        }
    };
    dfs(0, -1);
    for (auto i : path) {
        cout << i + 1 << ' ';
    }
    return 0;
}
E - Stronger Takahashi

题意

给出一个 \(h \times w\) ,由 .# 构成的网格,可以进行一种操作:

  • 将一个 \(2 \times 2\) 的网格全变为 .

问从左上角走到右下角所需的最少操作次数。

题解

先模拟 \(0\) 花费的 \(bfs\) 过程,然后假设在当前点进行了操作,那么与当前点哈密顿距离 \(\le 3\) 的点均可视作 \(1\) 花费的可达点,优先队列 \(bfs\) 即可。

代码

#include <bits/stdc++.h>
using namespace std;
const int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int h, w;
    cin >> h >> w;
    vector<string> MP(h);
    for (auto& s : MP) {
        cin >> s;
    }
    priority_queue<tuple<int, int, int>> pque;
    vector<vector<bool>> vis(h, vector<bool> (w));
    pque.emplace(0, 0, 0);
    while (not pque.empty()) {
        auto [d, x, y] = pque.top();
        pque.pop();
        d = -d;
        if (vis[x][y]) {
            continue;
        }
        vis[x][y] = true;
        if (x == h - 1 and y == w - 1) {
            cout << d << "\n";
            break;
        }
        for (int i = 0; i < 4; i++) {
            int nx = x + dir[i][0], ny = y + dir[i][1];
            if (0 <= nx and nx < h and 0 <= ny and ny < w and not vis[nx][ny] and MP[nx][ny] == '.') {
                pque.emplace(-d, nx, ny);
            }
        }
        for (int dx = -2; dx <= 2; dx++) {
            for (int dy = -2; dy <= 2; dy++) {
                if (abs(dx * dy) == 4) {
                    continue;
                }
                int nx = x + dx, ny = y + dy;
                if (0 <= nx and nx < h and 0 <= ny and ny < w) {
                    pque.emplace(-(d + 1), nx, ny);
                }
            }
        }
    }   
    return 0;
}