POJ 2231 Moo Volume(递推、前缀和)
题外话:
emm……第三套题好像综合了其他OJ的题目蛤,那么我就把题目分开了发了蛤蛤……
POJ 2231 Moo Volume
题意:
你有一个牛庄,牛庄中总共有n头牛,在晚上,每两头牛都会进行交谈,而交谈的声音的音量就是这两头牛的距离,给出你这n头牛各自的位置,让你求在晚上这些牛发出的总音量。
解题过程:
看了题目发现n有100000,所以暴力是肯定过不了的,那么我们就可以考虑另一种类似公式递推的方法,我们先对所有牛按照位置进行排序,然后假设F[i]表示第i头牛与其他牛交谈发出的总音量,然后对于第i+1头牛,我们设一个d值,代表第i头牛与第i+1头牛之间的距离,那么对于第i+1头牛之前的牛j,与第i+1头牛交谈产生的音量值就是第i头牛与第j头牛交谈的音量+d,同样,对于第i+1头牛之后的牛j,与第i+1头牛交谈产生的音量值就是第i头牛与第j头牛交谈的音量-d,所以我们可以得出递推式F[i+1]=F[i]+d*(i-1)+d*(n-i+1),这样O(n)递推下去就行了,最后把音量值加起来就是所求的答案了。
AC代码:
#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <list>
#include <vector>
#include <cstdlib>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn=100005;
int n;
ll a[maxn];
ll f[maxn];
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%lld",&a[i]);
}
sort(a+1,a+1+n);
for(int i=1;i<=n;i++) {
f[1]+=a[i]-a[1];
}
ll ans=f[1];
for(int i=2;i<=n;i++) {
ll d=a[i]-a[i-1];
f[i]=f[i-1]+d*(i-1)-d*(n-i+1);
ans+=f[i];
}
printf("%lld\n",ans);
return 0;
}
本人蒟蒻OIer一枚,欢迎加QQ:840776708一起学习蛤。
「我不敢下苦功琢磨自己,怕终于知道自己并非珠玉;然而心中既存着一丝希冀,便又不肯甘心与瓦砾为伍。」