• codeforces 671B Robin Hood 二分


    题意:有n个人,每个人a[i]个物品,进行k次操作,每次都从最富有的人手里拿走一个物品给最穷的人

            问k次操作以后,物品最多的人和物品最少的人相差几个物品

    分析:如果次数足够多的话,最后的肯定在平均值上下,小的最多被补到sum/n,大最多减少到sum/n,或者sum/n+1

            然后就二分最小值,看所有小的是否能在k次被填满

                    二分最大值,看所有大的是否都在k次被抹平

    然后就是二分的写法,小和大的不一样,需要加等号,避免死循环

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <math.h>
    using namespace std;
    typedef long long LL;
    const int N = 5e5+5;
    int a[N],k,n;
    bool checkmax(int x){
       int tmp=k;
       for(int i=1;i<=n;++i){
        if(a[i]>x)tmp-=(a[i]-x);
        if(tmp<0)return false;
       }
       return true;
    }
    bool checkmin(int x){
      int tmp=k;
      for(int i=1;i<=n;++i){
        if(a[i]<x)tmp-=(x-a[i]);
        if(tmp<0)return false;
      }
      return true;
    }
    int main(){
        scanf("%d%d",&n,&k);
        LL sum=0;
        int k1,k2,x=0,y=0x7f7f7f7f;
        for(int i=1;i<=n;++i){
          scanf("%d",&a[i]);
          sum+=a[i];
          x=max(x,a[i]);
          y=min(y,a[i]);
        }
        k1=k2=sum/n;
        if(sum%n)++k2;
        int ans2,ans1,l=y,r=k1;
        while(l<=r){
           int m=(l+r)>>1;
           if(checkmin(m))ans1=m,l=m+1;
           else r=m-1; 
        }
        l=k2,r=x;
        while(l<r){
            int m=(l+r)>>1;
            if(checkmax(m))r=m;
            else l=m+1;
        }
        ans2=(l+r)>>1;
        printf("%d
    ",ans2-ans1);
        return 0;
    }
    View Code
  • 相关阅读:
    Day13
    Day12
    Day11
    Day10
    Day9
    Day8
    Day7
    mac上使用gitlab拉项目报错Permissions 0644 for ...
    vue-cli3使用svg
    js合并多个array
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5485473.html
Copyright © 2020-2023  润新知