Money
Submit Page Time Limit: 1 Sec Memory Limit: 128 Mb Submitted: 11 Solved: 8
Description
ZJ开公司,年年荣登315晚会。
315当天,一大帮员工来ZJ公司讨工资。(显然又欠工资了囧)。
员工们围成一个圈,把ZJ围在中间,打算用暴力手段讨取工资。
机智如ZJ早就料到这种情况了,所以ZJ身上带了钱。为了拖延时间,ZJ故意把钱不平衡地分给每个员工,这样,员工们就会因为分钱的事耽误时间。而ZJ就可以乘机逃跑了。。。
员工们的钱不平衡了,他们很不高兴。所以他们要开始交换钱。I的钱只能给I+1或者I-1。(1号的可以给n号,n号也可以给1号)。传递一块钱的时间是1s。
QQtan作为员工首领见状,立刻想出了办法,使传递的钱的数量最少(每秒钟只允许一个人传递1块钱,ZJ给钱的时间不算在内)。
你作为ZJ公司的首席程序猿,需要告诉ZJ,他有多少时间用来逃跑。
Input
第一行n,员工数量 第2行到n+1行,整数a[i] 每个员工已经拿到的钱。 N<=1000000
Output
一个整数,ZJ还有多久可以逃跑。
Sample Input
4
1
2
5
4
Sample Output
4
详见白书题目。
设 i 初始金钱为 ai,可算出每人应得的平均钱数M。
设 xi 为 i 给 i-1 的金币数,那么就可以列出n-1个有效方程(第n个可以由前n-1个推导出来):
ai + x(i+1) - xi = M;( 1 <= i <n )
x2 = x1 - a1 + M = x1 - C1(C1=a1-M,Ci = (a1+……+ai)- i*M);
……
xi+1 = xi - Ci;( 1 <= i < n )
所求应为|x1|+……+|xi|+……+|xn| = |x1| + |x1-C1| +……+ |x1-C(i-1)| +…… + |x1-C(n-1)|,可看作n个点到x1的距离和,x1应为其中某点,使其最小即找0,C1……C(n-1)的中位数。
很玄妙。
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int maxn=1e6+10;
int n;
long long m=0;
long long a[maxn],c[maxn];
long long ans=0;
int main()
{
scanf("%d",&n);
for(int i=0;i<n;++i){
scanf("%lld",&a[i]);
m+=a[i];
}
m/=n;
c[0]=0;
for(int i=1;i<n;++i){
c[i]=c[i-1]+a[i]-m;
}
sort(c,c+n);
long long x=c[n/2];
for(int i=0;i<n;++i){
ans+=llabs(x-c[i]);
}
printf("%lld\n",ans);
return 0;
}