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

脳log[20231223]



2023年12月23日 (土) [AtCoder] 今日はユニークビジョンプログラミングコンテスト2023 クリスマス (AtCoder Beginner Contest 334) があった。自分のすべての提出。配点からわかる通り、B 問題と C 問題にちょっと癖があった。それぞれ 10 分と 17 分かけた。そのかわりではないだろうけど、D 問題と E 問題は手を動かすだけの問題だった。そして F 問題。40 分残していて、急がば回れということで(「Rational でサンプル1を試したらね、1/3 になるべきところが 4/3 になってることがわかってね、(略) mod の数字を見てもデバッグはできない。」)、まずは愚直解を作るところから始めた。そして TLE が出た時点で残り 10 分弱。12-14 行目がまずいのはわかっていて、どうすれば改善できるかもわかる。しかしデバッグが完了したときには終了後 14 分経っていた。あとで書くけども、ある行を2行上に移動するだけのことだった。くやしい。ではふりかえり。■A 問題「Christmas Present」。if 文が書けますかという問題。■B 問題「Christmas Trees」。負の数がいやらしいですね。負の数の整数除算の丸め方向を気にかけたくはない。M の倍数分 L と R をずらしても答えは変わらないので、L と R が A より右に来るように加算した。あとは L-A ≦ i*M となる最小の i と、j*M ≦ R-A となる最大の j を求めて j-i+1 が答え。整数除算を使った切り上げ切り捨て計算なんておなじみなのに、i と j を求めるのにもどうやって負の数を出さずに済ませられるか数分考え込んでしまった。頭がはたらいていない。■C 問題「Socks 2」。難しいよね。制約を見ると、ペアがそろってなくなることはないみたい。片足だけもしくは両足そろった靴下が隙間なく連続して並んでいる。片足-両足-両足-片足 という風に並んでいるとき、左から順番にちぐはぐなペアを作っていっても、真ん中の両足ペアを省いて両端の片足をペアにしても奇妙さの合計は変わらないみたい。じゃあ半端ものだけでペアを作ることを考えて良い(たぶん両足ともなくしてしまったことによるギャップがあるとそうはいかなかった)。そして総数が偶数のときは左から順番にペアを作っていって良い。では奇数のときはどの靴下を省くのが最良か。これって C 問題でしょ、絶対簡単な考え方があるよなという疑念に包まれたまま、左右からの累積和を使って総当たりで最良の答えを探した。■D 問題「Reindeer and Sleigh」。トナカイとスライもしくはスレイ(※読みも意味も知らない)。トナカイは匹ではなく頭で数えたい気がしました。ソートして累積和を用意して二分探索をする。■E 問題「Christmas Color Grid 1」。問題文がちょっと難しいけど、隣接する # のマスでグループを作って、. のマスがいくつの異なるグループを連結してその結果連結成分がいくつになるかを数える。実装していて気がついたけど、. のマスが新たな孤立グループになることもある。期待値を求める式に難しいところはない。すべての . マスについて、連結成分の数を数えて合計し、. マスの数で割る。■F 問題「Christmas Present 2」。DP をしたいけど線形時間で解けと制約がいっている。どうしましょう。いったん時間を忘れると、ある子供のところに行くにあたり、2通りのルートが考えられる。(プレゼントが1つ以上あるなら)直前の位置から直行して手持ちのプレゼントを1つ減らす。もしくは、サンタさんの家に寄って K 個のプレゼントを手にしてから来て、K-1 個にプレゼントを減らす。K+1 要素のデックに移動距離を記録して、shift、push、最小値の取得をすれば答えは出る。しかし TLE が避けられない>提出 #48793891 (TLE)。アイデアはある。K+1 要素の固定長ではなく、スライド最小値の要領で意味のある値だけを記録すればいい。全要素に対して移動距離を加算したり、プレゼント数を減算したりしたくなるのは、ベースとなる値をそれぞれに用意して、それとの差分を記録するようにすればいい(ベースを増減すれば全体が増減する)。提出 #48800858 (AC / 415 Byte / 305 ms)。数字が合わなくて提出が間に合わなかったのだけど、原因は 12 行目の処理を 13-14 行目の後ろに置いていたこと。基準値(d0)を加味した値と基準値からの差分とを比較してはいけない。あーあ、解けてたのになー。■それでも青パフォうれしい。コンテスト成績証。最近不調だったけど、今日のここが定位置だと自認している。次のステップは F 問題を時間内に通すことなんだよな。■F 問題を Ruby で最初に通した人はセグメント木を使っている。最小値を取得するのにセグメント木を使いたくなったのは自分も同じだけど、shift/push をどうするかがわからなくて深追いしなかった。セグメント木で解けるとわかってそういう前提でもう一度考えてみると、N+K 個くらいの要素数でセグメント木を初期化しておいて、参照する K 幅の範囲を1ずつ右にずらしていくという方法で shift/push 操作がまかなえるのではないか。セグメント木をそういう風に使ったことがないので思いつかなかった。……と思ったんだけど、セグメント木を使う2つの提出 #48799502#48806332 を見てみるとそれぞれ K+2 と N のサイズで初期化している。なんで全部違うんだ。いや、まあ、説明できないことはない。N+K と N は、最初は参照するべき値が K 個ないことを考えると実質同じようなものだし、K 要素の方は、無効になったインデックスに新しい値を詰めるようなリングバッファ的な使い方で理解できる。実際にそういう使い方をしているのかは確かめていないので知らないけども。