単位が kg であることに注意してください」と注意があるなんて学校の問題よりなんと親切なことか。小学生は 1000 を掛けるのか 1000 で割るのか迷うんですよ。でもそれだけ。■B 問題 Bird Watching。数と大きさの和がわかれば平均が計算できる。■C 問題 Flapping Takahashi。高橋君が存在しうる下限と上限を更新しながら判定をする。判定条件に一瞬迷ったけど、下限≦上限で間違いではなかった。いつものように
all?、any?、none? といった Array のメソッドで入力を受け取りながら同時に判定をすると入力を受け取り切らなくて次のケースが狂うことに注意した。■D 問題 Clouds。計算量の見積もりができなかったのが敗因。2000×2000 の二重ループも、全体で N に収まるループも許されているけど、それらが組み合わさって 2000×N のループになっていることに気づけなかった。気がついたらやりようはある。雲のひとつひとつにハッシュ値を割り当てて重なり合いを xor で計算するならグリッドを走査するのに伴う雲の足し引きは定数時間の計算になる。提出 #71342582。どこかのブログを読んだ限りではもっとオーソドックスな解法があるなんてことない D 問題だった雰囲気があるけども、グリッドではなく雲の座標を伝っていくようにすると間に合うんですか?■E 問題 Distribute Bunnies。終了後に読んだけどわからなかった。似た問題が ARC-A あたりにあったのは知っている。たくさんの二択。UnionFind だと見かけたので UnionFind で解いた。でも UnionFind でいけるということが見抜けるようになったことを意味しない。カードに関する問題だったと思ったから AtCoder Problems で問題名を検索したら ARC111-B「Reversible Cards」がそうだった。400 点問題。4年半前の自分の提出 #21761198。ストレートに UnionFind ではないけど UnionFind っぽい処理をしている? 解説によれば連結成分ごとに DFS などで木かどうか判定すれば良いと書いてある。自分の今日の提出 #71357456 が木の判定をしているのかどうか知らないので2つが同じ問題なのかどうかも確かではない。■D 問題。雲が何枚重なっているかをマス目ごとに数えた後で、雲の厚みが1のマスの2次元累積和を作成し、雲ごとに、領域内に厚み1のマス目がいくつあるかを数えるらしい(「ABC434 振り返り - naoya - Obsidian Publish」)。厚み1のマス目の2次元累積和を用意するステップが完全に想定外だった。グリッドを走査するときに同時に1枚だけの雲がどの雲かを特定しようとしていたから TLE になっていた。その段階では枚数だけを数えておけば良かったのだ。2次元累積和を使って A-B-C+D の式で任意の矩形領域の和を得るのなんて簡単だよ。■■■D 問題。雲にハッシュ値を与えて XOR で重ね合わせをしたと書いた。実は最初は足し算と引き算で雲を重ねたり取り除いたりしていて、それでもサンプルが合っていた。なぜ足し算引き算ではなく XOR なのか。たとえば雲をたくさん重ねた状態のビット長がコントロールできないのが不都合なのかと思った。雲のハッシュ値が 40 ビット長だとして 1000 個の雲を足し算で重ねるとざっと 50 ビットがないと状態が保持できない。では雲の最大数が決まっていてビット長が足りているなら足し算で問題ないのだろうか。むしろ状態が 40 ビットを超えると発行済みの雲のハッシュ値(単独)とのかぶりが考えられなくなるのが嬉しいのではないか、と一瞬思ったけど、それなら最初から 50 ビットのハッシュ値を配っておいて XOR で重ね合わせをするのがビットの効率的活用なのかなというところに落ち着いた次第。■D 問題。単に雲の番号を足し合わせたものを状態として持っておけば良い。ハッシュ値はいらない。重なっている層数をあわせて管理しておき、雲が1枚だけのときにだけ雲の番号の和を参照するのだから、雲1+雲2が雲3と判別不可能だろうと関係ない。……ということが復習を終えた段階でもわからないんだなあ。\1,\2...)とかぶっているのが気に入らない。それに文字列リテラルのエスケープ文字として \ が消費されてしまうことへの配慮がないのも問題。だから必ずブロックを与えてグローバル変数としての $1,$2... を参照するんだけど、忘れていました。■C 問題 Candy Tribulation。19 分かかった。ずっと手が動かなかった。大きい飴の数を最大化するというからまずは個数のすべてを大きい飴に寄せた。そこから総重量を揃えるために小さい飴に置き換えていく。その刻みは必ず Y-X ずつなので、まずは不可能なケースとして Y-X で割った余りがすべて同じでないといけない。最も個数が少なく従って最も軽い人の総重量に揃えられるのかな? 個数が多すぎるとできないけども。提出後も半信半疑でジャッジの進捗を見守っていた。WA が出て全く不思議がなかった。■D 問題 Suddenly, A Tempest。大きな海苔を縦または横にスパッと切ってずらす。それを最大で 14 回。2 の 14 乗でもそれほど大きくない。矩形の切断と移動をシミュレートして許されそう。矩形クラスを用意させられているあたりでもう実装が大変なんだけど、まだ後半パートがある。細かく刻まれた矩形の隣接判定と UnionFind がしたい。しかし組み合わせの総当たりは (1<<14)**2/2 > 1億3000万なので許されないと思った。刻まれた矩形の1枚1枚は重なっている部分がゼロのはずで、隣接のしかたは右辺と左辺もしくは上辺と下辺が1差で隣接している場合に限定できるので、X(Y) 座標で分類して Y(X) 座標でソートすれば総当たりの2乗ではなくソートの NlogN のオーダーで判定ができると思った。ところが自分は分類だけしてソートも尺取りもしなかったのでオーダーが改善しておらず最悪で ((1<<14)/2)**2 ≒ 6700 万の計算量で危なかったけど、45 ms で余裕だった (#70980315)。ギリギリの計算量で落とす意図はなかったみたい。■E 問題 Clamp。クエリ2の式の意味を理解するのに時間を要した。なるほど上と下をクリップするのねと理解した瞬間に問題名の Clamp が目に入って悔しい思いをした。式を読まずに Clamp の一語ですべてが伝われば早いんだけど、そういう順番での理解はありえないんだろうな。でも苦労してたどりついた結論が問題名に書いてあるっていうね。クエリ2に罠があります。l と r の大小関係に制約がありません。そういうときはクランプするのに min と max をとる順番に応じた定数になる。問題自体はいつもの BIT で和と個数を管理するやつ。お前 F 問題の常連ではなかったか。■F 問題 Candy Redistribution。N の制約が 20 以下と小さいけど何が難しいのかがわかっていません! たくさんの飴を持っているなら、自分か相手のすくなくとも一方の個数をちょうどにできる。あまりにも多くの飴が足りないなら、複数の人からかきあつめる必要がある。これはどちらも避けられない操作なので差はつかない。差がつくのは余りと不足がぴったり一致している二人のあいだで受け渡しを行うときで、1回の操作で2人が満足する。だからたぶん難しさというのは、たくさん持っている人がうまく分配することで、たとえば X 回の操作で自分を含む X+1 人が満足するケースをどのように実現するかだと思った。まるで見当がつかないので BFS をして経路を復元する方法を書いている途中で時間切れ。BFS のキーはソートして正規化したいけど並べ替えをしてしまうと操作列の復元が難しくなる(不可能ではなさそう)、というところで足踏みをしている。■順位表を見ると 86 分の遅遅5完でも意外に高くて 585 位だった。E 問題を 2294 人が通しているのに対して D 問題を通しているのが 732 人ととても少ない。自分では ABCDE で一番頭を使った C 問題を 4429 人が通しているのはちょっと信じたくない。もっと自分と同じように苦しんでほしかった。■■■D 問題ってもしかしてカットして倍々に増やしていくことってできない?(日曜の朝最初に頭に浮かんだこと) X カットと Y カットがそれぞれ n 回と m 回なら(n+m=N)、(n+1)*(m+1) が精々? 矩形の数が最大で 64 ? 総当たりでもなんでもやれば通るんだ?(N-M+1).times (0 から N-M までの繰り返し) から [*0..N-M+1] (0 から N-M+1 までを値とする配列) に書き換えたときに off-by-one エラーを仕込んでしまって合わないサンプルに困ってしまった。デバッグプリントで解決。■C 問題 Truck Driver。しばらくわからなくて目の前に沼が広がって見えた。今日はここまでかと。2つの条件に合う範囲をそれぞれ二分探索で求めて考え合わせる。気がつけばこれだけ。■D 問題 Neighbor Distance。お隣さんがわかれば差分更新できる。SortedSet がないから BIT で管理するんだけど X の値が大きいので座圧が必要。今でこそ座圧なんてやるだけ面倒なだけに見えて制約で手軽にいじめられてるなこのひと手間必要でしたかなんて考えてしまうけど、「座標値(-10^9 以上 10^9 以下の整数)でなく座標値の序列(N個以下とM個以下)でグリッドを作るって発想が出てこないんだよなあ」なんて初々しい感想を書いていた時期が自分にもありました。座圧ができれば橙 diff の F 問題「. (Single Dot)」が解けた時期が AtCoder にはありました。WA になった最初の提出まで 24 分かかってるんだけど、実装に取りかかる前に強制うんこ休憩に襲われて急いで E 問題を読んで駆け込んだのだった。なお E 問題のロリハ方針が決まってもまだ出られなかったもよう。WA の原因は番兵が小さすぎたこと。番兵との距離が1しかないならいないはずの番兵との距離を答えに計上して間違える。修正に2分。■E 問題 Shift String。入力が素直に2進数に見えるのでハッシュ値を比較するのもハッシュ値を差分更新するのも自然に行えると思う。マルチテストケースであり問題の見た目から基数に2が選ばれやすいだろうから、ありがちな素数の組に対してハッシュの衝突が狙いやすいと思ったけど、AtCoder で最も有名な2つの素数を使っていても大丈夫だったみたい。■F 問題 Back and Forth Filling。50 分弱残して解けなかった。似た設定でこれより答えやすい問題を見たことがある。自分の左右に最低いくつ最大いくつの数があるかを DP で求めて BIT で区間 add をすれば答えの C 数列が得られると思ったけど、サンプルが合うところまでいかなかった。■コンテスト成績証。737 位、1502 水パフォ。■■■F 問題。昨日はこう書いた。「左右に最低いくつ最大いくつの数があるかを DP で求めて……」。最大でいくつの数が置けるかを管理する必要はないのだった。最低限必ず置かなければいけない数がいくつあるかだけで良かった。前から4変数、後ろから4変数で DP をしていたものを、前から2変数、後ろから2変数に書き換えたらするっと答えが一致した。BIT もいらなかった。変化量の累積和で十分。提出 #70649443 (AC)。■■■@2025-11-11 ABC431 の結果が消えていて、ABC430 の結果は順位が同じまま 1587 パフォに上がっている。何があったんだろ。