zjnu 1783 PROSJEK(二分)

这道题的题意就是:

给你一个长度为N的序列和一个K值,问你在这个序列中的长度至少为K的子序列的最大的平均值是多少。

这题的思路就是先二分这个最大值,然后判断这个值是否符合,这边的判断方法就是先把序列中所有的数都减x,把他们求一个前缀和sum,从第k个开始,看sum是否大于0。

如果小于0,就用Minx来记录前i-k+1的最小的前缀和,看之后的sum-minx是否大于0即可

AC代码:

/* ***********************************************
Author        :yzkAccepted
Created Time  :2016/3/29 19:03:12
TASK		  :ggfly.cpp
LANG          :C++
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <stack>
#define eps 1e-6
using namespace std;
typedef __int64 ll;
const int maxn=300001;
double a[maxn];
int n,k;
double b[maxn],sum[maxn];
int fun(double x)
{
	int i;
	double minx=0;
	sum[0]=0;
	for(i=1;i<=n;i++)
	{
		b[i]=a[i]-x;
		sum[i]=sum[i-1]+b[i];
	}
	for(i=k;i<=n;i++)
	{
		if(sum[i]-minx>=0)
			return 1;
		minx=min(minx,sum[i-k+1]);
	}
	return 0;
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int i;
	scanf("%d%d",&n,&k);
	for(i=1;i<=n;i++)
		scanf("%lf",&a[i]);
	double m,l=0,r=1000000;
	while(r-eps>l)
	{
		m=(l+r)/(2.0);
	//	printf("%lf %lf %lf\n",l,r,m);
		if(fun(m))
		{
			l=m;
		}
		else
		{
			r=m;
		}
		
	}
	printf("%.6lf\n",l);
    return 0;
}


你可能感兴趣的:(二分)