zoukankan      html  css  js  c++  java
  • BZOJ3293: [Cqoi2011]分金币

    Description

    圆桌上坐着n个人,每人有一定数量的金币,金币总数能被n整除。每个人可以给他左右相邻的人一些金币,最终使得每个人的金币数目相等。你的任务是求出被转手的金币数量的最小值。

    Input

    第一行为整数nn>=3),以下n行每行一个正整数,按逆时针顺序给出每个人拥有的金币数。

    Output

    输出被转手金币数量的最小值。

    Sample Input

    4
    1
    2
    5
    4

    Sample Output

    4
    样例解释
    设四个人编号为1,2,3,4。第3个人给第2个人2个金币(变成1,4,3,4),第2个人和第4个人分别给第1个人1个金币。

    HINT

    N<=<=100000,总金币数<=10^9

     
    设X[i]为第i个人给他下一个人的金币数,T表示最终每人应该得到的金币数。
    则X[i-1]+A[i]-X[i]=T,移项得X[i]=X[i-1]+A[i]-T。
    但是我们是不能直接解方程的,因为虽然方程有N个,但有一个是没用的。
    我们忽略第一个方程,即让X[0]=0,然后我们可以发现这可以理解为坐标轴上N个点,我们要找一个点到其他点距离之和最短。
    排序中位数即可。
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
        if(head==tail) {
            int l=fread(buffer,1,BufferSize,stdin);
            tail=(head=buffer)+l;
        }
        return *head++;
    }
    inline int read() {
        int x=0,f=1;char c=Getchar();
        for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
        return x*f;
    }
    typedef long long ll;
    const int maxn=100010;
    int n,A[maxn];
    ll ans,sum,C[maxn];
    int main() {
        n=read();rep(i,0,n-1) sum+=(A[i]=read());
        sum/=n;rep(i,1,n-1) C[i]=C[i-1]+A[i]-sum;
        sort(C,C+n);
        rep(i,0,n-1) ans+=abs(C[i]-C[n>>1]);
        printf("%lld
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    bzoj1797
    bzoj1266
    bzoj1497
    bzoj1412
    bzoj3156
    JSOI2014第三轮总结
    bzoj1855
    bzoj1044
    codeforces 371D
    codeforces 371B
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5288343.html
Copyright © 2011-2022 走看看