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

脳log[20230729]



2023年07月29日 (土) [AtCoder] 今日はユニークビジョンプログラミングコンテスト2023 夏 (AtCoder Beginner Contest 312)があった。以下 ABCDF のふりかえりと GE の精進を。■A 問題「Chord」。こういうのはコピペを活用してできるだけミスの混入を避けるべきなんだよね。そういう意味で自分の提出 #44032329 はコピペしたあとに手を動かしていて良くない。Shiro_S さんの提出 #44031960 を見習いたい。■B 問題「TaK Code」。すっかり実装が面倒くさい枠の B 問題。4×4×2=32 マスの黒白を愚直に確かめるだけ。そんなんでも添字の範囲を間違えたりしてたいへんなんですよ。■C 問題「Invisible Hand」。ぼんやりして全然頭がはたらかなかった(いつものことか?)。問題文を読むかぎり必ず答えが見つかるみたいな雰囲気を感じるけど、そうだとはわからない。目に付いた数字で二分探索をするもサンプルの2がありがたくも優しくそれではダメだと教えてくれる。A、B 数列の両端付近の値を候補に加えて二分探索で答えを探したけど WA だった。それならと各数字の前後を候補に加えて 3N+3M 個の数字から答えを探したら AC だったけど、あまりにひどい力業。TLE になっていたらお手上げだった。Ruby で2番目に早く提出された gmmtea さんの決定的な提出 #44046237 がすごい。探索などしていない。■D 問題「Count Bracket Sequences」。2乗が通る制約。(閉じていない)開き括弧の数ごとに場合の数を記録する DP をやってみたら DP 配列を shift したり unshift したりする面白い形の遷移になった。もっと効率的なやり方(※)がありそうではあるけど、制約で許されているので愚直に配列を操作した。※倍の長さの配列を用意して真ん中を暫定の先頭にする。実は Ruby のインタプリタが shift も unshift も勝手にうまくやってくれるので考える必要がない。■E 問題「Tangency of Cuboids」。幾何問題。心中リスクが高いので飛ばした。終了3分後の提出 #44081331 は TLE だった。■F 問題「Cans and Openers」。配点は E 問題と同じ。貪欲法でできるかなと考えてみたけど、缶切りの数に応じて答えがガタガタして無理そうだった。場合分けも、缶切り不要の缶が M 個に足りない場合や、缶切りがあっても缶切りが必要な缶が十分にない場合など、状況と状況の重ね合わせまで考えるとたいへん。2本の累積和からいい感じに M 個を取るという構図から ABC116-D Various Sushi を思い出していた。しかしその精進(20220609)は生きず。BIT を2本使って缶切りの数ごとに愚直に満足度の総和を求めた。Ruby によるすべての提出を見ると、貪欲っぽいもの、プライオリティキューを使うもの、DP らしいものなどいろいろ。log が付くデータ構造を使った自分の提出 #44067838 などは時間が余分にかかっていて、もうちょっと頭を使ってがんばりましょう、という感じ。■G 問題「Avoid Straight Line」。コンテスト終了後に本腰を入れて考えた。単純パスを構成しない3つ組とはどういうものだろうか。制約を見るとペアを考えることが許されていないので、ペアから LCA を求めて……という解法にはならないとわかる。それで、どういう3つ組? 根っこに向かって一直線の3つ組ではない。2頂点とその LCA から成る3つ組(ペアの場合もあるが無視する)ではない。根っこに向かう直線ペアと×××の組み合わせではない。……。部分木ごとに直線ペアの数と分岐するペアの数を記録して根っこに向かう DP をすれば求めたいもの(分岐するトリオの数。変数名 spt は split trio の略らしいです)が計算できそう。提出 #44086692 (AC / 488 Byte / 1741 ms)。サンプルの3が合わないときは3つの子から1つずつ選ぶ spt を数え忘れてるかもね(経験談)。Ruby による G 問題へのすべての提出を見ると自分の遅さが際立っている。なぜ?■コンテスト成績証自分のすべての提出。ABCDF の5完でまずまずの成績。(終了後でも) G 問題が解けて満足している。AtCoder Problems によると難易度勾配は F(水)<G(青)<E(黄) らしいけどね。たしかに、E 問題の TLE を解消する手立てがまだわからない。直方体の数が 10 万あるのに、あれとこれが接触している、これとそれが接触している、と個別にペアを数えてはいけないのかもしれない。だけど6面あって重複をカウントしないように何ができる?■■■G 問題。自分の提出が他と比べて桁違いに遅いのでちょっと考えてみた。前回は子(部分木)ごとにサイズと直線ペアの数を記録して求めるもの(分岐トリオ)を計算して足し合わせていた。分岐トリオを求める計算が余事象が関わっていてちょっと面倒くさい。今日は子(部分木)ごとにサイズと直線ペアと直線トリオを記録して、根っこで一括して余事象を求めるようにした(3つ組の選び方から直線トリオを引く)。提出 #44113272 (AC / 309 Byte / 602 ms)。桁は並んだけど 400 ms 台、500 ms 台に比べると遅い。メモリ消費が4倍くらいあるんだよね。根っこから再帰関数を呼び出すのでなく、葉から根へ積み上げるべきなのかもしれない。だけど記述のシンプルさにはあらがえない。簡潔に書けてると思うん。ゴルフしてるものにくらべるとまだ余計なことをしてる無駄な記述があるみたいだけど。■E 問題。座標空間が 100×100×100 でえらく狭いなと、ここに直に書き込んで何かできないかと考えてはいた。でも 100×100×100×N では TLE だしなーと。見落としていた重要な制約があった!!! 「直方体同士は体積が正の共通部分を持たない」 だったら N 個分書き込んでも総和は 100 万以下じゃん! 隣のマスを見たら隣接直方体がわかるやん! 提出 #44116267 (AC / 553 Byte / 729 ms)。■延長1日を含めてこれもう実質7完でいいんじゃね? やったぜ!(めでたい)■■■G 問題。現在見ている頂点を3つ組の真ん中の頂点だと考えて直線トリオを数える DP ができるらしい(最後に3つ組の全選び方から引く)。提出 #44139844 (AC / 303 Byte / 634 ms)。そうすると直線ペアの数を数える必要がなくなって、サイズと直線トリオの数だけを数えればよくなったけど、期待に反してわずかに遅くなった。400 ms、500 ms 台に入ると思ったのになぜ? 実は答えを合わせるのにすこし苦労して、現在見ている頂点を3つ組の真ん中に決め打つということは、他の2頂点を選んでくるのは子方向の部分木だけに限らず親方向からも選んでこられる(16 行目)。その点がこれまでの2つの解答と異なっていた(これまでは現在見ている頂点が LCA になるような3つ組を考えていたので問題が子孫方向の部分木に閉じていた)。■E 問題。たぶんだけど、サンプルにわかりやすーい図解が付随していたら当日の AC がもっと多かったと思う。問題文を読んでも全然具体的イメージが構築できなくて苦労したもんね。まず直方体の対角線って何だ、とか。それは長方形の対角線とは(必ず)違うと考えていいのか、と。不等号(X1<X2, Y1<Y2, Z1<Z2)に意味を持たせすぎないでもっと文章で説明してくれていいのよ。辺が軸に平行だということも、え、それってどういう、という疑問からなかなか先に進めなかった。脳内直方体は歪んでいた(それは直方体ではなくない? 菱餅? そんなつっこみも出てきやしなかった)。■■■F 問題。自分の提出は BIT を使ったせいで余分な log がついて時間がかかっていた。よく考えて整理した結果、2本の累積和から M 個を取ったあとで綱引きをするようにした。要するに尺取り。提出 #44215202 (AC / 619 Byte / 389 ms)。最速級まではいかないけど BIT 版より倍は早くなった。じっくり整理したので規則的で理解しやすいと思う。S2 に前加工を施すと k1x の補正が必要なくなるし、無意味に缶切りを取得する前に試行を中断できるけど、それは TODO。