AtCoder Beginner Contest 157
比赛链接:https://atcoder.jp/contests/abc157
A - Duplex Printing
题意
计算 $n$ 页的文档双面打印要用多少张纸。
题解
答案即 $\lceil \frac{n}{2} \rceil$ 。
代码
#include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; cout << (n + 1) / 2; }
B - Bingo
题意
给出一个 $3\times3$ 的方格,方格中的数互不相同,给出 $n$ 个互不相同的数,判断其中在方格中出现的数是否位于方格的同一行、或同一列、或同一对角线中。
题解
模拟即可。
代码
#include <bits/stdc++.h> using namespace std; int main() { map<int, pair<int, int>> mp; int a[3][3] = {}; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { cin >> a[i][j]; mp[a[i][j]] = {i, j}; } } int row[3] = {}; int col[3] = {}; int diago[3] = {}; int n; cin >> n; for (int i = 0; i < n; i++) { int x; cin >> x; if (mp.count(x)) { ++row[mp[x].first]; ++col[mp[x].second]; if (mp[x].first == mp[x].second) ++diago[0]; if (mp[x].first + mp[x].second == 2) ++diago[1]; } } bool ok = false; for (int i = 0; i < 3; i++) { ok |= row[i] == 3; ok |= col[i] == 3; ok |= diago[i] == 3; } cout << (ok ? "Yes" : "No"); }
C - Guess The Number
题意
输出一个 $n$ 位长的最小数,要求每一指定位都为指定数字,除了 $0$ 以外不可以出现前导零。
题解
模拟即可。
代码
#include <bits/stdc++.h> using namespace std; int main() { int n, m; cin >> n >> m; bool ok = true; string ans(n, '0'); bool used[n] = {}; for (int i = 0; i < m; i++) { int s; cin >> s; char c; cin >> c; if (!used[s - 1]) { ans[s - 1] = c; used[s - 1] = true; } else if (ans[s - 1] != c) { ok = false; } } if (n > 1 and ans[0] == '0') { if (used[0]) ok = false; else ans[0] = '1'; } cout << (ok ? ans : "-1"); }
D - Friend Suggestions
题意
$n$ 个人中有 $m$ 对朋友关系,$k$ 对敌对关系,如果两个人既不是朋友关系也不是敌对关系且在同一朋友链中,称二者为彼此的朋友候选人,计算每个人有多少个朋友候选人。
题解
在一个并查集中:一个人的朋友候选人 = 并查集的总人数 - 并查集中的朋友数 - 并查集中的敌对数 - 自己。
所以先读入朋友关系构造并查集,然后根据朋友关系和敌对关系计算需要减去的人数即可。
代码
参考自:lukelmouse
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 100; int fa[N], size[N], ans[N]; int Find(int x) { return x == fa[x] ? x : fa[x] = Find(fa[x]); } void Union(int x, int y) { int fa_x = Find(x); int fa_y = Find(y); if (fa_x != fa_y) { fa[fa_y] = fa_x; size[fa_x] += size[fa_y]; } } void Init() { iota(fa, fa + N, 0); fill(size, size + N, 1); } int main() { Init(); int n, m, k; cin >> n >> m >> k; for (int i = 0; i < m; i++) { int x, y; cin >> x >> y; Union(x, y); ++ans[x], ++ans[y]; } for (int i = 0; i < k; i++) { int x, y; cin >> x >> y; if (Find(x) == Find(y)) ++ans[x], ++ans[y]; } for (int i = 1; i <= n; i++) cout << size[Find(i)] - ans[i] - 1 << ' '; }
E - Simple String Queries
题意
给出一个长 $n$ 的小写字母串 $s$,回答 $q$ 次询问:
- 将 $s_i$ 替换为小写字母 $c$
- 在区间 $[l,r]$ 中有多少种字母
题解一
利用 $set$ 存储每个小写字母的位置,每次二分查找是否有位置位于 $[l,r]$ 。
代码
参考自:harish_49
#include <bits/stdc++.h> using namespace std; set<int> st[26]; int main() { int n; string s; cin >> n >> s; for (int i = 1; i <= n; i++) st[s[i - 1] - 'a'].insert(i); int q; cin >> q; for (int i = 0; i < q; i++) { int op; cin >> op; if (op == 1) { int j; char c; cin >> j >> c; st[s[j - 1] - 'a'].erase(j); st[c - 'a'].insert(j); s[j - 1] = c; } else { int l, r; cin >> l >> r; int ans = 0; for (int j = 0; j < 26; j++) { auto it = st[j].lower_bound(l); if (it != st[j].end() and *it <= r) ++ans; } cout << ans << "\n"; } } }
题解二
为每个小写字母建立一个树状数组。
代码
参考自:zdragon
#include <bits/stdc++.h> using namespace std; const int N = 5e5 + 10; int bit[N][26]; void update(int pos, int id, int val) { for (int i = pos; i <= N; i += i & (-i)) bit[i][id] += val; } int query(int pos, int id) { int res = 0; for (int i = pos; i >= 1; i -= i & (-i)) res += bit[i][id]; return res; } int main() { int n; string s; cin >> n >> s; for (int i = 1; i <= n; i++) update(i, s[i - 1] - 'a', 1); int q; cin >> q; for (int i = 0; i < q; i++) { int op; cin >> op; if (op == 1) { int j; char c; cin >> j >> c; update(j, s[j - 1] - 'a', -1); update(j, c - 'a', 1); s[j - 1] = c; } else { int l, r; cin >> l >> r; int ans = 0; for (int j = 0; j < 26; j++) if (query(r, j) - query(l - 1, j)) ++ans; cout << ans << "\n"; } } }

浙公网安备 33010602011771号