【HAOI 2008】1.糖果传递

有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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值