题目描述
数轴上有N个点,任意两点连线得到n(n-1)条线段,试求线段的总长。
输入
第一行,一个整数N,表示点数。 接下来N行,每行一个整数X_i,表示点的坐标。
输出
一个整数,表示线段的总长。
样例输入
5 1 5 3 2 4
样例输出
40
提示
N < = 10000 , 0 < = X_i < = 1000000000
从X_i看出来,他的数据应该为10^9,所以一定要考虑long long,用上long long后,期初的想法就是扫一遍,然后O(n2)就能结果,当时担心着T,但是没有T,
过了后,又想到了另外一种简单的O(n)算法、先写出来O(n2)的方法了:
# include<cstdio>
# include<iostream>
# include<algorithm>
using namespace std;
# define MAX 10000+5
long long a[MAX];
int main(void)
{
int n;
while ( cin>>n )
{
for ( int i = 0;i < n;i++ )
{
cin>>a[i];
}
sort(a,a+n);
long long sum = 0;
for ( int i = 0;i < n-1;i++ )
{
for ( int j = i+1;j < n;j++ )
{
sum+=a[j]-a[i];
}
}
cout<<2*sum<<endl;
}
return 0;
}
O(n)的算法思想就是算排完序后的点对于答案的贡献程度了,并且发现了,第一个点与后面的点的连线对于答案的贡献恰好满足前缀和:
# include<cstdio>
# include<iostream>
# include<algorithm>
using namespace std;
# define MAX 10000+5
long long a[MAX];
long long sa[MAX];
int main(void)
{
int n;
while ( cin>>n )
{
for ( int i = 1;i <= n;i++ )
{
cin>>a[i];
}
sort(a+1,a+1+n);
for ( int i = 1;i <= n;i++ )
{
sa[i] = sa[i-1]+a[i];
}
long long sum = 0;
for ( int i = 1;i <= n;i++ )
{
sum+=sa[n]-sa[i-1]-a[i]*(n+1-i);
}
cout<<sum*2<<endl;
}
return 0;
}