有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。
求使所有人获得均等糖果的最小代价。
输入格式
第一行有一个整数 n ,表示小朋友个数;
在接下来 n行中,每行一个整数 ai。
输出格式
输出使所有人获得均等糖果的最小代价。
样例
输入数据 1:
4
1
2
5
4
输出数据 1:
4
数据范围与提示:
对于 30% 的数据,n≤1000;
对于 100% 的数据,n≤10^6,保证答案可以用 64位有符号整数存储。
分析:
用 64位有符号整数存储:用 long long存储。
每人只能给左右两人传递糖果:看作单向传递,传递个数可为正负数。
a[i]第i个小朋友原本糖果数,s[i]第i个小朋友给第i+1个小朋友的糖果数。
(因为坐成圈,所以s[n]是第n个小朋友给第1个小朋友的糖果)
公式:均数=原本+别人给的-自己给出去的
avg = a[i] + s[i-1] - s[i] ; => s[i] = a[i] + s[i-1] -avg; => s[i] - s[i-1] = a[i] - avg ;
数列 s[i] - s[1] = a[i]+..+a[2] - avg*(i-1)
s[i] =s[1] + a[i]+..+a[2] - avg*(i-1) = s[1] - c[i] =>c[i] = (i-1)*avg - a[2] -...-a[i] = c[i-1] +avg -a[i]
求min(s[1]+...+s[n] ) , 转换为 s[1]到c[i]的距离之和,所以s[1]为c[1]..c[n]的中位数
我们得出了s ss数组,就知道每个人之间的关系,这个时候我们就只需要找一个人为基准值,使他为基准传出去的糖果的总和最小.
#include<iostream>
#include<algrithm>
using namspace std;
long long i,n,weight=0,sum=0,avg,a[1000001],s[1000001],c[1000001];
int main()
{
cin>>n;//
for(i=1;i<=n;i++)
{
cin>>a[i];
sum+=a[i];
}
avg=sum/n;//平均数
c[1]=0;
for(i=2;i<=n;i++)
{
c[i]=c[i-1]+avg-a[i];//
}
sort(c+1,c+n+1);//排序
s[1] = c[n/2+1];//中位数
for(i=1;i<=n;i++)
{
weight + =abs( s[1] -c[i]);//求s[1]到c[i]的距离之和
}
cout<<weight;
return 0;
}