1471 C. Strange Birthday Party

https://codeforces.com/contest/1471/problem/C

题意:给你n个朋友和m个礼物,每个礼物都有自己的价格b[j],同时b[j]按礼物出现顺序升序排列,每个朋友都有自己的号码a[i](a[i]<=m)。对于每个朋友,第一中选择是给他b[a[i]]的钱,第二种选择是在j<=a[i]的前提下花a[j]的价钱购买第j个礼物(礼物买了之后就没了,不能重复使用)。怎样才能使你的开销最小?

由于b数组是升序排列,所以我们的策略是设now为1(第一个礼物),对于每个朋友如果b[a[i]]>b[j]我们就做第二种选择,给他买第j个礼物,同时now+1(礼物只能用一次),如果b[a[i]]<a[j]我们就做第一种选择,直接给钱,如果b[a[i]]=b[j]我们还是做第一种选择,因为钱可以随便给,礼物只能用一次。

制定这样的策略之后结果还不是最优的,因为在做第一种选择的时候我们没有做到开销最小, 例如 a:1 2 3 4,b: 1 2 3 4 ,这样我们花费就是1+2+3+4,而如果是a:4 3 2 1,b: 1 2 3 4,话费就是1+2+2+1 。我们发现a如果是降序排列的结果才是最优的,因为a[i]跟b[a[i]]成正比,所以较大的编号我们要尽可能让他做第二种选择,因此要降序排列~

#include <bits/stdc++.h>
using namespace std;
#define qc std::ios::sync_with_stdio(0);
int a[300001], b[300001];

bool cmp(int a, int b) {
	return a > b;
}

int main() {
	qc;
	cin.tie(0);
	int t;
	cin >> t;
	while (t--) {
		long long ans = 0;
		int n, m;
		cin >> n >> m;
		for (int i = 1; i <= n; i++)
			cin >> a[i];
		for (int i = 1; i <= m; i++)
			cin >> b[i];
		sort(a + 1, a + n + 1, cmp);
		int now = 1;
		for (int i = 1; i <= n; i++) {
			if (a[i] >= now) {
				ans += b[now];
				now++;
			} else
				ans += b[a[i]];
		}
		cout << ans << endl;
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值