旅行(travel)

时间:2024-06-10 07:03:12

旅行

题目描述

暑假又到了,小A同学要进行 N 天的旅行,旅行社收费方案是按天收,即第 i 天的费用为 A i A_i Ai ,当然假期旅行社搞活动推出了优惠券,你买了优惠券可以优惠 D 天(不一定连续)的费用,优惠后的价格为 P。如果剩余 2 天,优惠券的作用是 3 天,那么依然可以使用。
小A同学如何做才能在这 N 天旅行中花费最小呢?

输入格式

第一行有 3 个整数 N,D,P。

第二行有 N 个整数,第 i 个为 Ai。

输出格式

1 个整数,如题意。

样例 #1

样例输入 #1

5 2 10
7 1 6 3 6

样例输出 #1

20

样例 #2

样例输入 #2

3 1 10
1 2 3

样例输出 #2

6

样例 #3

样例输入 #3

8 3 1000000000
1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000 1000000000

样例输出 #3

3000000000

提示

1 < = N < = 2 ∗ 1 0 5 1<=N<=2*10^5 1<=N<=2105

1 < = D < = 2 ∗ 1 0 5 1<=D<=2*10^5 1<=D<=2105

1 < = P < = 1 0 9 1<=P<=10^9 1<=P<=109

1 < = A i < = 1 0 9 1<=Ai<=10^9 1<=Ai<=109

样例一解释

使用一张优惠券优惠 1,3 天的费用,总费用为 ( 10 × 1 ) + ( 0 + 1 + 0 + 3 + 6 ) = 20 (10×1)+(0+1+0+3+6)=20 (10×1)+(0+1+0+3+6)=20

样例二解释

不使用优惠

样例三解释

最低成本是通过购买 3 张优惠券并使用。

1000000000 × 3 = 3000000000。

/*
首先将数组从大到小排序,将其每隔 D 个元素分为一段,如果每一段的所有元素的和小于或等
于
P,就购买正常车票,也就是花费所有元素的和的价钱,否则花费 P 元购买可以使用 D 天的周游
票。
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
using ll= long long;
ll n, d, p, f[N];
int main() {
	cin >> n >> d >> p;
	for (int i = 1; i <= n; i++) {
		cin >> f[i];
	}
	sort(f + 1, f + 1 + n);
	ll ans = 0, c = 0, sum = 0;
	for (int i = n; i >= 1; i--) {//从花费多的开始
		sum += f[i];
		c++;
		if (c == d) {//分成多段,每段 d 个
//小于或等于 P,就购买正常车票,也就是花费所有元素的和的价钱,否则花费 P
			元购买可以使用 D 天的周游票
			ans += min(p, sum);
			c = 0;
			sum = 0;
		}
	}
	if (c > 0) ans += min(p, sum);//处理 n%d
	cout << ans << endl;
	return 0;
}