码迷,mamicode.com
首页 > 其他好文 > 详细

糖果传递

时间:2019-10-28 19:22:03      阅读:104      评论:0      收藏:0      [点我收藏+]

标签:比较   i++   获得   main   https   span   sum   pre   cpp   

https://loj.ac/problem/10010

题目描述

??有\(n\)个小朋友坐成一圈,每人有\(a_i\)颗糖果。每人只能给左右两人传递糖果。每人每次传递一颗糖果的代价为\(1\)。求使所有人获得均等糖果的最小代价。

思路

??个人感觉这道题的贪心策略还是比较难想的,刚开始没有任何思路。首先我们设平均数为\(average\)\(p_i\)表示 \(i\)\(i - 1\) 的糖果数。所以可以得到以下几个等式:

??\(a_1 + p_2 - p_1=average\)

??\(a_2 + p_3 - p_2=average\)

??\(a_3 + p_4 - p_3=average\)

??\(……\)

??那么我们把它们化简:

??\(p_2 = p_1 + average - a_1\)

??\(p_3 = p_2 + average - a_2 = p_1 + 2*average - a_1 - a_2\)

??\(p_4 = p_3 + average - a_3 = p_1 + 3*average - a_1 - a_2 -a_3\)

??\(……\)

??我们再设\(x_i = i*average - \sum_{j=1}^{i}{a[j]}\)

??那么我们求得就是\(ans=| p_1 | + | p_1 - x_1 |+| p_1 - x_2 |+……| p_1-x_n|\)

??这就是求\(p_1\)\(x_1,x_2,……,x_n\)这几个点的距离和,那么\(p_1\)的值即为这\(n\)个数的中位数

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[1010000],x[1010000];
int main() 
{
    ll n,sum=0;
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        sum+=a[i];
    }
    sum=sum/n;
    ll ans=0;
    for(int i=1;i<=n;i++)
        x[i]=x[i-1]+sum-a[i];
    sort(x+1,x+n+1);
    int k=x[(n+1)/2];
    for(int i=1;i<=n;i++)
        ans+=abs(k-x[i]);
    printf("%lld",ans);
    return 0;
}

糖果传递

标签:比较   i++   获得   main   https   span   sum   pre   cpp   

原文地址:https://www.cnblogs.com/fangbozhen/p/11754325.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!