ABC302

7完で黄色復帰。体調微妙だったけど大丈夫だった。Fまで解いてG読んで順位表見て思ったより順位悪かったので早解き回で負けるやつかと思ったけどなんとかGが通って。Exも解けなくはなさそう?

A - Attack

なんか切り捨てだと思っててサンプル合わなかった。普通に切り上げやん。ようやく頭が回り始めたか?1分切ったのでいいでしょう。

B - Find snuke

番兵を置いて、8方向は3*3-1で、その方向へ5文字見る。forが5重になってるけどそこまで難しくない。

C - Almost Equal

next_permutationで全探索。隣同士で文字が違うところが全てちょうど1個ならOK。

D - Impartial Gift

片方を固定したとき差がD以下になる範囲が広い可能性がある。そこでしゃくとりを考える。まずソートして大きいのから見る。求めるのは最大値なので、大きいほうから見て発見したらそれが答え(それが(A_i, B_j)としてA_iより小さいものとB_jより大きいものがペアになれるならA_iとB_jより大きいものもペアになれる)。見つからなかったとき、次に進んで、さっき調べた相手はもう調べなくていい(大きいやつはより遠くなってるし、小さいやつはない)。

E - Isolation

Eを読んで時計見たら30分近く経ってて、思ったより時間を使っている。

グラフだけど局所的に見るだけでいいのでunordered_setで管理。次数0の頂点数も管理。サンプル合わなかったけど、削除して頂点vが次数0になったときの処理を書いてなかった。

O(Q)解法あるらしいです。当然、そういうのがありそうならそっちへ行ってるので、わからなかったのは残念。解説見たけど何言ってんのかわからん。

F - Merge Set

最短経路問題なんだけど、すっきりとはわからなかった。最初、集合内の数から辺を出していたが、集合から出すのだ。M個の整数とN個の集合を辺で結ぶ。行きはコスト0、帰りはコスト1。1とMがどちらも多いというケースもあるので、スタートSとゴールTの頂点を追加してSから1を持つ集合へ、Mを持つ集合からTへ、コスト0の辺を張る。多点スタートでもいいけどこっちのが実装楽でしょ。

G - Sort from 1 to 4

これ4だからできるなんてことがあるの。かなり難しそうなので開き直るしかない。ソートしたものと元のを比較して、一致しているものは動かさなくていいと仮定する。1回の操作で一気に2箇所揃うならやっていいと仮定する。そこから巡回とか置換とかわからんものを考えて、「長さKの列をK-1回の操作でrotateする」だけでいいと仮定する。それをKが小さい順にやっていいと仮定する。あとは、ソート済みと比較して何が何になったという16通りをカウントしておいて、貪欲に取っていく。長さ3のやつは3重ループになったけどまあ。長さ4は、残りが4で割り切れると信じて4で割って3を掛ける。割り切れなかったらthrowするコードを提出した。そのせいでACがREになる可能性もないではないが、未証明なので情報が得られたほうがいい。なんかACした。

Ex - Ball Collector

種類数って見て笑っちゃった。まず、1個の問題を解くだけだったときを考える。グラフになる。次数1の頂点は取っていい。連結成分毎に、木であれば1個除きに取れて、そうでなければ全部取れる。永続UnionFindかなあ。Library Checkerを見に行くと、自分はACしてない。永続UnionFindが何なのか知らないけど、こういう用途なら変数の変更履歴を持っておけばいけそう。

(追記)一応思ってた方針でできたけど、バグがしぶとかった。経路圧縮をしないUnionFindでmerge操作を戻せるようにする。閉路を持つかの情報を戻してなかったのと、戻すときに種類数の最大値をプラマイ逆にしてなかったのと、頂点数を-1倍して格納してるのを忘れて-1を使ってたのとで3WA。最後のは全くわからなくて解説や他人のコードを見て(自分では同じ動作だと思ってるけど)そういう書き方をしたら通ったのでそこから少し考えたらわかった。