D - 果物狩りフェスティバル / Fruit Picking Festival Editorial by admin
Qwen3-Coder-480B概要
高橋君が、与えられた順番で脚立を使って果物を収穫し、得られるおいしさの合計を最大化する問題です。
考察
この問題では、各収穫チャンスごとに「今届く高さの果物の中から最もおいしいものを選ぶ」のが最適です。しかし、単純に毎回線形探索で最大のおいしさを探すと、最悪ケースで \(O(NM)\) となり、制約が大きいため時間内に処理できません(TLE)。
そこで、「今選べる果物」を効率的に管理するために、優先度付きキュー(最大ヒープ) を使うことを考えます。
さらに、脚立の高さ \(L_j\) が必ずしも昇順で与えられないため、脚立の高さ順にソートして処理することで、徐々に選べる果物を増やしていくことができます。
具体的には: - 果物を高さ \(D_i\) の昇順にソートしておく。 - 収穫チャンスも脚立の高さ \(L_j\) の昇順に処理する。 - 各収穫チャンスにおいて、今使える脚立の高さで届く果物をヒープに追加。 - ヒープから最もおいしさの高い果物を取り出して採用する。
こうすることで、各果物は一度だけヒープに入り、各収穫チャンスで最大の要素を取り出すだけなので、全体で高速に動作します。
アルゴリズム
- 果物リストを高さ \(D_i\) の昇順にソートする。
- 収穫チャンスの脚立の高さ \(L_j\) を昇順にソートし、その順序で処理を行う。
- 最大ヒープ(Pythonでは最小ヒープを負にして使う)を用意し、各収穫チャンスにおいて以下を行う:
- 現在の脚立の高さ \(L_j\) で届く果物をすべてヒープに追加。
- ヒープの最大値(最もおいしい果物)を取り出して答えに加える。
- 全ての収穫チャンスを処理したら、合計値を出力。
例
例えば、果物が \((D, V) = [(1, 3), (2, 5), (3, 2)]\)、脚立が \(L = [2, 3]\) の場合:
- ソート済み果物: \([(1, 3), (2, 5), (3, 2)]\)
- 脚立昇順: \([2, 3]\)
1回目の収穫(\(L=2\)): 高さ1と2の果物から選べ、おいしさ5を選ぶ → 合計5
2回目の収穫(\(L=3\)): 高さ3の果物(おいしさ2)を選択可能 → 合計7
よって最大値は7。
計算量
- 時間計算量: \(O(N \log N + M \log M)\)
- 果物のソート: \(O(N \log N)\)
- 収穫チャンスのソート: \(O(M \log M)\)
- ヒープ操作(最大でN回追加、M回取り出し): \(O((N + M) \log N)\)
- 空間計算量: \(O(N + M)\)
実装のポイント
Pythonの
heapqは最小ヒープなので、最大ヒープとして使うには要素を負にして管理する。果物の追加と収穫は、ソート順を守って行う必要があるため、二つのリストを事前にソートしておく。
ヒープが空かどうかのチェックを忘れずに(何も取れない場合はパス)。
ソースコード
import heapq
import sys
input = sys.stdin.read
def main():
data = input().split()
N = int(data[0])
M = int(data[1])
fruits = []
idx = 2
for _ in range(N):
D = int(data[idx])
V = int(data[idx+1])
fruits.append((D, V))
idx += 2
L = list(map(int, data[idx:idx+M]))
# 果物を高さDでソート
fruits.sort()
# 収穫チャンスを高さLでソートしたインデックスを取得
sorted_indices = sorted(range(M), key=lambda x: L[x])
# 各収穫チャンスで選べる果物候補を管理するためのヒープ
heap = []
fruit_idx = 0
total_deliciousness = 0
# 高さが低い収穫チャンスから順に処理
for i in sorted_indices:
l = L[i]
# 現在の脚立の高さで届く果物を全てヒープに追加(おいしさを負にして最大ヒープ)
while fruit_idx < N and fruits[fruit_idx][0] <= l:
heapq.heappush(heap, -fruits[fruit_idx][1])
fruit_idx += 1
# その収穫チャンスで最もおいしさの高い果物を選択
if heap:
total_deliciousness += -heapq.heappop(heap)
print(total_deliciousness)
if __name__ == "__main__":
main()
この解説は qwen3-coder-480b によって生成されました。
posted:
last update: