C - 特売セールの選択 / Bargain Sale Selection 解説 by admin
GPT 5.2 High概要
各商品を「通常価格で買う」か「クーポンでセール価格にする」かを選び、クーポンを使える最大 \(K\) 個の範囲で合計金額を最小化します。
考察
クーポンを使うと、商品 \(i\) の支払いは \(A_i\) から \(B_i\) に下がります。つまり「いくら安くなるか」は
\(A_i - B_i\) 円です。
ここで重要な観察は次の通りです:
- まず全商品を通常価格で買うと合計は \(\sum A_i\)。
- そこから、クーポンを使った商品分だけ \((A_i - B_i)\) 円ずつ合計が減る。
- よって「合計を最小にする」ことは「値引き額 \((A_i - B_i)\) の合計を最大化する」ことと同値。
したがって、クーポンを使う商品は「値引き額が大きい順」に最大 \(K\) 個選ぶのが最適です。
素朴に「どの商品にクーポンを使うか」を全探索すると、選び方は最大で \(\binom{N}{K}\) 通りあり、\(N \le 2\times 10^5\) では到底間に合いません(TLE)。
この問題は各商品の効果(値引き額)が独立で、相互作用がないため、貪欲に大きい値引きから選べばよい、という形に落とし込めます。
例: - \((A,B)=(10,7),(8,3),(5,5)\)、\(K=2\) - 値引き額は \(3,5,0\) - 大きい順に \(5,3\) を選ぶ → 合計は \((10+8+5) - (5+3)=23-8=15\)
アルゴリズム
- 合計
totalを \(\sum A_i\) として計算する。 - 各商品について値引き額
s = A_i - B_iを配列savingsに入れる。 savingsを降順ソートする。- 上位 \(K\) 個の値引き額の合計 \(\sum_{j=1}^{K} savings[j]\) を
totalから引く。 totalを出力する。
(\(K=0\) のときは何も引かず、そのまま \(\sum A_i\))
計算量
- 時間計算量: \(O(N \log N)\)(値引き額のソートが支配的)
- 空間計算量: \(O(N)\)(値引き額の配列)
実装のポイント
\(A_i, B_i\) は最大 \(10^9\)、\(N\) は最大 \(2\times 10^5\) なので、合計は最大で約 \(2\times 10^{14}\) になります。Python なら整数は自動で大きくなるので安全ですが、他言語では 64bit 整数が必要です。
savings.sort(reverse=True)で降順にし、sum(savings[:K])で上位 \(K\) 個だけを足します。入力が大きいので
sys.stdin.readlineを使うと安定します。ソースコード
import sys
def main():
input = sys.stdin.readline
N, K = map(int, input().split())
total = 0
savings = []
for _ in range(N):
A, B = map(int, input().split())
total += A
savings.append(A - B)
savings.sort(reverse=True)
total -= sum(savings[:K])
print(total)
if __name__ == "__main__":
main()
この解説は gpt-5.2-high によって生成されました。
投稿日時:
最終更新: