Task
N*m的矩形,每行取[ 1,m ]个数,求取出的最大平均值。
H*n<=1e5,a[i][j]∈[1,1e9]
Solution
二分的功能:
① 有序数组查找某值
② 假定解,判可行
③ 最大化最小值
④ 最大化平均值
本题用2,4个功能。
sum1+sum2+*+sumn/num1+num2+***numn>=k
(sum1-k*num1)+(sum2-k*num2)+*(sumn-k*numn)>=0
顺序扫描这一行,找到sum-k*num最大的值,作为这一行的选择。
Double类型的二分技巧:循环100次,把mid赋值给l或r。l小于r+0.00001就可以停了,千万不要向我一样傻乎乎地循环了750次,导致TLE了。
常见的最大化平均值还有 枚举+贪心/dp 枚举分子,贪心分母 但是这不适用与于这一题。
code
const int M=1e5+5;
vector<int>A[M];
int n,m,mx;
inline void input(){
int i,j,k;
rd(n);rd(m);
rep(i,0,n-1)rep(j,1,m)rd(k),A[i].pb(k),mx=max(mx,k);
}
inline bool check(db k){
int i,j;ll sum=0;
db ans=0.0,mx;
rep(i,0,n-1){
mx=-2e9;sum=0;
rep(j,0,m-1){
sum+=A[i][j];
mx=max(mx,(db)sum-1.0*1ll*k*(j+1));
}
ans+=mx;
}
return ans>=0;
}
inline void solve(){
int i,j,k=50;
db l=0,r=1.0*mx;
db mid;
while(k--){
mid=1.0*(l+r)/2;
if(check(mid))l=mid;
else r=mid;
}
printf("%.4lf\n",l);
}
int main(){
input();
solve();
return 0;
}