1045: [HAOI2008] 糖果传递
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2958 Solved: 1319
[ 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
Source
贪心,
从线性的均分纸牌出发、令a[i]为纸牌树,k为每堆的目标牌数、
记p[i]=k-a[i]+p[i-1] 含义就是第i堆需要从后一堆拿的纸牌、
那么对p数组求和就是答案了、
对这个环形的、我们这样考虑、
记sum[i]=sigma(p[j]-p[j-1]) j<=i 那么可以得到p[1]=p[i]-sum[i] 即 p[i]=sum[i]+p[1]
又因为最后的答案ans=sigma p[i]=sigma (s[i]+p[1]) 即数轴上s数组的点到-p[1]的距离之和、
而s数组中的值的集合在取任一点为起点的时候都是不变的、
所以当p[1]为该数组中的中位数时ans最小;
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
long long a[1000050],i,j,k,l,m,n;
long long Abs(long long a,long long b)
{
if(a>b)
return a-b;
return b-a;
}
int main()
{
while(scanf("%lld",&m)!=EOF)
{
long long sum=0;
for(i=0;i<m;i++)
{
scanf("%lld",&k);
sum+=k;
a[i]=sum;
}
long long mid=sum/m;
for(i=0;i<m;i++)
a[i]-=mid*(i+1);
sort(a,a+m);
l=a[m/2];
long long ans=0;
for(i=0;i<m;i++)
ans+=Abs(a[i],l);
printf("%lld\n",ans);
}
}