AtCoder ABC228

ABC228参加しました。

atcoder.jp

今回はC,Dだけ解説します。

 

C - Final Day

解説 - AtCoder Beginner Contest 228

提出 #27385698 - トヨタシステムズプログラミングコンテスト2021(AtCoder Beginner Contest 228)

4日目、ある人(Aさんとします)だけが満点(300点)を取り、Aさん以外の人が0点を取ると、Aさんの点の上がり幅は最大となります。この状態でAさんの順位が何位になるかを計算しました。

二分探索で、Aさんが300点を取った状態の合計得点Sが、配列のどの位置に来るのかを調べました。

ただ、公式解答通り、 K番目の順位の人の点を調べておいて(上の仮定どおりやれば、Aさん以外の順位は不動のはずです)、その点よりSが上か下かを判断するだけでも十分です。二分探索なんていらなかった。

D - Linear Probing

解説 - AtCoder Beginner Contest 228

提出 #27418742 - トヨタシステムズプログラミングコンテスト2021(AtCoder Beginner Contest 228)

提出プログラムに詳しく書きました。公式解説の「解法2」に準じています。
Aに伴って変わる配列Pを考えP=(0,1,2,3..., N-1)とします。 また、A[m] = -1となる場所mを「Aの空き枠位置」と表現します。

P[h] には、A[h%N]==-1となるh%Nの値が入っています。
問題のcase1の手順2の部分で、A[h%N]==-1となるhを探すためにhをインクリメントしてますが、そのようなhがなかなか見当たらない場合に計算時間を消費します。
よって、A[h%N]==-1となるh%Nの値を求めるために、場所hから辿れる次のAの空き枠位置を配列Pで覚えておきます。

配列Pからh番目の次の空き場所を探す場合に使うメソッドがp(h)です。

また、A[h%N]が変化したら、空き枠も1つ消費されるので、次の空き枠位置を(h+1)%Nから探し手求めておきます。

pの内部で経路圧縮としてp()を再帰的に呼ぶのがミソでした。

感想

Dは空き枠管理という考え方は思いついたが、union-find的な考え方までは至らなかった。