题意
给你 n 个数。问你这几个数之间所有的差是多少。
思路
比如我给出了三个数,你可以把它想象成一个数轴,这个会求吧,为了方便,排序一下,我们就能对这条数轴进行双指针的操作。使用 while 循环来做,就像这样:
1 2 3
设 1->2 表示 1 到 $ 的距离。
易知,1→2+ 2→3= 1→3。
所以,由于排序后中间的每一个数到两个端点的距离都相等,所以我们可以枚举左右端点,将距离 x 中间点数,即为 (r-l)*a[r]-a[l]。
这个公式怎么证明呢?
拿第一组样例开刀,数据为:
10 1 5
所以排序后为 1 5 10,1 到 5 距离与 5 到 10 距离之和为 1 到 10 距离之和,所以答案为 2* (10-1)。
但是,这是不对的,我们只考虑了一组 l,r,并没有考虑所有的子对 (l,r) ∩l<r。
你们看吧,比如说:
3 5 7 9
按照我们之前的公式,应为 3* (9-3),但是经过(计算器bushi)手算,我们会发现,答案应为 20。为什么呢?我们漏了 5和 7,所以再加上一步,就是求sum {l=1,r=n} ^ {l< r}a[r]-a[l]x(r-l)。
这样就能得出距离了,AC!
最后有个细节,由于 n 和 a_i 的乘积已经远远超出了 int 的最大值,故要开 long long。
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
int l = 1, r = n;
int a[100001];//定义数组
long long sum = 0;//开long long
for (int i = 1; i <= n; i++) {
cin >> a[i];//输入
}
sort(a + 1, a + n + 1);//先排序
while (l < r) {
sum += (r - l) * (a[r] - a[l]);
//套公式就行了
l++;
r--;//下一组l,r
}
cout << sum << endl;//输出
return 0;
}