问题描述
给定一个序列求其长度大于f的子区间的平均值的最大值
思路
求平均值可以用二分法来找平均值,先假设一个平均值,让原序列a减去假设平均值生成一个新序列b,b序列中有正有负,将b序列的前缀和存在sum数组中,区间[i,j]的和表示为sum[j]-sum[i],如果存在区间和大于0,说明平均值还可以更大一些。这样求得的平均值稍有误差,可以控制误差的数量级。
实现代码
int a[maxn]; //a数组
double b[maxn]; //a数组减去假设平均值
double sum[maxn]; //b的前缀和
double judgeAve(int n, double mid, int f)
{
for(int i = 1;i <= n;i++)
{
b[i] = a[i] - mid;
sum[i] = sum[i - 1] + b[i];
}
double min_val = 1e10, max_val = -1e10;
for(int i = f;i <= n;i++)
{
if(min_val > sum[i - f])
{
min_val = sum[i - f];
}
if(max_val < sum[i]-min_val)
{
max_val = sum[i]-min_val;
}
}
return max_val;
}
double largestAve(int a[],int n,int f)//a数组,数组长度为n,f子区间长度
{
double mid;
double l = 0,r = 1e5, eps = 1e-8;
while(r - l > eps)
{
mid = (r + l) / 2;
if(judgeAve(n, mid, f) > 0)
{
l = mid;
}
else
{
r = mid;
}
}
return r;
}