A - Doors in the Center
分奇偶讨论
点击查看代码
void solve() {int n;std::cin >> n;if (n & 1) {std::string s = std::string(n / 2, '-') + "=" + std::string(n / 2, '-');std::cout << s << "\n";} else {std::string s = std::string(n / 2 - 1, '-') + "=";std::string ans = s;std::reverse(s.begin(), s.end());ans += s;std::cout << ans << "\n";}
}
B - Full House 3
判断出现次数最多的两个数是否满足条件。
点击查看代码
void solve() {int cnt[14]{};for (int i = 0; i < 7; ++ i) {int x;std::cin >> x;++ cnt[x];}std::sort(cnt, cnt + 14, std::greater<int>());if (cnt[0] >= 3 && cnt[1] >= 2) {std::cout << "Yes\n";} else {std::cout << "No\n";}
}
C - Uniqueness
题意:找一个位置它是唯一出现过的数里值最大的。
点击查看代码
void solve() {int n;std::cin >> n;std::vector<int> a(n);std::map<int, int> mp;for (int i = 0; i < n; ++ i) {std::cin >> a[i];++ mp[a[i]];}int ans = -1;for (int i = n - 1; i >= 0; -- i) {if (mp[a[i]] == 1) {if (ans == -1 || a[i] > a[ans - 1]) {ans = i + 1;}}}std::cout << ans << "\n";
}
D - Bonfire
题意:\((0, 0)\)处不断生成烟,每秒所有烟都会按照给出的序列移动,烟不会消失。求每个时刻\((r, c)\)这个位置有没有烟。
如果第\(i\)时刻有一团烟在\((r, c)\),那么就是有一个\([j, i]\)使得操作这个区间可以到\((r, c)\),那么用\(set\)存坐标的变化,如果当前坐标是\((x, y)\),判断有没有一个坐标是\((x - r, y - c)\)。
点击查看代码
void solve() {int n, r, c;std::cin >> n >> r >> c;std::string s;std::cin >> s;std::set<std::pair<int, int>> set;int x = 0, y = 0;set.insert({x, y});std::string ans(n, '0');for (int i = 0; i < n; ++ i) {if (s[i] == 'N') {-- x;} else if (s[i] == 'W') {-- y;} else if (s[i] == 'S') {++ x;} else {++ y;}if (set.count({x - r, y - c})) {ans[i] = '1';}set.insert({x, y});}std::cout << ans << "\n";
}
E - Tree Game
题意:交互题。给出一棵树,你和别人轮流加边,加边的规则是,这个边之前没有出现过,且加上这条边之后没有奇数环出现。你可以选择是先手还是后手。
每次都只能给距离是偶数的点连边。
那么把所有距离是偶数的点存下来,根据奇偶判断先手。
点击查看代码
std::pair<int, int> ask() {int u, v;std::cin >> u >> v;return {u, v};
}void solve() {int n;std::cin >> n;std::vector<std::vector<int>> adj(n);for (int i = 1; i < n; ++ i) {int u, v;std::cin >> u >> v;-- u, -- v;adj[u].push_back(v);adj[v].push_back(u);}std::vector d(n, std::vector<int>(n));for (int i = 0; i < n; ++ i) {auto dfs = [&](auto & self, int u) -> void {for (auto & v : adj[u]) {if (d[i][v] == 0) {d[i][v] = d[i][u] + 1;self(self, v);}}};d[i][i] = 1;dfs(dfs, i);}std::set<std::pair<int, int>> s;for (int i = 0; i < n; ++ i) {for (int j = i + 1; j < n; ++ j) {if (d[i][j] % 2 == 0) {s.insert({i, j});}}}for (int i = 0; i < n; ++ i) {for (auto & v : adj[i]) {s.erase({i, v});}}if (s.size() % 2 == 1) {std::cout << "First" << std::endl;} else {std::cout << "Second" << std::endl;auto [u, v] = ask();F - ABCBAif (u == -1) {return;}if (u > v) {std::swap(u, v);}-- u, -- v;s.erase({u, v});}while (s.size()) {std::cout << s.begin()->first + 1 << " " << s.begin()->second + 1 << std::endl;s.erase(s.begin());auto [u, v] = ask();if (u == -1) {return;}if (u > v) {std::swap(u, v);}-- u, -- v;s.erase({u, v});}
}
F - ABCBA
题意:找一个字符串,使得\(s\)是它的前缀,且这个字符串是回文,并且要求长度尽可能小。
我们要求最长的是回文的后缀,这个可以用\(hash\)。
点击查看代码
void solve() {std::string s;std::cin >> s;int n = s.size();std::vector<ui64> h(n + 1), rh(n + 1), p(n + 1);for (int i = 0; i < n; ++ i) {h[i + 1] = (131 * h[i] + s[i] - 'A');}for (int i = 0; i < n; ++ i) {rh[i + 1] = (131 * rh[i] + s[n - 1 - i] - 'A');}p[0] = 1;for (int i = 0; i < n; ++ i) {p[i + 1] = 131 * p[i];}auto get = [&](std::vector<ui64> & h, int l, int r) -> ui64{return (h[r] - h[l] * p[r - l]);};int pos = n;for (int i = n; i >= 1; -- i) {if (get(h, n - i + 1, n) == get(rh, 1, i)) {pos = n - i;break;}}std::string ans = s.substr(0, pos);std::reverse(ans.begin(), ans.end());ans = s.substr(0, pos) + s.substr(pos) + ans;std::cout << ans << "\n";
}