【ybtoj 高效进阶 1.3】【二分】 最大均值
题目
解题思路
二分枚举平均值
求出所有数减去平均值之后的前缀和
如果一段区间和为非负数
说明这段区间的评价值大于当前的mid
两重循环枚举区间范围直接裂开
可以想到是长不小于L的区间
所以减去一个更小的值,区间的和会更优
只需要知道1~i-L中最小的值就可以
只需要枚举期间终点即可
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const double eps=1e-5;
int n,c,da;
double l,r,a[100010],sum[100010];
bool pd(double x)
{
double mi=1e10,ans=-1e10;
memset(sum,0,sizeof(sum));
for (int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i]-x; //求前缀和
for (int i=c;i<=n;i++)
{
mi=min(mi,sum[i-c]); //找最小的值
ans=max(ans,sum[i]-mi); //更新答案
}
return ans>=0;
}
int main()
{
scanf("%d%d",&n,&c);
for (int i=1;i<=n;i++)
cin>>a[i];
l=-1e6,r=1e6;
while (l+eps<r)
{
double mid=(l+r)/2;
if (pd(mid))
l=mid;
else r=mid;
}
da=r*1000;
printf("%d\n",da);
return 0;
}