ABC116-D:Various Sushi
解法自体は素直なので400点なのだろうが,見た目はとっつきにくいので難しいと思った。
考察・解法
食べることにする寿司の集合を,のネタの種類をと書くと,の最大値を求めることになる。解法はさまざまだが,ここではの和にまず注目することにする。この部分を最大化するのは簡単で,が大きい個を取ればよい。これら個の集合をとしよう。これが最適解とは限らないというところが難しいのだが,これより良い解があるとしたら,それはネタの種類がより大きい場合に限る。だから,からネタの種類が増えるようにの要素の寿司を交換していくことを考えたくなる。さらにこのとき,おいしさの和の項ができるだけ大きくなるようにする(どうしても小さくなるわけだが,それを最小限にする)必要がある。これはどのようにすれば効率的な計算時間で可能だろうか?
まず,を決めるためにでソートしておく。これによりが大きい方から個とり,とを計算する。さらに,実際にに含まれるネタの種類とそれぞれの種類の寿司の数を記録しておく。ここまでやってスタートである。
ここからネタの種類を増やしていく。まず,番目にが大きい寿司のネタの種類を見る。同じネタがにあるなら,のどの寿司を入れ替えてもネタの種類は増えないし,おいしさの和は減るだけなので,交換する必要はない。がにない場合,何かと交換することでネタの種類が増える場合がある。この場合,交換に出すべきの寿司として最適なものは,「に2つ以上含まれるネタの寿司の中で,もっともおいしさが小さいもの」である。このような寿司を選ぶことで,おいしさの和が小さくなることを最小限に抑えることができる。に1つしか含まれない寿司を交換に出しても種類が変わらないことに注意しよう。
以上の手続きを繰り返すことで,おいしさの和を最小限に抑えながら,ネタの種類を増やしていくシミュレーションができる。食べる寿司の集合が更新されるごとに答えの候補として試し,最大値を出力する。計算時間はまたはでできる。
提出
Submission #4063050 - AtCoder Beginner Contest 116
これを実装してくださいと言われてもまだ大変かもしれない。上のコードでは,を求めたあと,とおき,これを交換する候補の最初のindexとしている。また,食べる寿司の集合のネタの種類と数はmapで管理した。ここから寿司が交換に出す寿司の候補としてふさわしいか判断し,だめなら寿司を試すということを繰り返している。となったら,もう交換に出せる寿司の種類はないということなので,処理を終了してよい。mapを使っているので計算時間はとなっている。
- ABC Only回としては難しい,でもこういう問題好きです。
- こどふぉと被っていて,こどふぉはratedなのでそっちに出ていた。
- 〇〇 Sushi という問題は難しめという謎の習慣...?