题目链接
AcWing 102.
思路易错点在代码上部。
/*
二分平均值.
题目中有长度不小于L的限制(len>=L)
check时判断是否存在sum - len * avg >= 0
可以转化为是否存在子段和sum(a[i]-avg)非负,且子段长度不小于L
子段和sum用前缀和维护.
for(int i=1;i<=n;i++) b[i] = a[i] - avg;
int minn = 1e9;
int ans = -1e9;
for(int i=L;i<=n;i++){
// 记录合法的最小的前缀 动态判断.
minn = min(minn,sum[i-L]);
ans = max(ans,sum[i]-minn);
}
if(ans>=0) return true;
return false;
*/
#include <bits/stdc++.h>
using namespace std;
#define EPS 1e-5
// double EPS = 1e-5;
double a[100010],b[100010];
double sum[100010];
int n,L;
bool check(double m){
for(int i=1;i<=n;i++){
b[i] = a[i] - m;
sum[i] = sum[i-1] + b[i];
}
double minn = 1e10;
double res = -1e10;
for(int i=L;i<=n;i++){
minn = min(minn,sum[i-L]);
res = max(res,sum[i]-minn);
if(res>=0) return true;
}
return false;
}
int main()
{
std::ios::sync_with_stdio(false);std::cin.tie(nullptr);
cin >> n >> L;
for(int i=1;i<=n;i++) cin >> a[i];
double l = 0.0,r = 1e6;
while(r - l > EPS){
double mid = (l + r) / 2;
if(check(mid)) l = mid;
else r = mid;
}
// 注意精度问题!
cout << ((int)(r*1000)) << endl;
return 0;
}