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;//均值 
        while(midx<maxx)//二分 
        {
            int mid=(midx+maxx)/2;
            if(fun(mid)<=k)//可以达到均值,maxx(右)移动到mid 
                maxx=mid;
            else//不可以达到均值,midx(左)移动到mid+1; 
                midx=mid+1;
        }
        cout<<midx<<endl;
    } 
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xiongtao/p/9277601.html