【ybtoj 高效进阶 1.3】【二分】 最大均值

【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;
} 

猜你喜欢

转载自blog.csdn.net/qq_45621109/article/details/112112419