B - 観光地選び / Choosing Tourist Spots Editorial by admin
Claude 4.6 Opus (Thinking)概要
各観光地の「評価値(お土産の満足度の中央値)」を求め、その中から正の評価値を持つ観光地を最大 \(K\) 箇所まで選んで合計を最大化する問題です。
考察
重要な気づき①:評価値は中央値
各観光地 \(i\) の評価値は、\(C_i\) 個のお土産の満足度を昇順に並べたときの \(\frac{C_i+1}{2}\) 番目の値、つまり中央値です。\(C_i\) は必ず奇数なので、中央値は一意に決まります。
具体例: お土産の満足度が \([3, -1, 5]\) の場合、昇順に並べると \([-1, 3, 5]\) となり、中央値(2番目の値)は \(3\) です。
重要な気づき②:貪欲に正の評価値を選べばよい
- 0箇所以上 \(K\) 箇所以下を選べるので、訪れない選択肢もあります。
- 評価値が負の観光地を訪れると合計が減ってしまうため、評価値が正の観光地だけを選ぶべきです。
- 評価値が0の観光地は選んでも合計に影響しないため、選んでも選ばなくてもよいです(選ばなくてよい)。
- 正の評価値を持つ観光地が \(K\) 箇所以上あれば、大きい方から \(K\) 箇所選びます。\(K\) 箇所未満であれば、正の評価値を持つ観光地をすべて選びます。
素朴なアプローチとの比較
\(N\) 箇所から \(0\) 〜 \(K\) 箇所選ぶ全組合せを試すと最悪 \(2^N\) 通りで、\(N=100\) では到底間に合いません。しかし、上記の貪欲法により、ソートして上位を取るだけで最適解が得られます。
アルゴリズム
- 各観光地 \(i\) について、\(C_i\) 個の満足度を昇順ソートし、中央値(インデックス \(C_i // 2\) の要素)を求める。
- 全観光地の中央値のうち、正のもの(\(> 0\))だけを集める。
- 集めた正の中央値を降順にソートし、先頭から最大 \(K\) 個の合計を求める。
- その合計が答え(正の中央値がなければ \(0\))。
具体例: \(N=3, K=2\) で、各観光地の評価値が \([5, -3, 2]\) の場合、正の評価値は \([5, 2]\)。\(K=2\) 箇所まで選べるので、両方選んで合計 \(7\) が答えです。
計算量
- 時間計算量: \(O\!\left(\sum_{i=1}^{N} C_i \log C_i + N \log N\right)\)
- 各観光地のお土産をソートするコスト \(O(C_i \log C_i)\) と、中央値をソートするコスト \(O(N \log N)\) の合計です。
- 空間計算量: \(O\!\left(\max_i C_i + N\right)\)
- 各観光地のお土産リストと、中央値リストの格納に必要です。
実装のポイント
中央値のインデックス: \(C_i\) 個の要素を0-indexedで昇順ソートしたとき、中央値は
V[C_i // 2]です。例えば \(C_i = 5\) ならV[2](3番目の要素)。0箇所選ぶ場合を忘れない: 全ての評価値が負の場合、1箇所も訪れず合計 \(0\) が最大です。正の評価値だけを集めることで、この場合は自然に合計が \(0\) になります。
評価値が0の観光地: 選んでも合計は変わらないため、実装では
m > 0のフィルタで除外しても問題ありません。ソースコード
import sys
def main():
input_data = sys.stdin.read().split()
idx = 0
N = int(input_data[idx]); idx += 1
K = int(input_data[idx]); idx += 1
medians = []
for i in range(N):
C = int(input_data[idx]); idx += 1
V = []
for j in range(C):
V.append(int(input_data[idx])); idx += 1
V.sort()
median = V[C // 2]
medians.append(median)
# Select up to K spots with positive medians to maximize sum
positive_medians = sorted([m for m in medians if m > 0], reverse=True)
result = sum(positive_medians[:K])
print(result)
main()
この解説は claude4.6opus-thinking によって生成されました。