【Jason's_ACM_解题报告】Spreading the Wealth

Spreading the Wealth

A Communist regime is trying to redistribute wealth in a village.  They have have decided to sit everyone around a circular table.  First, everyone has converted all of their properties to coins of equal value, such that the total number of coins is divisible by the number  of people in the village.  Finally, each person gives a number of coins to the person on his right and a number coins to the person on his left, such that in the end, everyone has the same number of coins.  Given the number of coins of each person,  compute the minimum number of coins that must be transferred using this method so that everyone has the same number of coins. 


Input

There is a number of inputs. Each input begins with n(n<1000001), the number of people in the village. nlines follow, giving the number of coins of each person in the village, in counterclockwise order around the table. The total number of coins will fit inside an unsigned 64 bit integer.


Output

For each input, output the minimum number of coins that must be transferred on a single line.


Sample Input

3

100

100

100

4

1

2

5

4


Sample Output

0

4


美丽的Doris小妹妹告诉我,当点的数量是偶数的时候中位数是可以取两只之间的任何数的,包括两点又不仅仅局限于两点。

先证:当点数为偶数时中位数可以取中间两点的任意一点

假设有x1,x2,x3,x4四点(已经排好序),我们取中位数为(x2+x3)/2那么中位数向左移动到x2时移动了d距离,那么左边两点减少2d,右边两点增加2d,结果仍然不增不减,所以当点数为偶数时中位数可以取中间两点中的任意一点。

再证:当点数为偶数时中位数可以取中间两点的任意一点

由于代数分析的过程与数学模型建立的过程没有直接联系,所以可以完全的站在数学模型的角度上观察此问题,所以不影响结果。

此题应用了一个经典模型——中位数累加距离模型。通过递推的方法求解,涵盖了代数分析手法,值得学习。有兴趣的可以自行Google。

(注意:Unix/Linux环境下请使用lld ;Win环境下请使用I64d。)


附代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

#define ll long long
#define MAXN 1000000+5

ll A[MAXN],C[MAXN];

int main()
{
	int n;
	while(scanf("%d",&n)!=EOF){
		ll tot=0;
		memset(A,0,sizeof(A));
		memset(C,0,sizeof(C));
		
		for(int i=0;i<n;i++){
			scanf("%lld",&A[i]);
			tot+=A[i];
		}
		ll M=tot/n;
		for(int i=1;i<n;i++) C[i]=C[i-1]+A[i]-M;
		sort(C,C+n);
		ll x=C[n/2];
		ll ans=0;
		for(int i=0;i<n;i++) ans+=abs(x-C[i]);
		printf("%lld\n",ans);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值