糖果传递题解
有n个小朋友坐成一圈,每人有a[i]个糖果。
每人只能给左右两人传递糖果。
每人每次传递一个糖果代价为1。
求使所有人获得均等糖果的最小代价。
输入格式
第一行输入一个正整数n,表示小朋友的个数。
接下来n行,每行一个整数a[i],表示第i个小朋友初始得到的糖果的颗数。
输出格式
输出一个整数,表示最小代价。
数据范围
1≤n≤1000000
输入样例:
4
1
2
5
4
输出样例:
4
分析:
多个考点综合的问题,感觉像一道数学题。
对于每个人,假设他的糖果数要经过两类变化:1、从后一个人拿。2、给前一个人
最终的变化结果是变为ave。
所以有
- a[1]-X1+X2=ave X2=X1-(a[1]-ave)
- a[2]-X2+X3=ave X3=X1-(a[2]+a[1]-2*ave)
设c[1]=a[1]-ave
c[2]=c[1]+a[2]-ave
则有c[i]=c[i-1]+a[i]-ave
则有问题|X1|+|X2|+……+|Xn|的和最小每个都可以用X1表示为
|X1|+|X1-c[1]|+|X2-c[2]|+……+|X1-c[n-1]|
绝对值的含义又可以表示数轴上Xi到Ci的距离
所以问题转化为在c[1]到c[n-1]中选一个点到所有点的距离的和最短
(即中位数)
注意:不应该加上abs(c[n]-c[mid]),并且ans最后应该加上mid
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e6+5;
int a[N],c[N];
int main()
{
int n;
cin>>n;
LL sum=0;//记得初始化为0
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum+=a[i];
}
int ave=sum/n;
for(int i=1;i<n;i++)
{
c[i]=c[i-1]+a[i]-ave;
}
sort(c+1,c+n);//c[0]=0不能参与排序影响结果
LL ans=0;
int pos=n>>1;
for(int i=1;i<n;i++)
{
ans+=abs(c[pos]-c[i]);
}
ans+=abs(c[pos]);
cout<<ans<<endl;
return 0;
}
3.11