糖果传递

糖果传递题解

有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

点赞