/ 最近 .rdf 追記 設定 本棚

脳log[2021-12-19~]



2021年12月19日 (日) [AtCoder] 今日は M-SOLUTIONS プロコンオープン2021(AtCoder Beginner Contest 232) があった。ABC で ABC の三完を嘆いていたのが先々月のこと>20211010p01。今日はついに C 問題が解けなかった>提出 #28000177 (WA / 341 Byte)。B 問題でも WA を出した>提出 #27988292 (WA)。もう終わりだよ。脳細胞が死滅し尽くしている。■(C 問題が)解けた! 提出 #28019725 (AC / 341 Byte)。特に嬉しくはない。■E 問題は「Rook Path」だった。前日に Queen の問題を解いていたのは不思議な偶然>20211218。当然のこと Queen の解法が最初に頭に浮かんだけど、それは使えなかった。それもまた当然。提出 #28011903 (AC / 286 Byte / 523 ms)。この形の DP は「自分が DP を知らなかった昔に DP と知らずに書いたのと同じ形」だから一番なじみがある。行列累乗で高速化することまでは考えが及びませんが>#28012377 (63 ms でありつつほぼ同時刻の提出!)。


2021年12月18日 (土) [AtCoder] 精進。ABC183-E「Queen on Grid」(水 diff)。400 万マスのグリッド問題。グリッド全体を一度だけスキャンして答えを出さなければいけない。現在のマスにあるクイーンが移動できる先のマスを処理対象にすることはできない。現在のマスに移動してくることができるクイーンの移動経路の数が知りたい。コンテストの最中と直後は、一歩右と一歩下と一歩右下を操作対象にして累積的な効果を持たせることを考えていて、できなかった。今日は ABC224-E「Integers on Grid」を解いたときの記憶があったので(20211023p01.02)、どういう記録をつければいいのかすぐにわかった。提出 #27972471 (AC / 292 Byte / 723 ms)。わかるときとわからないときの差がわからない。論理で舗装した必然の道を敷くことができないんだろうなあとは思う。ひらめき待ち。


2021年12月17日 (金) もはや何チャンネルなのかわからんところの「ミニマップを表示すると、Backspaceで文字を連続で削除するのが超絶遅くなるけど、仕様? 使いものにならない…」に対する答え。書き込めなかったのでここに。「たぶん3種類くらい遅さがあって 1. バックスペースをカーソル左移動と Delete の2操作に分解して実行しているがゆえにアンドゥ履歴が2倍記録されて遅い。 2. ミニマップを表示してると文書サイズに比例して改行の入力/削除が遅い。 3. 文書末([EOF]マークがある位置)での文字入力/削除がなぜかひときわ遅い。さてどれでしょう」 2 と 3 は同根かもしれないのと、実際のところ 1 とミニマップの繋がりは(現象としては確認できても)まったく明らかではないしよくわかんない。■■■なんかアンドゥに関係してかしないでか(ミニマップを含む)全ビューの再描画が無駄に行われていたらしかった。「BSキーでカーソル前を削除時に画面が余計に再描画される事を防ぐ by beru · Pull Request #1754 · sakura-editor/sakuram_nOpeBlkRedawCount って初めて見るけどどういう役割なのかな。結局行き着くところはミニマップの構造的・原理的問題だよね。文書の全体を(たぶん愚直に)描画しているからいろいろと遅い。全体を俯瞰するのがミニマップの用途だと思うけど、俯瞰したいほど大きな文書を扱うのに難がある。LOD (Level of Detail) が必要?


2021年12月16日 (木) [AtCoder] JOI 2021/2022 二次予選 過去問から精進2問。■C 問題「国土分割 (Land Division)」。すること自体は難しくない。目指すべき状態を作ることも判定することも簡単にできる。だから仕切り方を全探索して数えるのは簡単にできるはず。それでは時間が足りないから効率がいいように手続きを組み立てるわけだけど、実装するのにすごく迷った。関数を抽出して処理がまとめられそうでまとめられなくて、でもやっぱりまとめたくてできなくて。提出 #27909751 (100 点 / 566 Byte / 69 ms)。結局抽出できたのは I 関数のみで、メインの処理は似た構造を重ねた二重ループのままになった。■E 問題「交易計画 (Trade Plan)」。制約上限が頂点数、辺数、クエリ数すべてで 40 万なので、判定はほぼ定数時間で行わなければいけない。UnionFind をうまく使うだけ。提出 #27932262 (100 点 / 727 Byte / 2581 ms)。もちろん一度は間違えた>WA。最初からうまくはできない。■飛ばされた D 問題「飴 2 (Candies 2)」。解けないんだよなあ。DP で間違いないと思うんだけど。単体の数と2数の和の2種類の数があって、2数の和から単体の数(と見なせる状態)への遷移があって、そういうのを整理しながら数列をスキャンしていって最大値を答えるんだと思うんだけど、答えにたどりつかない。


2021年12月10日 (金)

最終更新: 2022-01-03T13:27+0900

[AtCoder] JOIG 2021 過去問F 問題 デジタルアート (Digital Art)

D と E についてはここに書いた>20211206。A,B,C については ABC-C までの難易度帯という感じで特に何ということもなく解けたので書いていない。最後に F 問題が残っていた。

 考え方

色ごとにその色を完全に覆い隠せる矩形を考える。矩形は左上座標と右下座標で特徴付けられる。面積 S を超えない範囲でどのような矩形を選べばできるだけ多くの色を隠せるだろうか。

 制約

グリッドの一辺は最大 1000 なので、グリッド上の点は最大 100 万個。いくら面積 S を超えない範囲でできるだけ大きな矩形のみを考えるとしても、グリッドから2点を選ぶ組み合わせは1メガ×1メガに近い数になる。これは制限時間1秒で扱える数ではない。

色数の上限が 256 に抑えられている。256 の3乗は約 1600 万だから、Ruby の場合、定数倍が 1/2 とかなら3乗がなんとかなるかな、という雰囲気。

 どうやる?

二次元累積和であるとか「Range Set Query」が思い浮かんだけど、どうにも(知っている)定型の処理に当てはまらない。

矩形の左上座標と右下座標を探索することが許されるなら、色を、その色を囲う左上座標と右下座標のそれぞれでソートしておくことで、うまく探索してマッチングして数を数えられると思う。

色を特徴付ける矩形の左上角と右下角の組み合わせを選ぶ 256 の2乗通りでは答えを漏らすのでよろしくないが、4辺を選ぶ 256 の4乗通りは許されない。困った。

 どうした

矩形の縦の長さを固定して横方向に尺取りをした。

 提出 #27751046 (75/100 点 / TLE×9)

最後の小課題9のケースもいくつか通ってるので惜しいのかと思ったけど、実は遅いケースは 10 秒とかそこらかかっていた。

4重ループです。上辺について 256 通り。底辺について 256 通り。右辺と左辺について尺取りが 256×2 ステップ。その最深部で矩形に出入りする色が 256 個。だめじゃん。

 提出 #27751294 (TLE×9)

定数倍の改善。Array#minmax の呼び出し回数を節約した。650 ms が 350 ms になるレベル。

 提出 #27752007 (TLE×9)

定数倍の改善。上辺と底辺に関する第一第二ループを Array#repeated_combination(2) で横着せずに、尺取りっぽく遷移して重複する処理を減らした。550 ms が 450 ms になることもあるし、変わらないこともある、という変化。

 提出 #27772767 (TLE×1)

ついに来た! TLE は残り1ケース。

改善したのはやっぱり定数倍だけど、上辺に対する底辺の選び方を、尺取りの幅でグループ化して最も高さが大きくなるものに代表させることで、尺取りの回数が大幅に減った。

もうひとつ。ループをイテレータではなく while 文で書き直すことで Ruby の場合かなり速くなるんだけど、それに加えて、答えの候補を求めるループの途中で暫定的な答えにアクセスできるようになったのも大きかった。それにより答えを更新する可能性がない場合に最内ループをスキップすることができた>or ain.size<=max

 提出 #27797091 (100 点 / 935 ms)

これも定数倍の改善。インチキをした。底辺を尺取りの幅でグループ化する部分が

i1s = I1s.group_by{|i1| i1<i0 ? 0 : [S/(i1-i0+1),W].min }

だったところを、次のようにした。

I1s.shift while I1s[0]<i0
i1s = I1s.chunk{|i1| [S&1|S/(i1-i0+1),W].min }.map{|_,as| as[-1] }

S&1| ってなんですかね?

とにもかくにも、(1差の偶数と奇数を同一視することで)4重ループのうちの2番目のループの回数が節約できたのはとっても効いた。

想定解法は3乗もしくは3乗+logとかのもっとスマートなアルゴリズムを使っているのだろうか。それとも Ruby は想定外だからさっさと Crystal や C++ で出し直すべき案件だったのだろうか。3 MiB オーバーの入力ファイルを読み込むのにも、つまりはスクリプトの1行目の処理を終えるまでにということだけど、1秒しかない時間のそれなりの割合を使っているのだよね。

 デジタルアート解説 (PDF)

想定解法は上辺と底辺を固定しての尺取りだった。やり方は間違っていなかった。その計算量が O(HW+A^3) だというのがわかっていなかった。実際は A^3 でできていたのか、それとも何かおかしなことをして A^4 にしてしまっていたのか、どっちだろう。


ちょっとおかしなことをしていた。AC 提出の最内ループのこの部分。

	ain.reject!{|wj0| wj0<=j1 }

尺取りから出て行く色を見つける部分で、尺取りの中にある色の全体を都度スキャンしていた。

尺取りの右がある座標に至ったときに入る色と、尺取りの左がある座標に至ったときに出る色は、それぞれの合計が最大で 256 個であり、一度の尺取りを通して合わせても 512 個という定数にしかならない。ある座標で入る色と出る色をそれぞれリストしておいて、ある座標に至ったときにそれらの色が尺取りの中にあるかどうかを確かめるべきだった。

このように>joig2021_f.rb27。あるいは最初に TLE をもらった提出 #27751046 のように>20211210p01.05

だけどたぶんこれは TLE になる(OS が違うけどローカルで測定している)。定数倍の影響が大きすぎるのではないか。最後の TLE をクリアしたとどめの一手だって、尺取りのステップ数を随時削減することによる定数倍の改善だった(S&1| だけでは足りなかったのだ)。やはり Ruby で満点を取ることは想定されていないと思う。


日本情報オリンピック 第2回女性部門(JOIG 2021/2022) から「情報オリンピックに初めて参加する方は、出題形式・勉強法・講習会などに関する情報をまとめた「情報オリンピックの勉強法」をご覧ください」とリンクされていた(JOIの)ページから。

JOI 本選

本選は 2 月に実施されていて、4 時間で 5 問に取り組みます。上位者は春合宿に招待されます。

本選では二次予選と比べて難しいアルゴリズムの知識や、そのアルゴリズムを与えられた課題に適用させるための高度な発想力が問われます。

JOI 春季トレーニング合宿 (春合宿)

春合宿は IOI 日本代表を決めるための代表選抜会です。3 月に実施されていて、4 日間連続で毎日 5 時間の競技に取り組みます。上位 4 人は IOI 日本代表として派遣されることになります。

なお、春合宿で使えるプログラミング言語は C++ のみです

本選の後に春合宿があり、「なお、春合宿で使えるプログラミング言語は C++ のみです。」 そうなのね。


2021年12月07日 (火) 我は如何にして精進ボットとなりしか。


2021年12月06日 (月) [AtCoder] 精進。JOIG 2021 過去問D - 展覧会 2 (Exhibition 2)。まずは TLE & WA だけど 39/100 点の提出 #27698611。よくある DP をした。あるインデックス i より右から j 個の要素を選んだ場合の価値の最低値を記録する DP。これを j が 1 から M に至るまで繰り返した。N と M の上限がともに 10 万だから二重ループが TLE になるのはわかる。でも WA が 7 個(もしくは TLE の背後にそれ以上)あるのはわからん。■個数と価値を記録するのでなく個数だけ記録するのはどうだろうかと考えた。i 番目の絵画の右と左に合わせて M-1 個(以上)の絵画が飾れるなら、i 番目の絵画の価値は答えの候補になる。右からと左からの2度のスキャンで済むから処理時間は足りる。だけど M 番目に大きい価値がいくつになるのかがわからない。■制約をメタ読みすると N^2 はダメでも NlogN の処理は許されている。ある価値で足切りした場合にいくつの絵画が飾れるか。足切りラインの探索に二分探索を、いくつの絵画が飾れるか調べるのに2度のスキャンを繰り返してもまだ時間は足りる。提出 #27735789 (100 点 / 617 Byte / 792 ms)■スキャンは2回1セットである必要はないみたい。自分にはわからんけども。■JOI が何かも知らないなら JOIG が何かも知らなかったけど、G は Girls の G だったらしい。EGOI などというものもあって J (日本) 固有ではないらしいけど、あえて for Girls をもうけるモチベーションはよく周知してほしいと思う。わからないから。女子を集めて愛でるためではないだろうし、数的能力に性差を認めて平等に活躍の機会を与えるための不平等な取り扱いというわけでもないだろうし。母集団の大きさが違いすぎるのかなという気はするけど、分類の基準は性別に限らず能力別も考えられるはずで、決め手に欠ける感じがある。■■■E - パレード (Parade)。普通かな。逆行する回数を1ずつ増やしながらプライオリティキューでダイクストラ法を繰り返した。提出 #27742640 (100 点 / 1112 Byte / 535 ms)。頂点 0 と頂点 1 から 0 への辺を追加するとメインループのコピペが解消できる。


2021年12月01日 (水) スラム化が促進するアパートの“空室”問題 それでも郊外のアパートが増え続けるのはなぜか | 文春オンライン」■記事の内容には興味がないんだ。因果関係を確かめるために最後のページまで読んでしまった。3ページ目から。「空室率の上昇は、アパートのスラム化を促進する。」 促進するが自動詞でもあるなら記事のタイトルはどちらの意味にもとれるけど、そうではないのでどちらがどちらかわからなくなってる。まあ、ポジティブフィードバックがありそうで区別の必要がないような気もするが、そういう意図があって書かれてはいないと思う。■空室問題は誰の問題か。執筆者の経歴はこちら>「牧野 知弘 プロフィール | 文春オンライン」。記事の最後には『空き家問題』という著書へのリンクがあり、そのレビューによると、空き家問題を抱える個人にとっては期待はずれの内容で、日本の税や住宅政策を原因とする構造的問題を取り上げたいらしい。だけども記事の方は違う。タイトルや最終ページの最後の方の内容(「空き住戸の多いアパートは住んでいても気持ちが悪く、治安も悪化する。住環境の悪化を嫌う住民は他の新しいアパートに移り、懐に余裕のない住民だけがアパートに残る。当然賃料の引き上げには応じる余裕はないし、その気もない。住民層も若年から、もはや世の中の動きから取り残された高齢貧困層などに替わっていくだろう」)からはそういう大きな問題意識は伝わってこない。空室問題は問題なのか。記事からはそこが読み取れなかったのでプロフィールから著作のレビューまで読むことになってしまった。■政策ミスによる無駄の誘導は是正してより価値あるものを残すべきだと思うけど、それを大家の問題に矮小化しているようにしか読めない。そして大家が抱えることになる問題は(お金がない)住人視点では問題に見えない。


2021年11月30日 (火) [AtCoder] 昨日あった ARC130。C 問題「Digit Sum Minimization」。制約が貪欲しか許さないと告げている。繰り上がりが起こった場合にしか和が減らないのはわかった。繰り上がりがある前提で繰り上がりを連鎖させるために桁の和が 9 から 18 になる組み合わせをこの優先順位で作っていくのが良さそう。ただし最初に繰り上がりを起こす和(10 から 18)の作り方がまずいとサンプルの2が合わない。敗因は、単独で繰り上がりを起こす1桁目を全探索しても許されると解らなかったこと。今日の提出 #27603786 (AC / 782 Byte / 712 ms)。数字の操作ではなく配列の操作を繰り返していて間に合ってるんだもんなあ。■あ、昨日じゃねーや。消えた月曜日。


2021年11月26日 (金) [AtCoder] 精進。JOI 2020/2021 本選 過去問 C「集合写真 (Group Photo)」。少し考えると、許される並びは一直線に右下がりの並びを基本として、何か所かでちょん切った右下がりを逆順に配置したギザギザ右下がりしか許されないとわかる。それを制約上限 5000 を4秒以内で求める手順とは。DP ですね。1以下の H をいい感じに並べる手数から始めて2以下、3以下……をいい感じに並べていくと最後に答えが出る。■提出 #27502421 (64/100 点 / TLE×15)。制約が異なる小課題のうち最後の小課題5がすべて TLE だった。アルゴリズムのオーダーが間違っている。N の二乗に BIT 由来の log をくっつけたのが良くなかった。■提出 #27509632 (TLE×15)。同じ TLE とはいえ実行時間は 44xx ms から 40xx ms に改善している。ここからは定数倍の改善で 100 ms を稼げばなんとかなる。この提出では二重ループの内側で BIT を利用するのをやめて N^2 のループで前処理をした。処理を1か所にまとめようとしてループを重ねて計算量のオーダーを悪化させるより、同じオーダーのループを2つ並べる方が速いということが盲点になっている。Maximize GCD のときも気がつけなかった>20210919p01.03。今回のメインループは N^2 なのだから、大概のことが前処理でできる。BIT の代わりになる N 個の累積和(配列)を用意しても許される。■提出 #27510644 (AC / 3120 ms)。前処理で扱う配列の長さを必要な分だけに切り詰めた。要素数の合計が N*N から N*(N+1)/2 に減ったと思う。あとは配列参照を減らしたり数字の微調整をなくしたり reverse_each をなくすために最初から逆向きの配列を用意したりという爪に火をともす努力。そういうの好き。結果として AC 提出が一番短くなって 277 Byte。


2021年11月25日 (木) [AtCoder] 精進。ARC124-D「Yet Another Sorting Problem」(ギリギリ黄 diff。そんなアホな)。これは Swaps の仲間なのかな>20200826p0120211022p01。3つの中でこれが一番頭が爆発した問題だった。実際にソートして数を数えても許されるあたりは厳しくはないんだけど、添字と値が入れ替わって入り交じるスワップ操作で頭がこんがらかる。そして最後の最後にも罠があった>(gn-gm).abs提出 #27485094 (AC / 515 Byte / 188 ms)。ほぼ一日かかった。■考え方はいろいろあるのかな。自分はまず反対側の領域にもぐりこんでいる要素を探した。そしてそこに本来収まるべき要素を探し、探した要素があった場所に本来収まるべき要素……を芋づる式に探してグループとした。ただしグループは前半領域、後半領域のどちらかの中にだけ作って、領域をまたぐグループは考えなかった。こうやって1つずつ反対側に移動している要素の位置を移動しながらついでにソートもしていくと、最終的に反対側に移動している要素はなくなり、前半後半のどちらかに閉じて位置を交換していてソートされなかったグループが残る。反対側の未ソートグループが利用できる場合は利用して互いに交換回数を節約しながら全グループをソートする。この、手続きに基づいた解法がどのような考えからひねり出されてきたかというと、必ず行わなければいけない操作を無駄なく行う、というところから。貪欲法?


2021年11月22日 (月) [AtCoder] 精進。ARC112-D「Skate」(ギリギリ黄 diff)。初見ではない。グリッドだけど行列に見える。行と列を並べ替えて寄せていってもいいのかなと。島(#)がない行か列に足場(#)を作って連結していくことを考える。だけど足場が行と列の両方で孤立している場合には連結にならない。そこから連結しているもの同士が複数のグループに分かれて孤立している場合に想像が及ぶ。行で連結するのがいいか列で連結するのがいいか、両方のベストミックスを考える必要があるのか。いろいろ考えてしまって答えが出なかったのが初見のとき。今回は UnionFind でなんとかなりそうだと見当がついた。提出 #27452260 (AC / 471 Byte / 830 ms)。■青 diff の後ろの4問目でなければ水 diff だった可能性もあるのでは? こんなアンケートがあったよ。「ARC112 C(DFS Game)とD(Skate) どっちの方が難しいと感じましたか」 結果は7対3で C。印象通りだけど C 問題の方は時をおかずに解けているのも事実>20210216p01。■「Ruby によるすべての提出」を見ると他の AC (3つ)はほぼ半分の 400 ms 前後で処理を終えている。どうやら行と列に分けて2回の UnionFind を行う必要はなかった。行と列の組み合わせを一意に識別する (縦×横) 通りの通し番号を使うことは考えていたのだけど、そもそも # がある場所について、ある行に対する列、ある列に対する行を識別する必要がなく、(縦+横) 通りを考えるだけで良かった。提出 #27452260 (AC / 467 Byte / 445 ms)。


2021年11月21日 (日) [AtCoder] コンテストの時に限って頭ヨワヨワの神経衰弱になること、あると思います。実は試される機会がないから気がつかないだけで、いつでも頭ヨワヨワで生きていること、あると思います。