题目链接: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; }
原文地址:https://www.cnblogs.com/xiongtao/p/9277601.html
时间: 2024-10-12 03:01:04