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
",ans);
    return 0;
}

本人蒟蒻OIer一枚,欢迎加QQ:840776708一起学习蛤。

「我不敢下苦功琢磨自己,怕终于知道自己并非珠玉;然而心中既存着一丝希冀,便又不肯甘心与瓦砾为伍。」
原文地址:https://www.cnblogs.com/Apocrypha/p/9433672.html