Uva - 11300 - Spreading the Wealth

题意:党要重新给一个村庄的村民分配财产,n个村民(n < 1000001)围坐在一张圆桌上,开始时逆时针方向地给每个人a[i]个coins,接着每人给一些coins自己左边的人,给一些coins自己右边的人,最后所有人所得的coins数量相等,问总共最少要交换多少个coins。(注意用64位整数)

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=25&problem=2275

——>>设第i个人给了xi个cions自己左边的人:则有

——————————————>>x1 = x1 + 0;

第1人:a[1] - x1 + x2 = M;——>>x2 = x1 - (a[1]-M)

第2人:a[2] - x2 + x3 = M;——>>x3 = x1 - (a[1]-M) - (a[2]-M)

……

第n-1人:a[n-1] - x(n-1) + xn = M;——>>xn = x1 - (a[1]-M) - (a[2]-M) - ... - (a[n-1]-M);

第n人:a[n] - xn + x1 = M;(这个没用了)

设c[i] = c[i-1] + a[i] - M;

则有:

——>>x1 = x1 + c[0]

——>>x2 = x1 - c[1]

——>>x3 = x1 - c[2]

……

——>>x(n-1) = x1 - c[n];

要求的便是| x1 | + | x1 + c[0] | + | x1 - c[1] | + ... + | x1 - c[n] |的最小值——>>中位数!

#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

const int maxn = 1000001 + 10;

long long a[maxn], c[maxn];     //a[i]为输入的第i个人的初始拥有资金,c[i]为 a[1]-M + a[2]-M + ... + a[i]-M

int main()
{
    int n, i;
    while(cin>>n)
    {
        long long sum = 0;      //总和
        for(i = 1; i <= n; i++)
        {
            cin>>a[i];
            sum += a[i];
        }
        long long M = sum / n;      //求每人最后得到的钱
        c[0] = 0;
        for(i = 1; i < n; i++)
            c[i] = c[i-1] + a[i] - M;
        sort(c, c+n);       //从小到大排序,以便求得中位数
        long long x1 = c[n/2];     //中位数的下标
        sum = 0;        //这次用sum来计算总交换的金币数
        for(i = 0; i < n; i++)
            sum += abs(x1 - c[i]);
        cout<<sum<<endl;
    }
    return 0;
}


posted @ 2013-01-14 14:04  xiaodanding  阅读(106)  评论(0编辑  收藏  举报