/ 最近 .rdf 追記 設定 本棚

脳log[2025-09-08~]



2025年09月08日 (月) 信号無視をした話。■渋滞している道路を走っていて赤信号で自分が先頭になった。その少し前、そろそろ赤になるな自分は抜けられないなと思っていたときにどこかから救急車の音が聞こえてきて、ミラーに赤色灯が見えたので後ろから来ているとわかった。なので一応左端に寄りつつ、赤信号なので停止線で止まった。ミラーで車体が確認できるくらい、救急車はたぶん4、5台後ろまで近づいてきていた。右車線はあいにくとダンプが3台連なっている。そもそも工事をしていて車線が減っているから渋滞しているという背景がある。ダンプも渋滞も偶然ではない。救急車は右折レーンに入って抜けようとしたようだけど、中央分離帯に寄ってあいだを開けようとしたダンプと動きがかぶって進路を塞がれたかたち。自分の直後の車は今になって左端に寄ろうとしている。しかし前が詰まっていて思うように寄れない。さあどうする? 交差点に車の動きはない。サイレンの音が聞こえているからか歩車分離で歩行者信号のみが青だったからかは確認していないので知らない。普通のドライバーは赤信号を安全に無視するためにどこに注意を向けるべきか知らない。とにかく交差点は空いていた。横断する勇気はないので左端に寄ったまま交差点に進入して、そこで止まって様子を伺おうか一瞬迷ったけど左折して走り去ってしまった。本当は直進する予定だったのだけど。このことで切符を切られることがあっても行いは行いとして仕方がないなと思ってるけども、交通ルールを守るために救急車を無視するのは仕方がないことではないというのが自分の優先順位だった。現場の創意工夫はだいたい東海村臨界バケツ事故で黙らされるイメージがあるけども、自分は自分が納得したルールのみに従い意味がわからないルールは無視ししがちな、軽率な側の人間です。


2025年09月07日 (日) [AtCoder] 精進。昼間にあった AtCoder Beginner Contest 422。■A 問題「Stage Clear」。ステージ数が倍のスーパーマリオブラザーズ。がっぴの処理と同じ。0始まりに文字列置換して8進数にして1足して文字列にして1始まりに置換するのは書いてて嫌になるほど無駄なのでやらない。じゃあなんで書いた? 一瞬やろうとしたから。■B 問題「Looped Rope」。サンプル図を見た感じ、1本のひもが交差するのは許されるけど折り返して接するのは許されない、というのを表した問題名らしい。そんなのは関係なく全マス目について「黒マスではないか、隣接する黒マスが2個か4個であるか」を判定する。最初に書いた条件は「黒マスであって、隣接する黒マスが2個か4個であるか」だったけどサンプル実行前に修正したからセーフ。■C 問題「AtCoder AAC Contest」。A と C の少ない方に合わせて AXC を作ったあとで、余っている A_C を崩して AAC/ACC を何個作るかが問題。単に文字の数を数えて3で割るだけなんだけど、解説によると最初に AXC を作るパートを飛ばしてそういう計算をしていいらしい。飛躍が過ぎてわかりません。■D 問題「Least Unbalanced」。想像通りであるしサンプルの通りでもあるように平らに均します。再帰的に分配する過程が操作の逆再生になっている。■E 問題「Colinear」。時間内には解けなかった。過半数っていうんだからテキトーに選べば当たるのはわかります。でもそういう確率的な操作を書いたことがないし、決定的な方法を探して諦めてしまった。翌日に2か所で乱択の文字を見かけたので、そっち方面に突っ込んで考えてみた。半分が同じ直線に乗っているなら、テキトーに選んだ2点が乗っている確率は4分の1。点の数が最大で 50 万なので、線形時間の処理が 20 回で 1000 万。Ruby の限界は数千万のところにあるので試行回数は数十回が限度か。仮に 20 回試行するとして、外れのペア(が定義する直線)を引き続けるのは (3/4)^{20} で 0.3 % くらいらしい。不安だけどまあ。提出 #69170329 (AC / 455 Byte / 1034 ms)。やっぱり 20 回の試行でもけっこう時間がかかっている。lazy が遅い? それはあると思う。以前から常々思ってるんだけど、find_map メソッド欲しいよね。find が目的だから map{}.find{} だと一度全要素を変換するのに抵抗があるし回りくどくも感じる。かといって find{} で返ってきた値に find の条件ブロックで判定に利用するために施したのと同じ変換をもういちどかけるのも冗長で嫌だし nil 判定はもっと嫌だ。そういうわけで今回は lazy.map{}.find{} になった。でも遅そう。■F 問題「Eat and Ride」。ゴールから BFS をすればゴールまでのステップ数(増加する一方)が揃うので、同一ターンではイコール条件になり前後のターンでは優劣がはっきり決まることになり、ウェイトにゴールまでのステップ数を掛けて消費燃料に換算した値が比較可能になる。毎ステップ各頂点においてゴールまでの消費燃料の最小を更新したもののみが次のステップに進める。ダイクストラ法と違って燃料消費の最小値が更新されることがあるので最悪で2乗のオーダーになるが N≦5000 なので2乗は通る。だからこの問題は各 i をゴールにしたときの最小燃料を問うている。2乗が3乗になった。やるだけの問題にはしないということだ (TLE)。じゃあ唯一のスタート地点である頂点1からたどりますか? そうするとゴールまでのステップ数が不明なために、(ここまでに消費した燃料,消費燃料の増加量=ウェイト) という2つのパラメータが関わってきてダイクストラ法の基準になるコストが一意に定まらない。提出 #69169539 (AC / 1003 Byte / 117 ms)。パラメータを2つ持ってダイクストラ法をしたらけっこうな速さで通った。消費燃料を基準にしつつそれを絶対条件にはしないで消費燃料の増加量の最小を更新するものにも可能性を残している。それはプライオリティキューを使ったダイクストラ法ではない何かですね。通るとは思っていなかった。というのは、キューに入れるときに消費燃料最小か燃料増加量最小のどちらかを更新する可能性があるかを調べてから入れてるんだけど、そのときに基準値を更新していない。基準値を更新するのはキューから取り出したときに限っている。そうしないと答えを間違えると思ったからそうしているのだけど、結果としてキューが取り出してすぐに捨てられるダメな要素で膨れ上がって出し入れに時間がかかり過ぎるおそれがある。これはダイクストラ法を実装するときの罠であり勘所だから、それをしないのでは TLE になると思ったがならなかった。想定解法はなんだろう。Ruby での F 問題へのすべての提出 を見たら想定解法は通らないっぽい? 最近の制約はまじでクソだと思う。3乗が通らない N=500 と2乗が通らない N=5000 と NlogN が通らない 5×10^5 のことだよ。俺は Ruby を書くために AtCoder をやっているので、Ruby お断りの AtCoder につまらない思いをさせられたらできることがない。■オンタイムで参加していないので E, F が解けなくても平穏だ。Rated だったら入緑していたね。■■■F 問題。想定解法がようやく理解できた気がしたので書いてみた。提出 #69198045 (TLE×26/AC×25)。かなり気を使って普通でない書き方をしたけど TLE が 26 個。他の人のを見ると、提出 #69146527 (TLE×29 / tinsep19 さん)、提出 #69145173 (TLE×23 / fumta さん)。Ruby では全然見込みがなさそう。一番 TLE が少ない fumta さんの提出はちょっとおもしろくて、辺を頂点ごとにまとめずにそのまま DP の遷移に利用している。そうするとループの回数がちょうど半分になる。ループ1回の処理は往路、復路で2倍になっているので全体の処理量は変わらないけど、ループを回す負担は半分になる。Python で一番速い提出を見てみたらたこつぼのページでたびたびお世話になっている ikatakos さんの提出 #69123541 がコンテスト中に提出されていて、解法が自分のなんちゃってダイクストラ法と同じに見える。Python の層の厚さはすさまじい。Ruby でからくも TLE を免れた遅延セグメント木の問題でも、2人か3人の人がそれぞれの手法を突き詰めてどんどんとタイムの「桁を」縮めていく様子が提出一覧からうかがえたりもした。何をやって縮めてるのか全然わからないんですよ。見た目が違うからたぶん採用している手法は異なってるんですよ。


2025年09月06日 (土) [AtCoder] 今日は AtCoder Regular Contest 205 (Div. 2) があった。div.2 に Rated でいつまで参加できるのか先行きが怪しいこの頃ですが、まだ Rated です。■A 問題「2x2 Erasing」。与えられた矩形の中の白4マス四角の数を素早く数えたい。右、下、右下がすべて白マスである白マスを1と数える2次元累積和で数えられそう。提出 #69078973 (AC / 640 Byte)。枠で区切られた部分の調整で無駄なことをしてる気がする。SR と SC は不要で、i1,j1 をそれぞれ -1 するだけでよかったのではないか。■B 問題「Triangle Toggle」。解けない B 問題に残り時間をすべて奪われました。時間さえかければ解けた C 問題、D 問題に着手したかった。■C 問題「No Collision Moves」。制限時間が3秒と長めなんだけど、何が難しいのかわからなくてなんの罠を見落としているのかと疑心暗鬼だった。S に基づいた人の並びと T に基づいた人の並びが異なっていれば、必ずどこかで移動の交差が起きるので答えは No。じゃあ Yes のときは端から整列させていけばいいんちゃうの? その通りなんだけど、端の人を移動させる前にその先の人を移動させる玉突きを処理する必要があった。サンプルがその例。でもそれだけだった。提出 #69089475 (AC / 486 Byte / 550 ms)。■D 問題「Non-Ancestor Matching」。全方位ではない木 DP。どうしても残ってしまう白色頂点の数を子を頂点とする部分木ごとに数えたら、それをうまくマージして白色頂点を最小化する。提出 #69091151 (AC / 670 Byte / 1192 ms)。うまくない場合というのは、1つの子の下にペアを作れない白色が大量にぶら下がっていて、他のすべての子の下にある白色の頂点と黒色のペアを解消して用意した頂点を使い尽くしても余ってしまう場合のこと。■5×10^5 の制約はまじで良くないよ。ARC はもちろん ABC でも見たくないよ。■日曜の昼は毎週ほぼ確実に時間がとれないので明日の ABC はお休み。


2025年08月31日 (日) [AtCoder] 精進。昨日あった ABC421-F「Erase between X and Y」。クエリを先読みすれば前に詰めたり後ろにずらしたりしないでいいように適切な空間を空けて要素を挿入・削除できる気がした。1本の配列をどう切り分けて必要な情報をレイアウトしようか考えていたけど、結局必要なのは次の要素が何かという単リンクリストだけだった。クエリ2で問題になるのが x と y のどちらが前にあるのかという情報だけど、クエリ1のみを先読みして作った木構造を深さ優先でたどって通し番号を割り振って順序にできる……というのは各要素を決まった場所に並べて動かさないでいいという最初のアイデアと同じことを言っている。発想の順番としては木構造の方が先で、各ノードが要求する最大サイズが事前に先読みできるから、1本の配列上に木をレイアウトしたとしてそのあとノードを挿入したときに全体の再レイアウトが避けられるなと考えて、それからクエリ2によってノードが削除されたときに木構造を維持するために必要な更新をシミュレートしていたら(前から削除していくと子を残して親が先に消えるので子のつなぎ替えが必要)、木のような立体的な構造である必要はないな、ただの直線(リスト)だなと気がついて実装がとても簡単になった。■提出 #68964752 (TLE×2/AC×34)。なんでなんですか。一番に考えたのが 25 行目が無限ループになっているためにメモリを 1.5 GB ちかく消費し時間を 2.3 秒ほど費やしたところで実行を打ち切られているのではないかということ。しかし x と y の前後関係を見誤ってリストにループを作ってしまった場合、そのクエリの最中にリストを末端までたどった末に nil を演算に使用してランタイムエラーを出すはずなのだ。RE を出さずに無限ループをお膳立てする方法がわからなかった。それに他の AC になったケースをよく見ると、1.6 秒で約 1 GB のメモリを消費するなど、実行時間に比例してかなりのメモリを消費しているが異常ではないらしい。どこで多大なメモリを消費しているのかよくわかりませんが。■提出 #68969535 (AC / 924 ms / 352228 KiB)。2か所を while 文に書き直したらメモリ使用量が劇的に減って、したがってメモリ操作にかかる時間も減った結果 TLE が解消した。1つは .reverse_each.injectwhile .pop に、もう1つは .eachwhile .shift に。たぶん2つ目は時間に効くけどメモリに効くと意識したことはない。じゃあ Enumerator を返す使い方の Array#reverse_each に罠がありますか? あと、ちょっとだけ余分な時間がかかり、TLE と AC を分けることもあると知られている多重代入が複数の代入に分解されているのも確認できるけど、これは最初にこれだけをやってみて効果がなかったのでカウントしていない>提出 #68965976 (TLE×2)。■提出 #68970098 (MLE×2)。これは最初の TLE 提出の .reverse_each.inject.reverse.inject に書き換えただけのもの。reverse_each が罠なのかどうかを確かめたくて。結果は全体的に実行時間もメモリ使用量も何割か改善しているけど MLE になってしまった。そういえばメモリ制限は 1024 MiB だった。.reverse_each を .reverse に書き換えることで TLE は解消したけど MLE がそのままだったので AC にならなかった。ただの数値配列なのにメモリ制限が厳しい。使用済みのデータを随時破壊的にシュリンクしていって GC させないといけませんか。■Ruby の提出を時刻の早いものから見ていってる。提出 #68945143 (konayuki さん)。BIT を使って何をするのかわかりません。提出 #68947172 (hmmnrst さん)。なんとクエリ先読みが必要ない。クエリ2では x からと y からの両方を同時にたどってどちらが他方にたどり着くかを確かめている。自分の TLE/MLE の原因は x,y の順序を決めるための先読み部分の深さ優先探索にあったから、両方をたどってみるのが労なく AC できて正解だった。準備せずやってみるだけ! 同時にたどるのがたぶん重要なポイントで、順番にたどってみようとするとリストの全体をたどってしまうことを覚悟しないといけなくて、それは Q^2 のオーダーで TLE になる。他の提出は全部 BIT を使わないリスト解法かな。リストを二重リンクリストにして x から両方向にたどってるっぽいヴァリエイションもあった。■直近4回くらい緑パフォ安定で結果は出ないしコンテスト中は全然おもしろくないんだけど、だからふりかえりも書かないんだけど、精進日記や精進未満日記が3つ続くところを見ると問題自体に問題はなくて解くのを楽しめているような気がするんだよね(そのように見える判断できるというだけで楽しいと思ってはいない)。でも圧倒的に時間が足りていなくて、この F 問題は問題を読んだのが今日だった。この難易度の問題を後日提出の宿題にしてしまってはいけないんだよ。でも D 問題も F 問題も1時間では AC にならないし、E 問題は解けてもいない。メモ化再帰で書こうとして書けていない。キープする面の組み合わせをを選んでその場合の数を数えたいけどできない。■■■D 問題についても書こ。時間内に1時間かけたものは半分 AC で半分 WA だった (#68940840)。おしまい。終了後に最初の実装を捨ててもう一度書いた。実装の機微がすでに明らかなので、位置関係を分類して (左,右,同じ)×(上,下,同じ) の9通りを実装するのはやめて、現在の両者の距離と1秒後の両者の距離がゼロかどうかと変化量を見て判断することにした。分類して予測するより単位時間の経過を見る! 提出 #68953965 (AC)。D 関数がある時点の両者の距離で、X 関数がある時間の両者の重なり回数。実装し直しただけで AC になるのだから最初の提出の WA は実装ミスなんだろう。変化量が負になりうることを全く想定していなかったのでたぶんそのあたり。問題を一読したときから考える要素は1秒分もなかったけど、重なっている回数をうまく数えることができなかった。簡単な実装方針が見極められるのも実力のうち。ありませんでした。■■■リストを同時にたどるというアイデアが自分の頭から出てくる見込みがなさすぎて悔しいので、これが悔し紛れになるのかは知らないけど本で得ていた知識を1つ書こう。リストがループを持っているとき、その形は輪っかか輪っかにしっぽがついた「の」の字になるけど、輪っかがあるかどうか、あるとしたらそのサイズは何かを知るために2つのポインタでリストを同時にたどる方法がある(らしい)。アルゴリズムのキモはポインタの進む速さが異なっていることで、遅い方は1つずつ速い方は2つずつ進めていって、いつ2つが衝突するかを観察することから始めて、しっぽとサイクルの接続点を2つ(3つ)のポインタ以外の記憶領域を必要とせずに求めてしまう。そのときにはサイクルの長さもしっぽの長さも(数えたいなら)数え終わっている。というようなことが『プログラミング原論』の 2.3 衝突点 (pp.23-28) に書いてある。本の最初の最初のただの前置きみたいな部分なのに難しいね。


2025年08月27日 (水) 至極もっともなことがグラフを使ってわかりやすく整理されているこちらの記事。「「読みやすいコード」を依存グラフで考える」■内容はいいんです。読んで読みやすいコードのあれこれの裏付けを知ってそうだったのかと納得すれば良い。最後のまとめのうちのひとつ「宣言的でないコードは分離して端に掃き出すとよい」を自然と後押ししてくれるのが関数型言語のモナドだと思ってるけどよく知らない。■波線がないところに「波線」と書かれていたので、これは破線(ハセン)の変換ミスだなと思って自分でも変換してみたところ、破線と波線の読みがどちらもハセンだと知って驚いたのが今日の日記の中身。ナミセンには項目も立っていなかった。区別できないじゃん。


2025年08月25日 (月) [AtCoder] 日曜にあった ABC420-G「sqrt(n²+n+X)」。精進じゃないよ、解けないもんね。順位表を見たら F よりずっと多い 1000 人以上に解かれていたみたいだけど、それを知って取り組んでいたとしても解けなかったので結果は変わらなかった。今年の東大の何かと同じ式変形だとか、ただの受験数学とかのコメントが見えたけど、ただの……ねえ。■最初に考えたのは、なんで答えの数が有限なのかなということ。n がとんでもなく大きかったり小さかったりすると、n(n+1) が支配的になって X が無視できるから(都合のいい言葉)、n(n+1) は平方数ではなく、そのルートは整数ではないということだと思った。そうすると X が n(n+1) と n^2 の差分を相殺するときに答えが見つかるなということがわかる (n=-X は常に答えのひとつ)。n(n+1) と (n-1)^2 との差分を相殺するとき、(n-2)^2、(n-3)^2 との差分を相殺するときもそうかもしれない。いったいどこまで考えればいいのか。サンプルにあったように X 自身が平方数のときは n=0 と n=-1 も答えになる。こんな感じで思いつきを列挙していってどうして全部列挙できたと言えるのか。なんもわからん。


2025年08月23日 (土) 毎週 21 時の AtCoder を待機しているときに Windows の時計を「今すぐ同期」するのだけど、これが決まって 15 秒程度遅れていたかのような調整がなされる。1週間で 15 秒遅れるの? こういうのを精度はあるけど正確ではないというのだろうか。一度にいっぱい変わったのでなんともいえないけど、ミニ PC に替えたからというのを考えられる理由のひとつから外してはいない。あとゲーム実況動画の音声が違うように聞こえるというのもある。これもいっぱい変わりすぎていて、スピーカーは同じだけど音声の経路が途中まで HDMI になりモニタを経由していたりという変化がある。そもそも録音機材であるマイクを変えましたというので聞こえ方が変わってくるものでもある(とはいえ以前見た動画の音声が違うように聞こえているのは機材の違いではない)。マザーボードが違えば違ってくることってあるのかなあと考えたりなかったり。楽譜データを演奏するのに音源が~とかいうのとは関係ない話なので変わらないとは思うんだけど。あとは変な音響効果がオンだった、オンになった、とか。


2025年08月17日 (日) [AtCoder] 精進。昨日あった ABC419-E「Subarray Sum Divisibility」。コンテスト中の提出は TLE だった (#68558616)。制約が N,M,L≦500 で3乗だからしかたないな、C++ で書き直そうかな、やりたくないな、他に方法がないかな、やりたくないなと思いながらちまちま翻訳していたのだけど、デバッグの時間が数分足りなかった。ところがね、どこかの参加記を読んでいたら3乗ではないらしい。オーダーに L が関わってこない。自分の TLE 提出の 7 から 12 行目が諸悪の根源だった。点の遷移を線に展開することで結果としてオーダーが悪化していた。■提出 #68602921 (AC / 552 Byte / 56 ms)。3段構成。最初に L ずつ離れた要素の mod M を揃えるための最小操作数を求め、その結果長さ L の連続部分列の mod M がいくつになるかを求め、ついでに mod 調整用の遷移リストのリスト(L グループに分かれた N-L 個の遷移)を用意した。次にそれら3つを使って DP をして、長さ L の連続部分列の mod M を 0 から M-1 にするのに必要な最小操作数を記録した。最後に M 個から答えを選んだ。たぶんだけど mod M が 0 のところにだけ答えがあるのではなくて、1 から M-1 のところにも答えがあると思う。これらを 0 にする遷移は簡単で、mod を1増やすのに N/L のコストがかかる。これはつまり同時に操作しなければいけない L ずつ離れた要素のグループのサイズというのが1種類(N が L の倍数のとき)か2種類(N が L で割り切れないとき)あるのだけど、その唯一もしくは小さい方のサイズがコスト。2番目のステップによってグループ内のすべての要素がグループ内のどれかの要素と同じ mod M へ揃えられているので、最後のステップではグループ全体の mod を同時に動かす。TLE になった原因はステップ2とステップ3を分けなかったことにあって、グループの mod をグループ内のどれかの要素に揃えるのではなく、M 個のどの値に揃えるケースについても考えていた。これだとステップ3はいらないけどオーダーが悪い。N と LM の違い。他の人の提出を見て気がついたけど、ステップ1とステップ2を分ける意味はなかった。2と3を分けないせいで TLE になって、今度は分けすぎていた。■制約でお手軽に殺されたのかと思っていたら、しっかり骨太な問題だった。こういう問題はじっくり日をまたいで考える必要があります。解けない。言語によっては 500 の3乗でも通ってたよってのは関係ない。Ruby できっちり 72 ms で通している人がいた (#68564921。HalMat さん。いつも難読だなあ文字を費やしても読みやすくはならないんだなあと思いながら拝見しています)。ここまでできてしかるべきだった。


2025年08月15日 (金) 打ち水っていうのは昼の暑いさなかに撒いても湿度を上げて不快さを増すだけで良くないのだと。気温が下がり始めた夕方に撒くことで下降を後押しするのだということをネットで読んだ。以前に自分が打ち水をする様子を想像したときに、自分だったらバケツの水をぶちまけて終わりにしそうだなと思って、それがいいのか悪いのか知りたいと思って検索をした結果。ということを思い出していてふと思いました。夕方に気温が下がっていますか? 夜気の涼しさを感じるのは日付が変わって数時間後のことではありませんか。あつ。


2025年08月14日 (木) 行李(こうり)」■知っているようで知らない言葉だった。広辞苑には意味が4つ載っていて、順に「(1)(行きおさめる意)使者。」「(2)旅行の荷物。旅行の支度。転じて、旅。」「(3)旅行用の荷物入れ。竹または柳で編み、つづらのようにつくったもの。衣類入れにも使う。「柳―」 」「(4)軍隊の戦闘または宿営に必要な弾薬・糧秣(りょうまつ)・器具などを運ぶ部隊」■人だったり旅だったり荷物入れだったり軍の部隊だったり、いったいなんなのだ。旅にまつわる何かではあるのか。それにしても対象が十把一絡げ(じっぱひとからげ)過ぎない? 同じく ATOK で引いた明鏡国語辞典には「竹・柳などで編んだ箱形の物入れ。かつては旅行用の荷物入れに用いたが、いまでは衣類などの保存に使う。「柳─」 」とだけあり、これは広辞苑の3番目の意味だが、自分が知っていたのはこれ。実物は見たことがないし見てもそれとはわからないけど、柳行李(やなぎごうり)という言葉だけは見たことがある。


2025年08月02日 (土) [AtCoder] 今日は AtCoder Beginner Contest 417 があった。D 問題が難しすぎる。30 分以上かけて AC に至れなかったので捨てて E、F に行った。得点に至らない時間消費は得られたはずのパフォーマンスを下げるムーブ。時間をかけていいのは解けるか解けないかの最後の1問だけ。■A 問題 A Substring。出力する文字数が問題文に書かれてるの親切。最初の文字のインデックスが 0 始まりで A であることを確認したら、書いてある通りに。■B 問題 Search and Delete。どうやっても通る制約ではあるけども、ソートして NlogN で。A 数列が広義単調増加なのに B 数列がソートされていないなんて思いませんでした(サンプルが合わなくてデバッグした)。Hash を使うと定数倍は重いけどオーダーはさらに良くなるのかな。■C 問題 Distance Indicators。苦手な部類だけど式が直で問題文に書いてあるのでさすがに式で考える。必要なものをカウントしながら数え上げるのだけど、ポイントは i と A_i、j と A_j を等式の左右に分けること。値と添字を足し引きしたものは位置(添字)から独立した指標になる。■E 問題 A Path in A Dictionary。小さい頂点番号を優先して深さ優先探索でパスを見つける。再帰関数で実装していて TLE を出している人は訪問済みフラグをクリアしているのが原因ではないかと思う。過去にゴールに至れなかった頂点にあとから再訪して、良い結果が出ることがあるのかどうか。スタックで実装すると再帰関数では出さない TLE を出すことがあって、これは隣接頂点リストを何度も先頭からスキャンさせられることで出る。スタックに保存する状態を (頂点番号, 隣接頂点リストの位置) のペアにする。自分はスタックで実装して隣接頂点リストを破壊的に消費した。スタックがそのまま答えの頂点列になるので自然そうなった。■F 問題 Random Gathering20241218 で実装した遅延セグメント木をコピペするだけ。3秒制限のところ 2984 ms で通ったのはめでたいようで気持ちは虚無だ。ABC だから基礎知識の確認という意味はあるかもしれない。でもなあ。■D 問題 Takahashi's Expectation。まず問題設定が難しい。高いテンションはさらに高く、低いテンションはさらに低くなるようなイメージで長らくいたけど、実は逆で、高いテンションは下がりやすく低いテンションは上がりやすい。その交差部分をうまくマージしたいが、愚直 TLE 解を終了3分前に提出するのが精一杯だった。全部で1時間近く費やしてこれ。クエリの大きさははったりだなと思ったけど、クエリの数もそうなんかな。■■■遅延セグメント木の扱いについてコメントを書いた。提出 #68173358。自分はこういうのはパクリパクられで良いと思ったものをどんどん取り入れて手を入れていけばいいと思ってるんだけど、思ってるだけではどうにもならないわけで。ac-library-rb のような形が一番いいのだろうと思う。AtCoder では前回の言語アップデートからだったか require するだけで利用できるようになっている。遅延セグメント木に関しては制限時間のせいで貼るだけやるだけとはいかないらしいのが、AtCoder における Ruby の立場を弱くしている。■セグメント木に関して prod という用語が自分はわからないんだよね(調べない)。id という名前も同じようにわからなかったんだけど、昨日 ac-library-rb/lib/lazy_segtree.rb での使われ方を読んでいてわかった気がする。IX = XI = X であるような行列 I を単位行列と呼ぶはずだけど、I がたぶん Identity の頭文字。英語では習わなかったけども。ということは、id の名前で返すべきは何の作用ももたらさない操作なのかなと。e と id の区別が難しかったんだよね。最大値を求める操作に対しての負の無限大、最小値を求める操作に対しての正の無限大、数を数える操作に対してのゼロみたいな、初期値としての e とは別に用意される id という「値」はなんだろう、というのが疑問だった。物理的な形式はともかくとして概念としての id は操作ですよね? ということを納得すると、自分の実装で Op#nop? の名前を与えられている機能は Op#id? が相応しかったんじゃないかなあと思ったり。■コンテスト中の提出 #68152111 (AC / 1796 Byte / 2984 ms) と冒頭にコメントを付加しただけの提出 #68173358 (AC / 2433 Byte / 2596 ms)。ジャッジサーバーが使い回しではなく新規立ち上げだから1ケース目だけ 100 ms 余計にかかってる、みたいな話ではなく、全体的に1割程度の時間差がついている。再提出で 100 ms も差がつくことはないだろうと思っていたから意外に大きな差に驚いている。こんなんではコンテスト中に TLE だったものが終了後の再提出では AC になった、みたいなことが十分に起こりうる。特に遅延セグメント木と3乗の DP が解法となる問題ではシビアな定数倍低減が AC と TLE を分けるのでしゃれにならないよ。■■■@2025-08-07 精進。D 問題。提出 #68259724 (AC / 471 Byte / 1172 ms)。コメントに書いたけど「ひとたびテンションが 0..1000 の範囲に入ったら抜け出せない」ことが見抜けるかどうか。見抜けたらその範囲で DP をする。自分は見抜けなかったので 0..500 の範囲+それ以上という括りでクエリ全体を一括シミュレートしてサンプルしか通らなかった (TLE×27/AC×3)。さらにもうひとつどこ以降の DP 結果を参照するかを決めるのに二分探索をする必要もあったらしい。すべてのネタバレ後に実装をした。実装だけなら D 問題だったけど考察ポイントが2つもあると問題を総合的に理解していないと解けない。断片的な手がかりからあれかなこれかなというアプローチでは解けない。「クエリの大きさははったりだなと思ったけど、クエリの数もそうなんかな」と先に書いていた。大きすぎるクエリには二分探索で対応する。(シミュレートするには)多すぎるクエリは 1001 種類の入力にだけ対応した DP で予め答えを出しておく。それでいいそれでできるという判断に必要だったのが「ひとたびテンションが 0..1000 の範囲に入ったら抜け出せない」という洞察。ありませんでした。


2025年08月01日 (金) 部屋全体を冷やすことを考えてセッティングしている人間(俺じゃないよ)に対して「他人のことを考えていない(私に扇風機を独占させてくれない)」はそうとうな言い草だなと思いました。■食卓を確保しようとするのに抵抗して「どこが誰の場所ということはない」と言ったこともある。誰のでもない場所のことごとくをあなたが散らかしている現状をなんとするのか。■こういう人が自分自身のことを他人に気配りができる人間だと自認していたとして、逆説的ではあっても不思議はない。自己を批判する他人の目がないのだから、自分はいつでも完全な人間であり、自分からずれた視点と価値観を持ち判断して行動する他人は不完全で不満の対象でしかない。「自分がしっかり目配りしてやらないと」


2025年07月31日 (木) 咎人(科人)。かなりの人や創作物でトガビトと読まれがちな印象があるけど(自分がそう読んでいたから。“神を斬獲せし者”)、広辞苑と明鏡国語辞典ではトガニンで項目が立っていてトガビトやトガヒトにはない。罪人の読み方がザイニンかツミビトであり、罪科の読みがザイカかツミトガだから、原則に従うならトガビトになるはずだけど、なんでなんだろ。