ARC179

3完。さすがに得意セット。Dが、だいぶ遠いものの全くわからないわけじゃなかったので、いい順位ではあるが悔しさが残る。あと、やはりCまで通してパフォ2200程度が確保できてしまうと、次の1問を通したいという焦燥感がなくなる。さぼりたくなってしまう。普通に考えて失敗を減らすより大成功を少しでも増やしたいと思いそうなのに、自分の感情は逆なんだよな。

A - Partition

条件については、全ての隣接要素のペアについて調べればいい。K=0のケースが気になるが、未満と以上で分けているので、0.5を引いてしまえばK=-0.5と負の数の仲間入りで、正負の場合分けだけで済む。Kが正の場合は、初期状態(0)でK未満の位置にいるので、小さい順に並べれば最初損せず下がってあとから上がっていける。Kが負のときは、最初からK以上になってしまっているので、大きい順に並べて絶対にKを下回らないようにする。絶対には無理だけど。証明はできなかったけどわりと明らかに思えたので実装。ソートして隣同士を確認するだけ。

B - Between B and B

よくわからんけど、Mが小さいので2^M個の状態でDPできるのでは?そう決め打って考えると、次に置ける数の集合を状態とするDPができそうだ。実装しながら詰めていく。次に置ける数であって、間に置かれた数ではない。各状態から置ける数を置いて配っていく。置いたら、その数は置けなくなり、次にその数を置いたことで置けるようになった数を入れる(何を置いたら何が置けるようになるかをビットで前計算しておく)。O(N*2^M)でいけると思っていたが、更にM倍になってしまった。10^8程度だから間に合うけど。なんかもう解けている。

C - Beware of Overflow

回数を見ると、とりあえずのソートはできる。一番大きいものと一番小さいものを足せば±Rの範囲から出ることはないだろう。ちゃんと考えると、その2要素の符号が同じなら全部同じ符号でそれらを全部足してさえ範囲に収まるんだから2要素ならなおさら大丈夫。符号が違う場合は明らかに大丈夫(絶対値の最大値が小さくなる)。じゃあ同じように2番目同士をくっつけるのは?これが通れば要素数が毎回半分になって毎回ソートしても間に合いそうだと思ったが、これにはR=9で-9, 5, 5, 8という反例がある(5+5はRより大きい)。とりあえず、ソート部分のコードを持ってこようとして、自分のブログを"stable_sort"で検索してARCを見つける。ARC154Dだ。その提出を見ると、挿入ソートがある。これで解けた。黒板に書いてある整数について、何番目に書き込まれたかのインデックスをその大小でソートされた状態で持つ(この間接ソートっぽさが難しさだと思った)。そもそもstd::stable_sortは全てマージソートというわけではないので、比較回数だけなら(二分探索する)挿入ソートが有利。最初のソートも1要素ずつ挿入していく。足し算をしてもらったら、やはり挿入する。dequeを使い、両端を削除して挿入を繰り返すだけ。自作のinsertion_sortを、末尾の要素のみ挿入ソートするように変更し、挿入処理を関数にすればきれいに書けるし思考も要らない。内部0-indexedで、ジャッジとのやり取りは1-indexedなことにだけ注意。サンプルを手で試してから提出してAC。

D - Portable Gate

駒が自機。ゲートは好きな場所に戻れるが、一度戻ったらそれより過去へは戻れない感じ?考えていくと全方位木DPになる。自分のライブラリを持ってくると、かなりよく整備されていて希望が持てる。しかし、かなりややこしい。答え、最終的に根に戻る場合、ゲートを使わない場合、根に戻るのと戻らなくていいのの差の最大、コストの和、ゲートを使わない場合の和、といった変数を持つ(どんどん増えていった)。提出してWAで、ゲートを使わない場合の最小コストが間違っていたっぽい。しかしそこを直してそれで正しいという自信は全くない。全方位木DPのライブラリがあれば簡単そうに見えて、細部が全然見えない。これはつらい。