1. 问题描述:
给定一个长度为 n 的非负整数序列 a1,a2,…,an。你可以对该序列进行最多 k 次操作。每次操作选择两个非 0 的元素 ai 和 aj,然后选择一个整数 c(0 ≤ c ≤ ai),使得 ai 减少 c,aj 增加 c。
请问,在操作全部完成后,序列中的最大值和最小值之差是多少。例如,如果初始序列为 [5,5,5,5] 而 k = 1,则一种最优方案是将 a2 减少 5,将 a4 增加 5,得到序列 [5,0,5,10],这样最大值和最小值之差为 10。再例如,如果序列中的所有元素都为 0,则无法进行任何操作,所以最大值和最小值之差也为 0。
输入格式
第一行包含整数 T,表示共有 T 组测试数据。每组数据第一行包含整数 n 和 k。第二行包含 n 个整数 a1,a2,…,an。
输出格式
每组数据输出一行,一个整数,表示可以得到的最大差值。
数据范围
对于前三个测试点,1 ≤ n ≤ 10。
对于全部测试点,1 ≤ T ≤ 1000,1 ≤ k < n ≤ 2 × 10 ^ 5,0 ≤ ai ≤ 10 ^ 9,每个输入的 T 组数据的 n 之和不超过 2 × 10 ^ 5。
输入样例:
2
4 1
5 5 5 5
3 2
0 0 0
输出样例:
10
0
来源:https://www.acwing.com/problem/content/description/3630/
2. 思路分析:
分析题目可以知道每一次我们需要选择两个数字进行操作使得序列中的最大值与最小值的差最大,所以关键是选择哪两个数字进行操作,可以发现我们操作一次的最小值一定是0,而每一次一个数字加上的是选择的另外一个数字,所以要想使得差值最大那么选择的其中一个数字一定是序列中的最大值,另外一个数字肯定是当前还未选择的数字的最大值,每操作一次就有一个元素变为0,所以我们可以先对序列从大到小进行排序,将序列的前缀和计算到mp中,那么第一次操作的结果为mp[0],第二次操作的结果为mp[2],...第k次操作的结果为mp[k - 1],返回对应位置的结果即可。
3. 代码如下:
class Solution:
def process(self):
T = int(input())
while T > 0:
n, k = map(int, input().split())
a = list(map(int, input().split()))
# 从大到小排序
a.sort(reverse=True)
mp = list()
s = a[0]
if s != 0:
for i in range(1, n):
s += a[i]
mp.append(s)
# 按照字典的键从小到大排序
if len(mp) == 0: print(0)
else: print(mp[k - 1])
T -= 1
if __name__ == '__main__':
Solution().process()