Educational Codeforces Round 172 (Rated for Div. 2) 赛事记录

又要熬夜.

A. Greedy Monocarp

题意

你有 \(n\) 个箱子, 每个箱子最初有 \(a_i\) 个硬币.

现在有一个人, 他会贪心地按硬币多少从大到小拿箱子, 最终使得总共拿取的数量至少为 \(k\).

你现在想要他拿最少的硬币, 所以需要向里面添加硬币.

求必须添加的最少数量.

思路

贪心板子题.

我们先让其从大往小拿箱子, 直到剩余所需硬币数量小于箱子内的硬币个数为止.

这个剩余所需硬币数量即为答案.

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
#include "iostream" #include "algorithm" using namespace std; constexpr int N = 52; int n, k, a[N]; void init() { cin >> n >> k; for (int i = 1; i <= n; ++i) cin >> a[i]; sort(a + 1, a + n + 1); return; } void calculate() { int tot = k, pos = n; while (1) { if (tot < a[pos] or pos == 0) break; tot -= a[pos]; --pos; } cout << tot << '\n'; return; } void solve() { init(); calculate(); } int main() { int T; cin >> T; while (T--) solve(); return 0; }

T2

题意

如图.

思路

依旧贪心板子题.

考虑 Alice, 对其来说一定是先选数量少的弹珠更优(因为更有可能集齐).

而对于 Bob, 他想破坏 Alice 的计划, 所以他一定会尽可能地使 Alice 集不齐一种颜色.

而 Alice 是先手, 所以对于数量为一的弹珠, 她一定可以取到.

这样, 容易发现, 最优策略即为排序后隔一个取一个.
模拟即可.

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
#include "iostream" #include "algorithm" using namespace std; constexpr int N = 1e3 + 10; int n, a[N], cnt[N]; bool vis[N]; void init() { cin >> n; for (int i = 1; i <= n; ++i) cnt[i] = vis[i] = 0; for (int i = 1; i <= n; ++i) cin >> a[i], ++cnt[a[i]]; sort(a + 1, a + n + 1, [](int x, int y) { return cnt[x] == cnt[y] ? x < y : cnt[x] < cnt[y]; }); return; } void calculate() { int ans = 0; for (int i = 1; i <= n; i += 2) { if (cnt[a[i]] == 1 and !vis[a[i]]) ++ans; if (!vis[a[i]]) ++ans, vis[a[i]] = 1; } cout << ans << '\n'; return; } void solve() { init(); calculate(); } int main() { int T; cin >> T; while (T--) solve(); return 0; }

T3

题意

思路

考虑最终贡献:

\[(cnt1_{x_1} - cnt0_{x_1}) \times 0 + ((cnt1_{x_2} - cnt1_{x_1}) - (cnt0_{x_2} - cnt0_{x_1})) \times 1 + ... + ((cnt1_{x_n} - cnt1_{x_{n-1}}) - (cnt0_{x_n} - cnt0_{x_{n-1}})) \times (n - 1) \]

\(cnt_1,\ cnt_0\) 即为前 \(i\) 为 1, 0 的个数.

展开化简得:

\[(cnt0_{x_1}-cnt1_{x_1})+(cnt0{x_2}-cnt1{x_2})+...+(cnt0_{x_{n-1}}-cnt1{x_{n-1}})+(n-1) \times (cnt1_{x_n}-cnt0_{x_n}) \]

最后的 \((cnt1_{x_n}-cnt0_{x_n})\) 为定值, 先不考虑.

可以发现每一对括号内的 \(x_i\) 是互不影响的, 所以我们可以从大到小贪心地取(将 \((cnt0_{x_i}-cnt1_{x_i})\) 看做一个整体).

这样就又变成了贪心板子题.

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
#include "iostream" #include "algorithm" #include "numeric" #include "cstring" using namespace std; constexpr int N = 2e5 + 10; int n, k; string s; int cnt0[N], cnt1[N]; int f[N]; void init() { memset(cnt0, 0, sizeof cnt0); memset(cnt1, 0, sizeof cnt1); cin >> n >> k; cin >> s, s = " " + s; for (int i = 1; i <= n; ++i) { cnt0[i] = cnt0[i - 1] + (s[i] == '0'); cnt1[i] = cnt1[i - 1] + (s[i] == '1'); } iota(f + 1, f + n + 1, 1); sort(f + 1, f + n + 1, [](int x, int y) { int dx=cnt0[x]-cnt1[x],dy=cnt0[y]-cnt1[y]; if (dx==dy) return x<y; return dx>dy; }); return; } void calculate() { int tot = 0, pos = 1; while (1) { if (tot >= k or pos == n + 1) break; tot += cnt0[f[pos]] - cnt1[f[pos]]; tot += cnt1[n] - cnt0[n]; ++pos; } if (pos == n + 1) pos = -1; cout << pos << '\n'; return; } void solve() { init(); calculate(); } int main() { int T; cin >> T; while (T--) solve(); return 0; }

T4

题意

思路

排序 + 二分查找.

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
#include "iostream" #include "algorithm" #include "set" using namespace std; constexpr int N = 2e5 + 10; int n; struct Node { int l, r; int id; friend bool operator<(Node x, Node y) { if (x.l ^ y.l) return x.l < y.l; return x.r > y.r; } } a[N]; long long ans[N]; void init() { cin >> n; for (int i = 1; i <= n; ++i) { cin >> a[i].l >> a[i].r; a[i].id = i, ans[i] = 0; } return; } set<int> s; void calculate() { sort(a + 1, a + n + 1); for (int i = 1; i <= n; ++i) { auto it = s.lower_bound(a[i].r); if (it != s.end()) ans[a[i].id] += (*it) - a[i].r; s.insert(a[i].r); } s.clear(); for (int i = 1; i <= n; ++i) { a[i].l = 1e9 - a[i].l; a[i].r = 1e9 - a[i].r; swap(a[i].l, a[i].r); } sort(a + 1, a + n + 1); for (int i = 1; i <= n; ++i) { auto it = s.lower_bound(a[i].r); if (it != s.end()) ans[a[i].id] += (*it) - a[i].r; s.insert(a[i].r); } s.clear(); for (int i = 1; i ^ n; ++i) { if (a[i].l == a[i + 1].l and a[i].r == a[i + 1].r) ans[a[i].id] = ans[a[i + 1].id] = 0; } for (int i = 1; i <= n; ++i) cout << ans[i] << '\n'; return; } void solve() { init(); calculate(); return; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); int T; cin >> T; while (T--) solve(); return 0; }

后补.

posted @   Steven1013  阅读(159)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开