# ACwing 122. 糖果传递(数学 + 贪心)

题意

在这里插入图片描述
在这里插入图片描述

思路

假设\(n=4\),每个人的糖果数为\(a_1,a_2,a_3,a_4\)\(A_i\)表示第\(i\)个人给第\(i+1\)个人的糖果数(正表示给,负表示获得),那么可以表示成:

\(a_1 + A_4 - A_1 = ave \\ a_2 + A_1 - A_2 = ave \\ a_3 + A_2 - A_3 = ave \\ a_4 + A_3 - A_4 = ave\)

\(A_i\)全部使用\(A_4\)表示:

\(A_1 = A_4 - (ave-a_1) \\ A_2 = A_4 - (2 * ave-(a_1+a_2)) \\ A_3 = A_4 - (3 * ave-(a_1 + a_2 + a_3) ) \\ A_4 = A_4 - 0\)

题目要求的就是求\(|A_1| + |A_2| + |A_3| + |A_4|\)的最小值,那么就可以理解为\((ave-a_1)\)\(2*ave-(a_1+a_2)\)\(3*ave - (a_1 + a_2 + a_3)\) , 0为数轴上的四个点,在数轴上选择一个点\(A_4\)使得这个点到其他点的距离之和最小,这就是典型的中位数问题了。

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
int a[maxn];
int n;
long long sum;
int main(){
    cin>>n;
    sum=0;

    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum+=a[i];
    }
    
    long long ave=sum/n;
    long long pre=0;
    
    for(int i=0;i<n;i++){
        pre+=a[i];
        a[i]=ave*i-pre;
    }
    
    sort(a,a+n);
    long long t=a[n/2];
    long long ans=0;
    for(int i=0;i<n;i++){
        ans+=abs(a[i]-t);
    }
    
    cout<<ans<<endl;
    return 0;
}
posted @ 2020-07-14 10:49  yhsmer  阅读(153)  评论(0编辑  收藏  举报