【AtCoder】ABC 461 C - Variety

C - Variety
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
AtCoder
実行時間制限: 2 sec / メモリ制限: 1024 MiB / Difficulty: 332 / NoviSteps: 3Q / 配点: 300 点
問題概要
個の宝石があり、 番目の宝石の色は で価値は である。
この 個の宝石の中から 個を選ぶことを考える。 ただし、選んだ宝石の色が 種類以上なければなければならない。
このとき、選んだ宝石の価値の総和としてありうる最大値を求めよ。
制約
- 種類以上の色の宝石が存在する
- 入力される値はすべて整数
考察
色の種類を無視すれば、単純に価値の高い方から 個を選べばよい。
そのような選び方で色の種類数が足りない場合は、まだ選ばれていない色の宝石を追加する必要があり、代わりに同じ色で2個目以降の宝石を削除しなければならない。
つまり、
- まだ選んでいない色から「その色で最も価値が高い宝石」を追加候補にする
- すでに選んでいる宝石のうち「同じ色で2個目以降の宝石」を削除候補にする
としたうえで、最も価値の高い追加候補と、最も価値の低い削除候補を交換するような操作を、色の種類数が 以上になるまで繰り返せばよい。
実装例
CPP
1.#include <bits/stdc++.h>2.using namespace std;3. 4.#define all(x) (x).begin(), (x).end()5.#define rall(x) (x).rbegin(), (x).rend()6.#define rep(i, start, end) for (auto i = (start); (i) < (end); (i)++)7. 8.using ll = long long;9.using Pair_ll = pair<ll, ll>;10. 11.template <typename T>12.inline bool chmax(T& a, T b) { return ((a < b) ? (a = b, true) : (false)); }13. 14.// ======================================== //15. 16.int main()17.{18. int N, K, M;19. cin >> N >> K >> M;20. vector<Pair_ll> jewels(N);21. rep(i, 0, N) cin >> jewels[i].first >> jewels[i].second;22. 23. sort(all(jewels), [](auto& a, auto& b) {24. if (a.second == b.second)25. return a.first > b.first;26. return a.second > b.second;27. });28. 29. vector<int> cnt(N, 0);30. vector<ll> remove_cands;31. 32. ll ans = 0;33. int kinds = 0;34. rep(i, 0, K) {35. auto [c, v] = jewels[i];36. c--;37. 38. ans += v;39. 40. if (cnt[c] == 0) {41. kinds++;42. }43. else {44. remove_cands.push_back(v);45. }46. 47. cnt[c]++;48. }49. 50. if (kinds >= M) {51. cout << ans << endl;52. return 0;53. }54. 55. vector<ll> best_add(N, -1);56. rep(i, K, N) {57. auto [c, v] = jewels[i];58. c--;59. 60. if (cnt[c] == 0)61. chmax(best_add[c], v);62. }63. 64. vector<ll> add_cands;65. rep(c, 0, N) {66. if (best_add[c] != -1) {67. add_cands.push_back(best_add[c]);68. }69. }70. 71. sort(rall(add_cands));72. sort(all(remove_cands));73. 74. rep(i, 0, M - kinds) {75. ans += add_cands[i];76. ans -= remove_cands[i];77. }78. 79. cout << ans << endl;80. 81. return 0;82.}
Submission #76508721 - AtCoder Beginner Contest 461
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
AtCoder
実装時間: 15分
コメント
公式解説でいうと実装例は解法2にあたるが、解法1の方が実装は簡単そう。





