リアルタイム受験した。4時間40分かけて全完。前回に比べるとかなり苦戦した。
F
別解っぽいの:
の降順に埋められるできるだけ早い日を埋めていく貪欲が成立する。(交換しても損しないことに注目すればよい。) このとき、 日目以降(inclusive)でまだ埋めていない最も早い日、として空きを管理する。を辿る際にpath compressionするとたぶん。
K
(
を見るとネストの深さが+1され、)
を見ると深さが-1されると考えると、文字を削除(=無視)するのは深さを変えないで次に進むことと解釈できる。したがって、次のようなDPが可能である:
文字目まで見て、深さがの場合の最小コスト
答えはに等しい。。
L
個の要素を選ぶ際、先頭から番目(0-based)の数の元のインデックス(0-based)はを満たす必要があり、その中で最小(タイブレークはもっとも左)の数を選べばよい。優先度付きキューでできる。
M
今回いちばん大変だった問題で、最後にACした。
数列をいくつかつなげたものを走査して、各食事についての情報を累積していく。具体的には、に(日付, この日付までに食べた料理の数, この日付までに食べた以外の料理の数)の日付に関する昇順配列を作って、料理が出るたびに情報を追加していった。こうすると、ある日付から一巡したときに食べる好みの料理の数と好みでない料理の数は二分探索でわかるので、何周するか計算すればよい。ただし、端の処理をするのがかなりつらかった……
N
平面走査する。座標を圧縮しておいて座標に関して走査した。
O
問題の条件を無視して最小全域木を得たとする。に外の任意の辺を追加すると閉路ができるが、この閉路上でもっとも重みの大きな(以外の)辺を除けば求める最小全域木が得られる。(正当性は最適性条件により明らか……と言いたいところだが、そんなに簡単な証明を思いつかなかった。下に書いた。)この「辺の重みの最大値」は上のパスに関するクエリを処理すれば得られる。
やることはわかったのだが、そもそも木上のパスクエリを処理した経験があまりない。単純なオイラーツアーではmin/maxの処理ができないように見えるし、HL分解やLC木は持っていないし、Mo's algorithmではの遷移が思いつかないし、しばらく困っていた。HL分解を調べて書こうと決めたところで、そもそも更新がないのでLCAのbinary liftingがそのままmin/maxクエリにも使えることに気づいた。やっぱり経験がないとこういうことがぱっとわからないな。
証明: のコストをとし、このコストをに変えたグラフをとする。また、のMST が与えられたとして、そのコストの総和をとする。(path optimality conditionより)はを必ず含むので、は上でコストの全域木になっている。のを含む全域木 でこれより総コストの低いものが存在すると仮定して、総コストをとする。はの全域木でもあり、コストの総和はだが、なので、がMSTであるという仮定に反する。したがって、求める全域木はのMSTであることがわかった。
あとは、上の作り方でできた全域木が上でMSTであることを示せばよい。外の任意の辺を追加すると閉路ができるが、この閉路に含まれる以外の辺は(のにおけるpath optimality conditionより)以下の重みを持つし、自身は重みなので、やはり以下の重みを持つ。したがって、は上でpath optimality conditionを満たす。
後半は有名事実だと思うけど若干雑…… 書き直すかも