【BZOJ 1045】 1045: [HAOI2008] 糖果传递
1045: [HAOI2008] 糖果传递
Description
有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。
Input
第一行一个正整数n<=987654321,表示小朋友的个数.接下来n行,每行一个整数ai,表示第i个小朋友得到的
糖果的颗数.Output
求使所有人获得均等糖果的最小代价。
Sample Input
4
1
2
5
4Sample Output
4
【分析】
一道经典题。
设xi为i给i-1多少个糖果(负的表示反向给),x1表示1给n多少个糖果。
设M为平均数。
有:
a1-x1+X2=M -> x2=M-a1+x1
a2-x2+x3=M -> x3=M-a2+x2=2M-a1-a2+x1
.....
an-xn+x1=M
观察一下,设ci=ai-M
则:
x2=x1-c1
x3=x1-c2
...
就是求|x1|+|x1-c1|+|x1-c2|+...+|x1-cn-1|的最小值,变成了经典的数学的绝对值不等式的题目。
在数轴上表示成点到点的距离,就知道x1取所有C的中位数既有最小值。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<cmath> 7 using namespace std; 8 #define Maxn 10000010 9 #define LL long long 10 11 LL a[Maxn],c[Maxn],M; 12 13 LL myabs(LL x) {return x>0?x:-x;} 14 15 int main() 16 { 17 int n; 18 scanf("%d",&n); 19 for(int i=1;i<=n;i++) scanf("%lld",&a[i]); 20 M=0; 21 for(int i=1;i<=n;i++) M+=a[i]; 22 M/=n; 23 c[0]=0; 24 for(int i=1;i<n;i++) c[i]=c[i-1]+a[i]-M; 25 sort(c,c+n); 26 LL now=c[n/2],ans=0; 27 for(int i=0;i<n;i++) ans+=myabs(c[i]-now); 28 printf("%lld\n",ans); 29 return 0; 30 }
%%%大颓果
2016-12-13 16:53:51