Codeforces Round #611 (Div. 3)
比赛链接:https://codeforces.com/contest/1283
A - Minutes Before the New Year
题意
计算当前时间距离 $24:00$ 还有多少分钟。
Tips
小时要从 $23$ 减起。
代码
#include <bits/stdc++.h> using namespace std; void solve() { int h, m; cin >> h >> m; cout << 60 * (23 - h) + (60 - m) << "\n"; } int main() { int t; cin >> t; while (t--) solve(); }
B - Candies Division
题意
将 $n$ 个糖果分给 $k$ 个小朋友,要求所有小朋友分得的糖果数两两之差不多于 $1$,且分得最多糖果个数的小朋友不超过 $\lfloor \frac{k}{2} \rfloor$,可以保留一些糖果,问最多能分出多少糖果。
思路
先尽可能地平分糖果,然后加上 $\lfloor \frac{k}{2} \rfloor$ 和余下糖果中较小的值。
代码
#include <bits/stdc++.h> using namespace std; void solve() { int n, k; cin >> n >> k; int mi = n / k; cout << mi * k + min(k / 2, n - mi * k) << "\n"; } int main() { int t; cin >> t; while (t--) solve(); }
C - Friends and Gifts
题意
有 $n$ 个小朋友互赠礼物,但有的小朋友不知道该送给谁,试补全方案使得每个小朋友都能给出和得到一个礼物(不能自己送给自己)。
思路一
分别记录没有给出和得到礼物的小朋友,让既没有给出也没有得到礼物的小朋友们错位相赠,其余小朋友们互赠就可以了。
代码一
#include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; int f[n + 1] = {}; bool get[n + 1] = {}, give[n + 1] = {}; for (int i = 1; i <= n; i++) { cin >> f[i]; if (f[i] != 0) { give[i] = true; get[f[i]] = true; } } set<int> a, b; for (int i = 1; i <= n; i++) { if (!give[i]) a.insert(i); if (!get[i]) b.insert(i); } vector<int> v; for (int i = 1; i <= n; i++) { if (a.count(i) and b.count(i)) { a.erase(i); b.erase(i); v.push_back(i); } } if (v.size() == 1) { f[v[0]] = *b.begin(); b.erase(b.begin()); b.insert(v[0]); } else { for (int i = 0; i < v.size(); i++) f[v[i]] = v[(i + 1) % v.size()]; } for (int give : a) { auto it = b.begin(); f[give] = *it++; } for (int i = 1; i <= n; i++) cout << f[i] << ' '; }
思路二
分别记录没有给出和得到礼物的小朋友,如果存在自己送给自己的小朋友让前一个给出礼物的小朋友送给他,他送给前一个得到礼物的小朋友,因为前一对是两个不同的小朋友相赠的。
代码二
#include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; bool get[n + 1] = {}, give[n + 1] = {}; int f[n + 1] = {}; for (int i = 1; i <= n; i++) { cin >> f[i]; if (f[i] != 0) { give[i] = true; get[f[i]] = true; } } vector<int> a, b; for (int i = 1; i <= n; i++) { if (!give[i]) a.push_back(i); if (!get[i]) b.push_back(i); } for (int i = 0; i < a.size(); i++) { if (a[i] == b[i]) { if (i == 0) swap(a[i], a[i + 1]); else swap(a[i], a[i - 1]); } } for (int i = 0; i < a.size(); i++) { f[a[i]] = b[i]; } for (int i = 1; i <= n; i++) cout << f[i] << ' '; }
D - Christmas Trees
题意
有 $n$ 棵圣诞树和 $m$ 个人,已知数轴上 $n$ 棵圣诞树的位置,找出 $m$ 个位置,使得每个人距离附近的一棵圣诞树最近,并输出所有人最近距离之和。(每个人每棵树的位置两两不同)
思路
多源广搜,先找距离每棵圣诞树为 $1$ 的位置,然后是距离为 $2$ 的位置...直至找到 $m$ 个。(和 ABC161D、UVA - 136 有些类似)
代码
#include <bits/stdc++.h> using namespace std; int main() { int n, m; cin >> n >> m; int x[n]; for (int &i : x) cin >> i; map<int, int> d; queue<int> q; for (int i : x) d[i] = 0, q.push(i); long long ans = 0; vector<int> res; while (!q.empty()) { if (res.size() >= m) break; int cur = q.front(); q.pop(); if (d[cur] != 0) { ans += d[cur]; res.push_back(cur); } if (!d.count(cur - 1)) { d[cur - 1] = d[cur] + 1; q.push(cur - 1); } if (!d.count(cur + 1)) { d[cur + 1] = d[cur] + 1; q.push(cur + 1); } } cout << ans << "\n"; for (int i = 0; i < m; i++) cout << res[i] << ' '; }
E - New Year Parties
题意
数轴的一些点上有一些人,每个点 $x$ 处的每个人可以选择待在原地或移动到 $x - 1$ 或 $x + 1$ 处,一个人最多移动一次,问这些人最少和最多能占据多少点。
思路
最少的点:若当前点 $x$ 有人,则当前点的人可以与 $x + 2$ 处的人都移动到 $x + 1$ 处,然后跳至 $x + 3$ 处继续判断。
最多的点:每个点 $x$ 向左移动一人到 $x-1$,因为这样对后面的点最优,如果有多余的人数可以在保留 $x$ 点的人的前提下再向右移动一人至 $x+1$ 。
代码
#include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; int cnt[n + 3] = {}; int a[n]; for (int &i : a) cin >> i, ++cnt[i]; int mi = 0; for (int i = 1; i <= n; i++) if (cnt[i]) ++mi, i += 2; int mx = 0; for (int i = 1; i <= n; i++) if (cnt[i]){ if (!cnt[i - 1]) ++cnt[i - 1], --cnt[i]; if (cnt[i] > 1) ++cnt[i + 1], --cnt[i]; } for (int i = 0; i <= n + 1; i++) mx += cnt[i] > 0; cout << mi << ' ' << mx; }
F - DIY Garland
这篇博客已经讲得比较好了,不再赘述。

浙公网安备 33010602011771号