AtCoder Weekday Contest 0019 Beta E問題メモ
E - Loading Cargo
問題文
- $N$ 個の段ボール箱があり、$i$ 番目の段ボール箱の重さは $W_i$、耐荷重は $D_i$ です。
- 高橋君はこれらの段ボール箱の中から何個か選び($0$ 個でもよいが、同じ段ボール箱を複数回選ぶことはできない)、選んだ段ボール箱を好きな順番で下から上へ一列に積み上げます。
- 積み上げた全ての段ボール箱について、その上に載っているすべての段ボール箱の重さの合計が耐荷重を超えてはいけません。
- つまり、選んで積み上げた段ボール箱を上から $i_1,i_2,...,i_k$ とすると、$p=2,...,k$ の全てで $\sum_{q=1}^{j-1}W_q \le D_p$ が成立しないといけません。
- 積み上げに使用できる段ボール箱の個数を最大化してください。
制約
- $1 \leq N \leq 2 \times 10^5$
- $1 \leq W_i \leq 10^9$
- $0 \leq D_i \leq 10^9$
- 入力はすべて整数である。
解法
典型っぽい見た目だが見た記憶が無かった。
気付けば実装は簡単なんだけど、なかなか気付けなかった。
まず、こういう重さと耐荷重がある場合は、$(W_i+D_i)$ でソートすると上手くいく。
ソート順に番号を振り直すとする。
$i \lt j$ なら、積み上げる時に $i$ の方を上に置くとして損しない。
で、ここから個数を最大化したいんだけど、$N$ も $W_i$ もでかいので、ナップサックDPみたいなことはできない。
- $\mathrm{DP}_没[i,j]:=i$ 番目の箱から選んで、重さ合計が $j$ である時の最大個数、など
実は、以下の方法で上手くいく。
- 優先度付きキュー $Q$ を空で初期化する。各時点で $Q$ に入っている値の総和を $S$ とする。
- $i=1,2,...$(ソート順)に処理する。
- $S \le D_i$ なら、$Q$ に $W_i$ を追加する。
- そうで無い場合、$Q.max \gt W_i$ なら、$Q$ の最大値と $W_i$ を入れ替える。
- 最終的な $|Q|$ が答えである。

