/ 最近 .rdf 追記 編集 設定 本棚

脳log[20241224]



2024年12月24日 (火) [AtCoder] 精進……失敗! 先週末あった ABC385-F「Visible Buildings」。傾きでソートしながらどんどん更新していくような解法を検討していたのだけど、全然違った。「Fはまず何も考えずに二分探索を書いた」という人がいるが、さっぱりわからない。別の所で「原点から全てのビルを見られなければ、左から順に左隣のビルの陰にならないように高さを上げていきます」と読んで、嘘だぁと思いながら、なんで左隣のビルを見るだけでいいのかを考えていた。こんな感じ。3つのビルがあって原点に近い方から A、B、C とする。AB のてっぺんを繋いだ直線を C まで伸ばしたときの上下を考える。C の上空を通り過ぎるとき、答えに近いのは BC のてっぺんを繋いだ直線なので A を起点として考えるのはおしまい。C の側面に触れるとき、AB を結ぶ直線を保留にしたまま B を起点にした直線について考える。いずれにしろ A と C が関係を持つことはない。本当に? わかりません。実装を始めたらサンプル2と3の違いが難解すぎて手が止まった。共有点を持つとき、見えないんだってね。AC のてっぺんを結ぶ線に B のてっぺんが触れるとき、A から C が見えない。提出 #61050894 (WA×1 / 320 Byte / 1329 ms)。1ケースだけ通らなかった。誤差が大変というのを見かけていたので答えを出力するとき以外全部整数で計算したけど、1ケースだけ合わない。どうしたらいいのかもうわかりません。■A 問題 Equally。全部同値か、どれか1つの2倍が3数の和か。■B 問題 Santa Claus 1。シミュレート。各家1回ずつしか数えないので @ を通過したあと . に書き換えた。■C 問題 Illuminate Buildings。難しかった。実装で2つ間違えてペナルティは4回出した。AC が出たのは終了5分前。2乗が通る制約だからと愚直に書いて、念のために最大ケースでテストしたら TLE になりそうだった。愚直というのは始点を固定して全ての間隔を試すというもの。よく考えると右側にある同じ要素を何度も参照するから2乗では済んでいない。そこで間隔を中心に考えることにした。1つおき、2つおき……の各数列について、同じ要素が最長でどれだけ続くかを数える。間隔が S なら長さが N/S 程度になる S 本の数列を考える。間隔の選び方がおよそ N 通りだからこれで O(N^2) になる。ここでも罠があって Array#values_atEnumerable#chunkInteger#step を組み合わせた解答が予想よりも時間を食っていた。Enumerable#each_cons には大きい数を引数にしたとき尺取りの計算量 O(N) では済まないらしい罠があると思ってるんだけど、ここにもあったのだろうか。手続き的に書き直して最初に提出するまでに 15 分かけた。そこからペナルティを重ねるんだけど、最後まで見つけられなかったバグは N=1 のケース。間隔に注目したせいで単一要素のケースが漏れて nil を出力していた。■D 問題 Santa Claus 2。どうやって計算量に対処するか悩む。たとえば BIT を使えば各行、各列のどこに家を置いて、どこから家を取り除くかは自在に(対数時間で)できる。あるいは行ごと列ごとに移動区間と家の並びのソート列があれば並行してスキャンしていくことができる。どちらも行データと列データに重複して登録される家を二重にカウントしないために同期が必要。これは行に基づいて得た訪問家リストと列に基づいて得た訪問家リストを最後に線形時間でマージして出力すれば良い。ということを考えてから必要なデータ(行ごと列ごとの移動区間)を集めて整理していった。そうすると家を中心にして考えたとき、行データと列データを参照して二分探索をするとその家が訪問されるかどうかがすぐに判断できるなと気がついて、後半の実装がちょっとだけ楽になった。BIT はいらないし、ソート列の並行スキャンもいらないし、答えのマージもいらない。ランタイムエラーでペナルティを1回出したのは N×N のグリッドを想定していたせい。D の提出をするときに C が WA になっているのに気がついて、C のデバッグをしているときに D が RE になって、C のデバッグを優先したけど結果的にデバッグしやすかったのは D だった。いっときは C をあきらめて E 問題を読んだほど。■E 問題 Snowflake Tree。木 DP かなと思って実装を始めたら親方向の情報が欲しくなって全方位木 DP だと気がついて、残り 10 分での実装をあきらめて C のデバッグに戻った。C は終了5分前に、E は終了 10 分後に AC。最も簡単なタイプの全方位木 DP だと思ったけど、もっと簡単に中心を全探索して間に合う計算量だったらしい。頂点数が N でそこから辿る辺の数が両方向で 2×(N-1) だから間に合う。しかし気付けない。■C のミスと D の重さにやられて E を通す時間がなかったのが悔やまれる。F はどれだけ時間があっても無理なのであきらめがつく。