2024-08-15
Codeforces Round 966 (Div. 3)に参加した
Codeforces Div. 3の参加記.
8月13日に開催されたCodeforces Round 966 (Div. 3)に参加した.結果はABCDEFGの7完で275位.
Div. 3はコンテスト終了後にHackのフェーズが12時間ありその後でようやくシステムテストが始まるので,レート更新を待つ時間が永遠に感じられた.
A - Primary Task
問題概要
整数が与えられるので,以下の条件を満たす整数が存在するかどうか判定せよ.
- 条件:の(leading zeroなしの)進表記と,
'10'の末尾にの(leading zeroなしの)進表記を追加したものが一致する.
考えたこと
コーナーケースに注意して丁寧に判定していく.の進表記をとすると,以下の条件がすべて満たされていればよい.
- は文字以上
- の最初の文字が
'10' - の文字目は
'0'でない - の文字目以降を進整数として解釈したとき,その値が以上
Rustでの文字列操作はやっぱりまだ慣れない.
提出:https://codeforces.com/contest/2000/submission/276116576
B - Seating in a Bus
問題概要
個の座席が列に並んでいるバスがある.人の乗客がこの順にバスに乗り込み,乗客が座った座席はであった.このとき,以下の条件が成り立つか判定せよ.
- 条件:ならば,乗客の座った座席に隣接する座席であって,すでに別の乗客が座っているものが存在する.
考えたこと
座席iが埋まっているかを表す配列occupied[i]を管理しつつ,乗客の順に条件が満たされているかどうかを逐次的にチェックしていけばよい.座る席が端っこのとき配列外参照しないように注意.
提出:https://codeforces.com/contest/2000/submission/276133887
C - Numeric String Template
問題概要
長さの整数列と整数が与えられる.に対して,以下の個の判定問題を解け.
- 英小文字だけからなる文字列が与えられる.以下の条件がすべて満たされるか判定せよ.
- となる任意のに対して,
- となる任意のに対して,
考えたこと
要するに,整数と英小文字が1対1対応するかを判定すればよい.そのためには,の順に数列と文字列を同時に走査しながらHashMapなどを用いて「整数→英小文字」と「英小文字→整数」の対応を記録していき,対応先が複数存在する箇所を発見したら答えをNOとする.
提出:https://codeforces.com/contest/2000/submission/276161477
D - Right Left Wrong
問題概要
長さの正整数列と,LまたはRからなる長さの文字列が与えられる.あなたは以下の操作を回以上好きな回数だけ行うことができる.
- 操作:まだ選んでいない整数の中から,
LかつRを満たす整数を選ぶ.これにより点を得る.
このとき,最終的に獲得することのできる点数の最大値を求めよ.
考えたこと
操作が回までしか許されないなら簡単で,最左にあるLと再右にあるRを選ぶのが最適である.操作が複数回許される場合でも,できるだけ区間の幅が大きくなってほしいというのは変わらないので,直感的には「まだ選んでいない端点のうち,最左にあるLと再右にあるRを選ぶ」ことを繰り返せばよいように思える.これは,累積和を構築したのちしゃくとり法の亜種のように区間の左端と右端を管理するポインターを左と右から走査させていくことででできる.
さすがに未証明のまま満足するのはよろしくないのでざっくりに正当性を考えておく.最大値を与えるような操作列があったとする.まず,操作順は得られる点に影響しないのでとしてよい.さらに,とならないようなが存在した場合,端点を組み替えることで点の総和を悪化させずにをこの順に並べることができる.よって最適解の形ははじめからの形だけ考えればよく,その制約下では確かに「まだ選んでいない端点のうち,最左にあるLと再右にあるRを選ぶ」のが最適である.
提出:https://codeforces.com/contest/2000/submission/276184108
E - Photoshoot for Gorillas
問題概要
匹のゴリラがおり,番目のゴリラの身長はである.
のグリッドと整数が与えられたとき,グリッド上の異なる個のマスを選んでゴリラを配置することを考える.ゴリラをマスに配置したとき,その配置の眺めの良さ(spectacle)を,グリッド上のの正方形領域に含まれるゴリラの身長の総和をすべての正方形領域について足し上げたもの,と定義する.より厳密には
である.このときの最大値を求めよ.
考えたこと
マスにゴリラを配置したとき,上の和にが何回登場するかを考える.これはマスを含むような領域の個数に一致し,その数は
とで求められる(あるいは2次元imos法を使ってかけてまとめて計算してもよい).
こうして各マスにゴリラを置いたときの重みが分かったので,あとは身長が高い順に重みの大きいマスに割り当てていけばよい.この貪欲パートの計算量はである.
提出:https://codeforces.com/contest/2000/submission/276214198
F - Color Rows and Columns
面白かった!
問題概要
個の長方形があり,番目の長方形は行列のグリッドである.あなたは以下の操作を何回でも行うことができる.
- 操作:いずれかのグリッドのまだ色が塗られていないマスを選び,そのマスに色を塗る.
- そのマスに色を塗ったことにより,そのマスを含む行のすべてのマスに色が塗られた状態になった場合は,新たに点を獲得する.
- そのマスに色を塗ったことにより,そのマスを含む列のすべてのマスに色が塗られた状態になった場合は,新たに点を獲得する.
点以上をとるために必要な操作回数の最小値を求めよ.点以上を獲得することが不可能な場合は-1を出力せよ.
考えたこと
最適な手筋は単純な構造をしていなさそう.サイズの小さいグリッドから塗っていくのは必ずしも最適とは限らず,複数のグリッドをまんべんなく塗っていくほうが効率がよいこともありそうだ.また,グリッドを選んでもすべてのマスを塗るとは限らず,いくつかの行や列が埋まった状態で終わりにするほうがよい場合もあるだろう.
いろいろ考えるうちに,この問題を次のように言い換えるのがよいことが分かった.
それぞれの長方形に対して「色を塗るか塗らないか」「塗るとしたらどこまで塗るか」が選択できるとき,操作回数の最小値は?
このような枠組みで問題を捉え直すと,これがまさしくDPで解ける構造をしていることが分かる.具体的には,
- :番目の長方形まで塗り方を決めたとき,獲得点数がであるような塗り方に対する操作回数の最小値
のようなDPテーブルを定義して逐次的に値を求めていけばよい.
ただし遷移は少し複雑だ.まず長方形を塗らない場合に対応して
という更新をする.
問題は長方形を塗る場合だ.マスをどこまで塗るかによって得られる点数が異なるため,のそれぞれに対して,点得る場合に要する最小操作回数を計算する必要がある(得られる点数はマスを全部塗ったときが最大で,このとき行数と列数の合計である点が入る).注意しなければならないのは,「つねに行方向に塗る」「つねに列方向に塗る」などの戦略は必ずしも最適であるとは限らない点である.例えばのグリッドを塗るとき,つねに一方向に塗るよりも
xxx 3 ooo 2 ooo 2 ooo 1 ooo 1 ooo
xxx → xxx → oxx → ooo → ooo → ooo
xxx xxx oxx oxx oox ooo
のように,交互に塗ったほうが(最終的に獲得する点数は同じでも)早く点数を獲得できる.より一般には,塗る方向を新たに決めるたびに,その行/列を塗るために必要な操作回数(まだ色が塗られていないマスの数)がより少ない方向を貪欲に選んでいくとよい.これをの順に行っていき,その都度
という更新を行えばOKである.
このDPの状態数は,遷移は各に対してで,制約がなので実行時間制限に十分間に合う.
提出:https://codeforces.com/contest/2000/submission/276255664
G - Call During the Journey
TL 4 secとRustに甘えてlogを2つ付けました……
問題概要
頂点辺の単純無向グラフが与えられる.あなたは頂点を時刻に出発し,辺を移動して頂点まで移動する予定である.
各辺には種類の重みが設定されており,それによって辺を通る際の所要時間が以下のように決まっている.
- バスを使って移動する場合,時間がだけかかる.
- 徒歩で移動する場合,時間がだけかかる.
また,あなたは任意の頂点で任意の時間だけ立ち止まってもよい.
加えて,時刻から時刻には電話の予定があり,この間(端点を含まない)にバスに乗っていてはならない.
このとき,頂点への到着時刻が以下であるような出発時刻の最大値を求めよ.
考えたこと
問題設定は複雑だが解き方はシンプル.
ひとまずを固定して考えると,頂点への最も早い到着時刻はダイクストラ法で求めることができる.遷移がやっかいだが,時刻に頂点を出て辺を移動するとき,考慮すべきなのは
- だけかけてバスで移動する(またはのときに限る)
- だけかけて徒歩で移動する
- 電話が終わるまでその場にとどまってから,だけかけてバスで移動する(のときに限る)
の3つで十分である.
を固定したときの判定問題が解けたので,あとはの境界を二分探索で求めればでこの問題に答えることができる.
後から気づいたが,頂点を起点として逆向きにダイクストラ法を適用すれば二分探索なしで求めることが可能である.