CodeForces Gym - 100989G(二分)

Posted xiongtao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces Gym - 100989G(二分)相关的知识,希望对你有一定的参考价值。

题目链接:https://vjudge.net/contest/236677#problem/G

题目意思:有m个地方,有k小时,每个地方有a[i]个人。你要进行操作(一个小时可以移动一个人到另一个地方,或者不移动),最后使得m个地方的人数最多值变成最小情况。(就是移动人使每个地方的人接近平均值,就是统计学中方差就小)

思路:求出平均值,因为平均值是不变的,答案一定在平均值和最大值之间,二分就是要找到这个区间,左边临界值就是平均值,右边临界值就是最大值。在与当前最大值maxx二分得平局值mid,比较大于mid的地方移动到mid的时间总和是否比当前k大。

1.小于则说明都可以人数到达mid,再将最大人数maxx改为mid,k减去耗费时间,继续二分,直到大于,或者可以到达总平局值为止

2.大于则扩大均值,再二分,直到均值大于等于最大人数maxx

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int a[100050];
int m,k;
long long fun(long long t)//求当前人数最大到达t时间长 
{
    long long sum=0;
    for(int i=0;i<m;i++)
    {
        if(a[i]>t)
            sum+=a[i]-t;
    }
    return sum;
}
int main()
{
    while(cin>>m>>k)
    {
        long long sum=0,midx,maxx=0;
        for(int i=0;i<m;i++)
        {
            cin>>a[i];
            sum+=a[i];
            if(maxx<a[i])//maxx最大人数 
                maxx=a[i];
        }
        if(sum%m==0)
            midx=sum/m;
        else
            midx=sum/m+1;//均值 
        long long l=midx,r=maxx;
        while(l<r)//二分 
        {
            int mid=(l+r)/2;
            if(fun(mid)<=k)//可以达到均值,maxx(右)移动到mid 
                r=mid;
            else//不可以达到均值,midx(左)移动到mid+1; 
                l=mid+1;
        }
        cout<<l<<endl;
    } 
    return 0;
}

 

以上是关于CodeForces Gym - 100989G(二分)的主要内容,如果未能解决你的问题,请参考以下文章

Gym - 100989G

Codeforces Gym 100269 Dwarf Tower (最短路)

codeforces Gym 101063 C

codeforces Gym 100735 DEGHI

CodeForces Gym-101350M

Codeforces-gym-101020 problem C. Rectangles