AcWing 913. 排队打水
有 n n n 个人排队到 1 1 1 个水龙头处打水,第 i i i 个人装满水桶所需的时间是 t i t_{i} ti,请问如何安排他们的打水顺序才能使所有人的等待时间之和最小?
输入格式
第一行包含整数 n n n。
第二行包含 n n n 个整数,其中第 i i i 个整数表示第 i i i 个人装满水桶所花费的时间 t i t_{i} ti
输出格式
输出一个整数,表示最小的等待时间之和。
数据范围
1
≤
n
≤
1
0
5
1 \leq n \leq 10^{5}
1≤n≤105
1
≤
t
i
≤
1
0
4
1 \leq t_{i} \leq 10^{4}
1≤ti≤104
思路
将时间按照从小到大的顺序排队,总时间最小
证明:反证法
假设 t i > t i + 1 t_{i} > t_{i+1} ti>ti+1
有 t i ∗ ( n − i ) + t i + 1 ∗ ( n − i − 1 ) t_{i}*(n-i) + t_{i+1}*(n-i-1) ti∗(n−i)+ti+1∗(n−i−1)①
交换 t i t_{i} ti和 t i + 1 t_{i+1} ti+1 有 t i + 1 ∗ ( n − i ) + t i ∗ ( n − i − 1 ) t_{i+1}*(n-i)+t_{i}*(n-i-1) ti+1∗(n−i)+ti∗(n−i−1)②
①-②得 t i − t i + 1 t_{i} - t_{i+1} ti−ti+1 而 t i > t i + 1 t_{i} > t_{i+1} ti>ti+1 ∴ \therefore ∴交换后总时间变小
若想使总时间最小 则 t i t_{i} ti应该从小到大排序 即 t i < t i + 1 t_{i}<t_{i+1} ti<ti+1
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 100010;
int a[N], n;
int main() {
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
scanf("%d", &a[i]);
}
sort(a, a + n);
LL res = 0;
for (int i = 0; i < n; ++i)res += a[i] * (n - i - 1);
cout << res << endl;
return 0;
}