• BZOJ-1045-[HAOI2008] 糖果传递(中位数原理)


    Description

    有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。

    Input

    第一行一个正整数nn<=1'000'000,表示小朋友的个数.
    接下来n行,每行一个整数ai,表示第i个小朋友得到的糖果的颗数.

    Output

    求使所有人获得均等糖果的最小代价。

    Sample Input

    4
    1
    2
    5
    4

    Sample Output

    4
     

    题解

    这道题对于最终小朋友手中的糖的数量我们是可以算出来的,我们用ave来表示

    我们假设Gi表示第i个人给第i-1个人糖的数量,G1表示第1个人给第n个人

    那么最后答案就是|G1|+|G2|+···+|Gn|

    那么到最后

    第一个人的糖就是A1-G1+G2=ave

    第二个人的糖就是A2-G2+G3=ave

    ······

    第n个人的糖就是An-Gn+G1=ave

    这里我们假设Ci=Ci-1+Ai-ave

    所以通过第一个人的糖,我们可以推出G2=G1-C1

    通过第二个人,可以推出G3=G1-C2

    ······

    第n个人,可以推出Gn=G1-Cn-1

    所以最后答案就变成了|G1|+|G1-C1|+|G1-C2|+···+|G1-Cn-1|

    对于求最后答案,问题就变成了给你坐标轴上的n个点,要你找到一个点,使得这个点到所有的点的距离之和最小

    而这个点的坐标就是坐标轴上点的中位数

     1 #include<bits/stdc++.h>
     2 #define N 1000005
     3 #define ll long long
     4 using namespace std;
     5 int n,ave;
     6 ll sum,ans;
     7 int a[N],c[N];
     8 int main(){
     9     scanf("%d",&n);
    10     for (int i=1;i<=n;i++){
    11         scanf("%d",&a[i]);
    12         sum+=a[i];
    13     }
    14     ave=sum/n;
    15     for (int i=2;i<=n;i++)
    16         c[i]=c[i-1]+a[i]-ave;
    17     sort(c+1,c+1+n);
    18     int mid=c[(n>>1)+1];
    19     for (int i=1;i<=n;i++)
    20         ans+=abs(mid-c[i]);
    21     printf("%lld
    ",ans);
    22     return 0;
    23 }
    View Code
  • 相关阅读:
    低效代码的危害
    使用datetime来控制timer的问题
    redis for windows
    log4net支持用日期加时间指定文件名
    防止数据丢失的解决方法
    RabbitMQ默认情况下不保证每次都把消息传递
    UnitTest和Developer
    spring+eureka+zuul
    新工具解决消息丢失的bug
    java_if_else__的应用1
  • 原文地址:https://www.cnblogs.com/zhuchenrui/p/7718758.html
Copyright © 2020-2023  润新知