题意:Lee有n个整数a1,a2,...,an在他的背包里面,并且他有k个朋友。Lee把它的背包里面的整数分发给k个朋友,第i个朋友会获得wi个整数,每个整数只会属于一个人。让我们定义一个朋友的幸福度为他得到的数中的最小值和最大值的和。
Lee想让他的朋友的幸福度尽量最大,最大化朋友的幸福值的总和,求计算所有朋友的幸福值的总和。
分析:这是道贪心题,我们先看一下数据范围,(1 <= wi <= n),也就是存在wi等于1的,那么我们可以把w中为1的个数取出来,将a数组排个序,然后最大值每个取出来,直到没有1,*2加到答案里。然后我们看看wi >= 2的怎么处理,可以让答案尽量最大,我们先把w从大到小排序,我们的最大值取a数组排过序的最大值,最小值取末尾,开两个变量p1,p2指向开头和末尾,每次末尾的指针变量向前挪动w[i] - 2个位置,这样可以接下来的朋友的最小值尽量往前靠,就是最优的答案。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
using LL = long long;
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
int n, k;
scanf("%d%d", &n, &k);
vector<LL> v(n);
for (int i = 0; i < n; ++i)
scanf("%lld", &v[i]);
vector<int> w(k);
for (int i = 0; i < k; ++i)
scanf("%d", &w[i]);
sort(v.begin(), v.end(), greater<int>());
sort(w.begin(), w.end());
LL res = 0;
int i;
for (i = 0; i < k; ++i)
{
if (w[i] != 1) break;
else
{
res += v[i] * 2;
}
}
sort(w.begin() + i, w.end(), greater<int>());
int p1 = i, p2 = n - 1;
for (i; i < k; ++i)
{
res = res + v[p1] + v[p2];
++p1;
p2 = p2 - (w[i] - 2) - 1;
}
printf("%lld
", res);
}
return 0;
}