题目求平均数最大的子段, 有长度下限f.
转化为答案判定, 就是对于给定的平均数aver, 能否找到一个长度不小于m的满足平均数不小于aver的子段。
把整个数组减去aver, 就变成了判断有没有和为非负的子段. 若有非负子段, 则aver还可以往大猜;否则aver要变小。
所以问题最终转化为了求最大连续子段和, 而连续字段和可以化为前缀和相减的形式。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<cmath>
#include<queue>
using namespace std;
#define N 100005
double ant[N],sum[N];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%lf",&ant[i]);
}
double l=0,r=2000;
while(r-l>1e-5)
{
double mid=(l+r)/2;
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+ant[i]-mid;
double minn=1e9,maxx=-1e9;
for(int i=m;i<=n;i++)
{
minn=min(sum[i-m],minn);
maxx=max(sum[i]-minn,maxx);
}
if(maxx>0)l=mid;
else r=mid;
}
int ans=1000*r;
printf("%d\n",ans);
return 0;
}
注意: 实数域上的二分, 要求保留k位小数时, 则判断两数相等时一般当两数差的绝对值小于1e-(k+2)时就可认为相等, 精度太高也会WA