ABC082 D - FT Robot Next-DP 解法
Next-DP よくわかってないのでもしかしたら違うかも.
問題リンク
D - FT Robot
解法
まず,前処理として を
というペアの列にランレングス圧縮します.
次に,配列
の値
を,座標
に到達できるかの bool 値と定めます.
すると,
回目の移動で到達しうる座標は前に同じ向きで移動したときに到達しうる座標にのみ依存します.
よって,RLE 配列を順に見ていき,Next-DP 配列に移動後に到達しうる座標を記録し
の対応する次元の値を上書き,という操作を繰り返すことで最終的に到達しうる座標を求めることができます.RLE 配列のサイズは
時間,移動による配列の更新も
時間で行えるので全体として
時間で答えを求めることができます.
提出コード (76ms) Submission #61342243 - AtCoder Beginner Contest 082
JOI '11 本選 B - 古本屋 bitDP解法
解説することはあんまりないです.
問題リンク?
B - 古本屋 (Books)
解法
各ジャンルについて, 個売るときの買取価格の最大値は貪欲法で求まります.したがって,
を(既に0冊以上売却したジャンルの集合が
,売却した総冊数が
のときの買取価格の最大値)とすれば,bitDP によって答えを求めることができます.時間計算量はジャンルの種類数を
とすると
となり,
なので定数倍に気を付けると AC できます.ちなみに,
std::vectorを使うと TLE になります.
dequeで作る挿入削除 O(√N), 添字アクセスO(1)のset
急に思いついたので実装してみたらなんか速かった。
アイデア
集合の要素数の最大値が高々 であるとして,
個の集合
を次のようなルールにしたがって管理することを考えます。
- 各
の要素数は高々
である。
かつ
なら
である。
かつ
なら
である。
このとき、各 の最大値
を持つことで挿入削除が
time、インデックスアクセスが
time で行えます。
insert
ルールより、 は単調増加です。したがって、(挿入する要素の値)
となるような最小の
を二分探索し、これを
とします。
次に、 に要素を挿入し、
となるまで以下の操作を行います。
の最大値(dequeの末尾)をコピーし削除する。
を更新。
の最小値としてコピーを挿入(dequeの先頭)。
を1増やす。
挿入に time、上記のループは1回あたり定数時間で高々
回行われるので
time です。
erase
insertと同様に二分探索して を発見します。
次に、 で削除を行い、
となるまで以下の操作を行います。
の最小値(dequeの先頭)をコピーし削除する。
の最大値としてコピーを挿入(dequeの末尾)。
と
を更新。
を 1増やす。
insertと同様に time です。
k番目の要素へのインデックスアクセス
ルールより要素は左詰めです。なので、 の
番目の要素を返せばよいです。
time です。
実装
実際には2べきの定数で分割しています。(何個か試したら 211 が一番速かった)
pairなどの std::numeric_limits<T>::max() が使えないような型を要素に使うときは inf の値を指定してください。
Submission #57429636 - AtCoder Regular Contest 033
とっぴんぱらりのぷう
動的な Merge Sort Tree を作っちゃうぞ
Merge Sort Tree というデータ構造があります。 要素の 静的な列
に対し、次のようなクエリを処理できます。
が与えられるので、
に含まれる
以下の値の総和を求めよ。
以下の総和なので、ソートされていれば累積和+二分探索で
時間で求められますが、一般の場合はどうでしょうか。
これは、マージソートの過程(と累積和)をセグ木の形で持つことにより処理できます。

通常のセグ木と同様に、区間をすべて包含するノードまで降りる→クエリ処理(累積和+二分探索)の流れで解くことができます。
目的のノードに降りる操作、クエリ処理はどちらも 時間かかります。よって構築
時間、クエリ
時間で問題を解くことができます。
提出コード
Submission #55233396 - Japan Registry Services (JPRS) Programming Contest 2024 (AtCoder Beginner Contest 339)
次に、こちらの問題を考えてみましょう。
が与えられるので、
に含まれる
以下の値の総和を求めよ。
が与えられるので、
の値を
に変更せよ。
先ほどのように Merge Sort Tree で処理しようとすると、更新クエリごとに配列をリセットする必要があり計算量が大きくなってしまいます。
そこで、各ノードでどのように値が管理されていてほしいかを考えると、次のような要件が浮かんできます。
- 閾値以下の総和が高速に求められる(≒常にソートされた状態が保たれる)
- 値の重複を許す
実装が大変ですが、multisetを自作すればよいですね。
変更クエリはないですが、ちゃんと動きそうです
【精進】ABC153 F - Silver Fox vs Monster
毎日自分のレート+400以上のdiffの問題を解きます。
問題リンク
F - Silver Fox vs Monster
解法
座標順にソートした後、単純に前から順に「 が負ならcontinue, 正なら座標が
から
の間にあるモンスターの体力に
以上の最小の
の倍数を引く」という操作を行う。
座標が範囲内にある最大の添字は二分探索、体力の更新は遅延セグメント木を使えば で処理できるので、全体で
となる。
【精進】ABC046 C - AtCoDeer and Election Report
毎日自分のレート+400以上のdiffの問題を解きます。
問題リンク
C - AtCoDeer and Election Report
解法
投票数が満たすべき条件は 「広義単調増加」 かつ 「比が 」
したがってi回目での投票数は
「 回目の投票数以上の最小の
の倍数
」
「 回目の投票数以上の最小の
の倍数
」
のうち大きい方を 回目の投票数にかければ良い。計算量は
Submission #53756132 - AtCoder Beginner Contest 046
【精進】ABC073 D - joisino's travel
毎日自分のレート+400以上のdiffの問題を解きます。 問題リンク D - joisino's travel
解法
という制約からワーシャルフロイド法
が見えてくる。町を訪れる順番は順列全探索で
、順番が決まれば移動距離の総和は
で求められるので、合計で
となりAC。
Submission #53721947 - AtCoder Beginner Contest 073