1045: [HAOI2008] 糖果传递
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2790 Solved: 1220
[ Submit][ Status][ Discuss]
Description
有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。
Input
小朋友个数n 下面n行 ai
Output
求使所有人获得均等糖果的最小代价。
Sample Input
4
1
2
5
4
1
2
5
4
Sample Output
4
HINT
100% n<=987654321
最终每个小朋友的糖果数很容易求出来,等于平均数,用ave表示。假设编号为i的小朋友开始有Ai个糖果。Xi表示第i个小朋友给了第i-1个小朋友Xi个糖果,Xi<0表示第i-1个小朋友给了第i个小朋友|Xi|个糖果。则最终的答案ans=|X1|+|X2|+……+|Xn|。
对于第一个小朋友,他给了第n个小朋友X1个糖果,得到第2个小朋友的X2个糖果,最终还剩A1-X1+X2个糖果,即ave个糖果,所以得到方程A1-X1+X2=ave。同理可得A2-X2+X3=ave......
所以得到:
X2=ave-A1+X1=X1-C1 (C1=A1-ave)
X3=2ave-A1-A2+X1+X2=X1-C2 (C2=A1+A2-X2-2ave)
X4=3ave-A1-A2-A3+X1+X2+X3=X1-C3 (C3=A1+A2+A3-X2-X3-3ave)
……
所以ans=|X1|+|X1-C1|+|X1-C2|+......+|X1-Cn-1|,要使ans尽可能小。因为|X1-Ci|的几何意义是数轴上点X1到Ci的距离,所以问题转化为:给定数轴上n个点,找出一个点到各点距离和最小。所以这个点就是中位数。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define F(i,j,n) for(int i=j; i<=n; i++)
#define MAXN 1000000
#define LL long long
using namespace std;
int n;
LL a[MAXN],f[MAXN],ave=0,ans=0,mid;
int main()
{
scanf("%d",&n);
F(i,1,n)
{
scanf("%lld",&a[i]);
ave+=a[i];
}
ave/=n;
f[1]=0;
F(i,2,n) f[i]=f[i-1]+a[i-1]-ave;
sort(f+1,f+n+1);
mid=f[n/2+1];
F(i,1,n) ans+=abs(f[i]-mid);
printf("%lld\n",ans);
}