ARC112

4完。時間をかけてしまった感覚はあるがノンペナのほうが大きい。これで黄色初防衛。この2週間、ずっとそれを望んでいた。無難に休むのではなく、気持ちを競プロにぶつけた。(Dを通す時間が残っていないという意味で)Cで時間を使ってしまったとき、Dで詰まったときは覚悟したが、その後も最善を尽くしたことが奏功した。コンテスト後に地震

A - B = C

A=B+C と同値な式に変形して、L+L で既にRを超えてしまうような場合は0通り。そうでないとき、L+L は範囲内であり、どこまで増やせるかというと片方をLに固定してみると L+(R-L) がちょうどRになる。その間で自由に動かせると思ったら四角形じゃなくて三角形だった。1から (R-L)-L+1 まで足せばいい。正の数になっていることを確認しながらやる。非負整数を扱うので B+C がLを下回ることはない(この点で簡単)。なんとか9分で通したけど、初っ端からきつい問題だった。

B - -- - B

境界がかなり厄介なやつ。符号を反転させるときコスト1かかるし、0だけ絶対値が等しい数が1個しかない。数直線ではなく、左端に0を書いてその右に1と-1を上下に書きその右に2と-2というように書き、有向グラフにすると見通しが良くなった。解けそうなのはわかるのだが、どう考えるとわかりやすいかがなかなか見えない。最終的に、絶対値がBと小さい・同じ・大きいで分けて考えるのがよかった。絶対値が同じ数には全部行ける(Cは1以上なので)(0がコーナーケースでサンプルに助けられた)。絶対値が大きい数は、負の数がC/2個、正の数が(C-1)/2個(除算は切り捨て)、ただしBが正のときは最初にコスト1で符号を変える。絶対値が小さい数は、min(C/2, abs(B)) で、Bが負のときは最初にコスト1で符号を変える。ある整数を目指すとき行動は固定されるのでその意味では簡単だが、具体的に全部網羅するのは当然ながらきつい。

C - DFS Game

高橋くんがあの笑顔でどんどんコインを取っていく絵が浮かぶ。どういうときに体が入れ替わるのだろう。木を描いてみて、問題名の通りDFSだと思う。頂点と辺を順に選んでいくとして、頂点は1回しか選ばれない、辺は往復で2回。このときはよくわかっていなかったが、頂点の数の偶奇が重要で、頂点数が奇数だと手番が入れ替わる。総手数は一定だ。さて、普通にグラフを構築してDFSする。各頂点について、対応する部分木でゲームをしたときのスコア(手番から見た得失点差とした)と手番が入れ替わるかどうかを求めていく。子の部分木が全部解けているときにじゃあどうするかで苦戦した。ここがこの問題のコアだろう。スコアが負かどうか、手番が入れ替わるかどうかで場合分けして、基本は手番が入れ替わるものをスコアがいい順に交互に取っていく。スコアが非負のものは最初の人(手番の人)が全部取って、負のものは最後の「手番が入れ替わるもの」を取った次の人に押し付ける。入れ替わるものが存在しないときは手番の人が全部取るだけ。ソートしてもlogが付くだけなのでOK。符号と手番がややこしく、サンプルがなかなか合わない。手番は、コインを取ったら相手に渡る(相手が、最初にどの子を選ぶか決める権利を持つ)。スコアの符号は、子のコインを取るのは子を選んだ人ではないので、符号を反転させる。1時間近くかかったけど、よく書き切った。

昨日のyukicoderで思ったけど、自分はサンプルにずいぶん助けられている。ペナルティを出すことは比較的少ないが、支えなしにきっちり考察して書く力があるわけではないことを痛感した。

D - Skate

高橋くんが壁にぶつかったときの止まる位置はマスの端っこなのかなとか考えてた。まあ位置はどのマスの上にいるかだけで表される(必要な情報はそれだけである)んだろうけど、なかなか確信が持てなかった。まず、与えられた配置から行けるマスを列挙するだけでも少し考える(新しい地面に来る度に2000マス調べてたら間に合わない)。これを考えて、ある地面に辿り着けばその行や列は全部行けること、全部のマスを通過するには全部の行または全部の列をカバーする必要があること、といった結果を得る。また、「どのマスから見ても」という条件は、そのマスからでも左上隅へは行けるので左上隅から見て全部のマスに行ければよい。とりあえずこの状況に対する理解を深めるために現状で行けるマスを求めるコードを実装する。H個の行とW個の列を頂点とするグラフで地面で行と列の間に辺を張りBFSする。実装が終わるころ、UnionFindが降りてきた。これは天才。時間内ACが現実味を帯びてきた。まあBFSでもできるけど、連結成分を求めて、H個の行が5個の連結成分に分かれていたらくっつけるのに4個の地面が必要みたいな。辺を1個追加しても連結成分は高々1しか減らないし、地面を適切に1個追加することで連結成分は1減らせる(ということをぼんやりと確認)。BFSのときは1個頂点を追加してそこからスケートリンクの縁の2行2列に辺を張ってたけど、連結成分を数えるならということで入力を受け取ってから四隅を'#'に書き換えることで対応した。サンプルが合わなかったが、入力を受け取りながら処理していたのを変更するときにコピペして入力を2回受け取っていた。隅をスタート地点としていて、隅へはどこからでも行けるという非対称性に何かあるのかと疑っていた。正直ちゃんとは解けていない。

残り1分半でAC。時間が少ない中でやれることをやって結果を出したのは自信になる。