比赛链接: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;
}