【bzoj1045】[HAOI2008] 糖果传递

环形均分纸牌问题。用A[i]表示糖果数,sum表示目标的糖果数量。用X[i]表示从i + 1移动到i的糖果的个数(可+可-)。由此可以得到式子A[i] + X[i] - X[i - 1] = sum。我们可以得到这样的n - 1个方程(第n个可以由前n - 1个推导)。但是这样不足以求解。我们进行以下变形:
A[2] + X[2] - X[1] = sum => X[2] = X[1] + sum - A[2]
A[3] + X[3] - X[2] = sum => X[3] = X[2] + sum - A[3] = X[1] + (sum - A[2]) + (sum - A[3])
设W[1] = 0, W[2] = A[2] - sum, W[i] = W[i - 1] + A[i] - sum,则 X[i] = X[1] - W[i]
所以Ans = sigma (|X[1] - W[i]|), 1 <= i <= n
而这个式子的几何意义是找一个点,使得这个点到W[i]所对应的每一个点的距离的和最小。所以X[1]应该取W[i]的中位数。

 

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>
using namespace std;
 
typedef long long LL;
 
#define MAXN 1000010
 
int a[MAXN],c[MAXN];
int n;
LL sum,ans;
 
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        sum+=a[i];
    }
    sum/=n;
    for (int i=2;i<=n;i++)
        c[i]=c[i-1]+a[i]-sum;
    sort(c+1,c+n+1);
    int m=c[n>>1|1];
    for (int i=1;i<=n;i++)
        ans+=abs(c[i]-m);
    printf("%lld",ans);
    return 0;
}
 

 

posted @ 2016-03-31 22:21  Yangjiyuan  阅读(133)  评论(0编辑  收藏  举报