yokobuttonの不定期で競技プログラミングをするブログ

不定期で解けた競技プログラミングコンテストの問題を載せています。

AtCoder Beginner Contest 246 C - Coupon

問題の要約
 N個の商品がある。i=1,...,Nについて、i番目の商品の値段はAi円。
 今、K枚のクーポンを持っている。
 1枚のクーポンは1つの商品に対して使用することができ、1つの商品に対してはクーポンを何枚でも(0枚でもよい)使用することができる。
 値段がa円の商品に対してk枚のクーポンを使用すると、その商品をmax{a-kX,0}円で買うことができる。
 すべての商品を買うために支払う合計金額の最小値を出力せよ。
制約
 1<=N<=2*10^5
 1<=K,X<=10^9
 1<=Ai<=10^9
入力
 N K X
 A1 ... AN
考え方
 1,a<=Xのような場合、そのようなどの商品に対してクーポンを使っても最小値は変わらない。
  よって、X<aとなるように全ての商品にクーポンを使っていく。
 2,この時点で全ての商品はX<aである。このとき、aがXに近い値(すなわちより高い値段)の商品にクーポンを使った方が合計金額が小さいくなる。
  よって、全ての商品を降順でソートして、順にクーポンを使っていく。
 3,合計金額を計算して、出力する。

実際のプログラム
#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

int main(){
  long long N,K,X;
  cin >> N >> K >> X;
  vector<long long> A(N);
  for(long long i = 0; i < N; ++i){
    cin >> A[i];
  }
  
  for(long long i = 0; i < N; ++i){
    long long k = A[i] / X;
    if(k != 0){
      A[i] = A[i] - min(k,K) * X;
      K -= min(k,K);
    }
  }
  
  sort(A.begin(),A.end());
  reverse(A.begin(),A.end());
  
  for(long long i = 0; i < N; ++i){
    if(K != 0){
      A[i] -= A[i];
      K--;
    }
  }
  
  long long ans = 0;
  for(long long i = 0; i < N; ++i){
    ans += A[i];
  }
  
  cout << ans << endl;
  
  return 0;
}