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;
}
}