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|$ が答えである。

略証

Python3

programming_algorithm/contest_history/atcoder/2026/0305_awc0019.txt · 最終更新: by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0