• 二分算法题目训练(四)——Robin Hood详解


    codeforces672D——Robin Hood详解

    • Robin Hood
    • 问题描述(google翻译)

      • 我们都知道罗宾汉令人印象深刻的故事。罗宾汉利用他的射箭技巧和他的智慧从富人那里偷钱,然后把它归还给穷人。

        在Kekoland有n个公民,每个人都有ci硬币。每天,罗宾汉将从该市最富有的人那里拿出1枚硬币,然后将它交给最贫穷的人(最富有的1枚硬币后最穷的人)。如果选择不是唯一的,他将随机选择其中一个。可悲的是,罗宾汉已经老了,想要在k天退休。他决定在最后几天帮助穷人。

        罗宾汉拿走他的钱后,最富有的人也可能成为最穷的人,甚至可能会发生罗宾汉将他的钱还给他的钱。例如,如果所有人拥有相同数量的硬币,那么第二天他们也将拥有相同数量的硬币。

        你的任务是找出k天后最富有和最贫穷的人之间的差异。请注意,最富有和最穷的人随意选择不会影响答案。

    • 输入

      • 输入的第一行包含两个整数n和k(1≤n≤500000,0≤k≤109) - Kekoland的公民人数和Robin Hood退休前剩余的天数。

        第二行包含n个整数,其中第i个是ci(1≤ci≤109) - 第i个人的初始财富。

    • 输出
      • 打印一行,包含最富裕和最贫穷人口财富之间的差异。
    • 样例输入 1
      • 4 1
        1 1 4 2
    • 样例输出 1
      • 2
    • 样例输入 2
      • 3 1
        2 2 2
    • 样例输出 2
      • 0
    • 问题分析
      • 算出这批数据的平均值,将人群分为高于平均水平和低于平均水平的两类
      • 二分法找到一个均值,满足低于平均水平并且在 k 天内能补回平均水平的人,k 为控制变量
      • 二分法找到一个均值,满足高于平均水平并且在 k 天内能捐出去的人的集合,k 为控制变量
      • 两个均值差就是贫富差
    #include <iostream>
    
    #define Maxn 5000001
    
    using namespace std;
    
    typedef long long int LL;
    
    LL n;    //people
    int k;  //days
    int money;
    LL people[Maxn] = {0};
    
    int judge(LL day);
    int judge1(LL day);
    
    int main()
    {
        ios::sync_with_stdio(false);
        LL i = 1;
        LL sum = 0;
        cin >> n >> k;
        for(; i <= n; i++)
        {
            cin>>people[i];
            sum += people[i];
        }
        LL limit = sum / n;
        LL limit2 = limit;
        if(sum % n)
            limit2++;
        LL l = 1;
        LL r = limit;
        LL mid;
        LL result = 0,mark = 0,mark1 = 0;
        while(l <= r)
        {
            mid= (l + r) / 2;
            if(judge(mid))
            {
                mark = mid;
                l = mid + 1;
            }
            else
            {
                r = mid - 1;
            }
        }
        l = limit2;
        r = sum;
        while(l <= r)
        {
            mid = (l + r) / 2;
            if(judge1(mid))
            {
                mark1 = mid;
                r = mid - 1;
            }
            else
            {
                l = mid + 1;
            }
        }
        result = mark1 - mark;
        cout<<result;
        return 0;
    }
    
    int judge(LL day)
    {
        LL res = 0;
        for(LL j = 1;j <= n;j++)
        {
            if(people[j] < day)
                res += day - people[j];
        }
        return res <= k;
    }
    int judge1(LL day)
    {
        LL res = 0;
        for(LL j = 1;j <= n;j++)
        {
            if(people[j] > day)
                res += people[j] - day;
        }
        return res <= k;
    }
     
  • 相关阅读:
    Spring笔记:常用xml标签和属性 山上下了雪
    Spring笔记:Hello World 山上下了雪
    Spring笔记:bean的自动装配 山上下了雪
    IntelliJ IDEA 2020.3.3 x64破解到2099年
    每日长进计划
    idea测试类中的测试方法没有运行按钮
    删除所有的phpfpm进程命令
    高质量编程
    单例模式也能玩出花
    宝塔Linux面板安装命令
  • 原文地址:https://www.cnblogs.com/NikkiNikita/p/9450722.html
Copyright © 2020-2023  润新知