ABC225

5完。黄パフォと橙パフォの境界。早解きでこの順位になってしまった。FGでしっかり考えることができて、コンテスト全体としていい動きだった。最近ABCであまり集中できていなかったが、前回の反省を生かし(今回が高難度セットだったというのもあるが)コンテスト中の時間を有効に使えた。

A - Distinct Strings

想定解が何であるか全然わからない。next_permutationを使い、1分29秒。最初に考えたのは、現れる文字の種類数をカウントする方法(解説見たらこれだった)。1種類なら1通り、2種類なら3通り、そうでなければ6通り。カウントと場合分けの両方を実装するのは時間がかかりすぎると判断して別の方法を考えた。

B - Star or Not

いやBでこれは難しくないか。実装もけっこう悩んだ。辺に何回現れたかを数えてN-1のものがあればスターとした(木なのでこのとき他の頂点は1回ずつしか現れない)。2乗になるから全探索はできないとかグラフ構築するかどうかとか考えてたけど、今になってみると何を目指していたかわからんな。そっか、DFSして深さが2なら子の一つの隣の頂点数を数えればいいのか。

C - Calendar Validator

要するに1から順に左上から横書きで埋めていったもの。扱いにくいので1を引いておく。横幅は狭いのではみ出さないように注意。Bの左上隅を見れば「切り出したとすればここしかない」という位置がわかるので、あとは全部確認する。

(追記)問題名を見ていなかった。カレンダーから切り出すという設定がわかっていれば初動が少し楽だったはず。まあ問題名は滅多に役立たないから「見ることを心がける」はマイナスに働きそう。

D - Play Train

難しそう。おしっこしに行くと、考えが整理されて双方向リストを思いついた(ぷよぷよ最強リーグが始まる直前にトイレはちゃんと行ったけど、1時間経っているのと問題が難しいことでまた行きたくなった)。片方向リストでいいか?いや、先頭を見つける必要があるので双方向が必要だ。最初はなんか電車xの情報がどこにあるかのポインタみたいのを持つ必要がある気がしていたが、単に自分の前後の電車番号を持つだけだ(つながってなければ-1)。あとは愚直にやるだけ。

E - フ/7

こういう問題のときは英語問題文も(単なる興味で)見る。英語だと「フ」ではなく「7」だった。こういうの、日本語も7でいいと思うがなあ。問題文をよく見ると、実際にはLみたいな形で決まったサイズの図形。かなり大変そうに見えるが、第一象限だけなので、N個の区間から重ならないようにいくつ選べるかというだけの問題だった。しかしこれがかなり難しそうに見える。落ち着いて考えると、端から考えると幸せになりそうないつものだったかもしれない。最も左の区間を使うか使わないか、というのを考えていると、右端が最も左の区間に注目するいつものな気がしてくる。右端が最も左の区間は使って損しない。使っても左端がそこより右のものには影響しないし、そうでないものを代わりに使っても損しかない(右端がより左にならなければ右側について得しないし、左側についても得すると仮定したら右端の位置がもっと左のものがあることになってしまい矛盾)。よって、右端でソートして(左端はどうでもいい)使えるものを貪欲に使っていけばよい。角度の比較は外積で適当に(整数でできる)。「原点から見て点p0より点p1のが右にある」を判定できるようにして、あとは実装。

F - String Cards

FGを交互に考えた。最終的にはFをやっていた。提出者のうちACした人の割合が1桁%という異常な問題ではあったが、提出したのはよかった。提出後、微修正ばかりしてしまい落ち着いて考えられなくなることを経験できた。

異常に簡単そうな見た目。しかし、考えるほどわけがわからなくなる。次にある文字列を使うことと比較する相手が、他の文字列とは限らず、文字列をいくつかつなげたもの同士を比較しないといけない。それがどんどん組合せ爆発して頭がパンクする。ただまあ辞書順なので貪欲にやればいいだけではある。最初に使う文字列がどれかさえわかればいい(同じことを繰り返すだけ)。まずソートして、先頭の文字が最小のものから選ぶ。問題はそれが3個以上ある場合。次も同じような文字列を選ぶわけで、最小(最短)を基準にそれを繰り返したものと比較すればよさそう。愚直にやっても50文字までなら計算量も大丈夫だろう。提出してWA。最後の1回はあとのこと考えないで単に最小を選ぶ、残り回数だけ繰り返す、100文字くらいまで見る、などの修正をして少しWAの数が変動。感覚的に行けなくはない方針に思えたが、まあ時間がなくて何も考えてないので仕方ない。時間はかなり(1時間以上)あったんだけど、そうなってしまった。問題が難しい。

(追記)解説を読み、見たことのある比較方法だ(どこで見たか思い出せない)。ちゃんと順序になっていることの説明が書いてあってありがたい。順番になってなかったらどこかの隣接する2つが逆になってるからそこをswapしていけば状況が改善される。そしてDPだが、辞書順なのに後ろからやるのがヤバすぎ。確かに前からやると長さが揃わず、長さまでDPに含めるとさすがに間に合わなそう。後ろからやれば、辞書順で早いものを付ければ辞書順で早くなる。なぜそうなるのかわからん。正しいから正しいとしか。なぜこの宇宙は、いや、数学はこのようになっているのか。

G - X

線が影響し合う範囲を見ると、市松模様にして2つに分けることができる。それぞれを45度回転させて縦横に線を引く。フローみを感じる。だが、片方でも5000マスある。しばらく考えてマスを白黒2色に塗り周囲を白で囲み隣と違っていたらペナルティというのを思いつく。しかしそんな最小カットが間に合う制約ではない。

(追記)なんかTwitterを見てて「Dinicは速い」みたいな雰囲気だったから、とりあえず自分で書いて、サンプルが通ってから解説を見て、提出した。まじでクソ速い。最小カットが間に合う(ただし証明はされていない)制約だった。SからTへ流すとして、Sからキャパ0の辺しか出なくて無理なのではと思っていたが、ちゃんと書くとちゃんと流れてきてサンプルが通るといういつもの流れだった(フローだけに)。辺の張り方は最初からイメージできていたが、実装はけっこう苦戦した(それをイメージできていたと言えるかは諸説あるが)。自分は線の両端にコストをかけたが、他の提出がだいぶ速いので見てみると片方だけでよかった(言われてみればそう(一旦線が切れなければ再び線が始まることはないので))。