题目地址:
https://www.acwing.com/problem/content/3630/
给定一个长度为 n n n的非负整数序列 a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,…,an。你可以对该序列进行最多 k k k次操作。每次操作选择两个非 0 0 0的元素 a i a_i ai和 a j a_j aj,然后选择一个整数 c c c( 0 ≤ c ≤ a i 0≤c≤a_i 0≤c≤ai),使得 a i a_i ai减少 c c c, a j a_j aj增加 c c c。请问,在操作全部完成后,序列中的最大值和最小值之差是多少。例如,如果初始序列为 [ 5 , 5 , 5 , 5 ] [5,5,5,5] [5,5,5,5],而 k = 1 k=1 k=1,则一种最优方案是将 a 2 a_2 a2减少 5 5 5,将 a 4 a_4 a4增加 5 5 5,得到序列 [ 5 , 0 , 5 , 10 ] [5,0,5,10] [5,0,5,10],这样最大值和最小值之差为 10 10 10。再例如,如果序列中的所有元素都为 0 0 0,则无法进行任何操作,所以最大值和最小值之差也为 0 0 0。
输入格式:
第一行包含整数
T
T
T,表示共有
T
T
T组测试数据。
每组数据第一行包含整数
n
n
n和
k
k
k。
第二行包含
n
n
n个整数
a
1
,
a
2
,
…
,
a
n
a_1,a_2,…,a_n
a1,a2,…,an。
输出格式:
每组数据输出一行,一个整数,表示可以得到的最大差值。
数据范围:
对于前三个测试点,
1
≤
n
≤
10
1≤n≤10
1≤n≤10。
对于全部测试点,
1
≤
T
≤
1000
1≤T≤1000
1≤T≤1000,
1
≤
k
<
n
≤
2
×
1
0
5
1≤k<n≤2×10^5
1≤k<n≤2×105,
0
≤
a
i
≤
1
0
9
0≤a_i≤10^9
0≤ai≤109,每个输入的
T
T
T组数据的
n
n
n之和不超过
2
×
1
0
5
2×10^5
2×105。
要求最大差值,首先,经过 k k k次操作,一定可以让最小值变为 0 0 0,而最大值最多可以变为 a a a的最大 k k k个数之和,而这两者是可以同时取到的。代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 2e5 + 10;
int n, k, a[N];
int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
sort(a + 1, a + 1 + n, greater<int>());
long res = 0;
for (int i = 1; i <= k + 1; i++) res += a[i];
printf("%ld\n", res);
}
}
每组数据时间复杂度 O ( n log n ) O(n\log n) O(nlogn),空间 O ( 1 ) O(1) O(1)。