B - お菓子選びコンテスト / Candy Selection Contest 解説 by admin
Gemini 3.0 Flash概要
\(N\) 種類のお菓子の中から \(K\) 個を選び、それらの「満足度」(基本の美味しさ \(T_i\) + 好み補正値 \(C_i\))の合計を最大化する問題です。
考察
この問題で最も重要なポイントは、各お菓子の評価値が \(T_i\) と \(C_i\) の和という単一の数値で決まるという点です。
高橋君は合計の満足度を最大化したいと考えています。あるお菓子 \(i\) を選んだときに得られる満足度は \(S_i = T_i + C_i\) と計算できます。 複数の項目からいくつかを選んでその合計を最大化する場合、「単体での値が大きいものから順番に選ぶ」という貪欲な戦略が最適となります。
例えば、以下のようなお菓子がある場合を考えます(\(K=2\)): - お菓子1: \(T_1=10, C_1=5 \Rightarrow S_1=15\) - お菓子2: \(T_2=20, C_2=-10 \Rightarrow S_2=10\) - お菓子3: \(T_3=5, C_3=15 \Rightarrow S_3=20\)
この場合、満足度 \(S_i\) は順に \(15, 10, 20\) となります。合計を最大にするには、満足度が高い「お菓子3 (20)」と「お菓子1 (15)」の 2 つを選ぶのがベストです。
したがって、以下の手順で解くことができます: 1. すべてのお菓子について、満足度 \(S_i = T_i + C_i\) を計算する。 2. 計算した満足度を値の大きい順(降順)に並べ替える。 3. 上位 \(K\) 個の満足度を合計する。
アルゴリズム
- 入力の受け取り: \(N, K\) および各お菓子の \(T_i, C_i\) を読み込みます。
- 満足度の計算: 各 \(i\) について \(S_i = T_i + C_i\) を計算し、リストに格納します。
- ソート: リストを降順(大きい順)にソートします。
- 合計の算出: ソートされたリストの先頭から \(K\) 個の要素の和を求め、出力します。
計算量
- 時間計算量: \(O(N \log N)\)
- 満足度の計算に \(O(N)\)、ソートに \(O(N \log N)\)、上位 \(K\) 個の合計計算に \(O(K)\) かかります。全体ではソートの計算量が支配的になります。\(N = 2 \times 10^5\) であるため、この計算量で制限時間内に十分間に合います。
- 空間計算量: \(O(N)\)
- \(N\) 個のお菓子の満足度を保持するためのリストが必要です。
実装のポイント
高速な入力: \(N\) が最大 \(2 \times 10^5\) と大きいため、Python では
sys.stdin.read().split()を使って一括で入力を読み込むと処理が高速になります。ソートの順序:
sort(reverse=True)を指定することで、簡単に大きい順に並べ替えることができます。スライスと合計:
sum(satisfactions[:K])のようにスライスを用いることで、上位 \(K\) 個の合計を簡潔に記述できます。ソースコード
import sys
def solve():
# 標準入力からすべてのデータを読み込み、空白(スペースや改行)で分割してリストにします
# 競技プログラミングにおいて、大量の入力を高速に処理する一般的な手法です
input_data = sys.stdin.read().split()
# 入力が空の場合は終了します
if not input_data:
return
# 文字列のリストを整数のリストに一括変換します
# map関数をlistで包むことで、高速に変換処理が行われます
data = list(map(int, input_data))
# 1つ目の要素が種類数 N、2つ目の要素が選ぶ個数 K です
N = data[0]
K = data[1]
# 各お菓子の満足度(T_i + C_i)を計算します
# T_i と C_i のペアはインデックス2から始まります
# i番目のお菓子の T_i は data[2 + 2*i]、C_i は data[3 + 2*i] に位置します
satisfactions = [data[i] + data[i+1] for i in range(2, 2 * N + 2, 2)]
# 満足度が高い順にお菓子を選ぶため、降順(大きい順)にソートします
satisfactions.sort(reverse=True)
# 上位 K 個の満足度の合計を計算して出力します
# Pythonのスライス([:K])とsum関数を組み合わせることで効率的に合計を求められます
print(sum(satisfactions[:K]))
if __name__ == '__main__':
solve()
この解説は gemini-3-flash-preview によって生成されました。
投稿日時:
最終更新: