[jzoj 4256]平均数{二分答案+巧妙做法+前缀和优化}

版权声明:请大家斧正,如喜欢的话,为拙见点一个赞吧。 https://blog.csdn.net/qq_39897867/article/details/86728609

题目

Description
给出包含一个N个整数的数组A。找出一段长度至少为K的连续序列,最大化它的平均值。
请注意:一段子序列的平均值是子序列中所有数的和除以它的长度。

Input
第一行包含两个整数N(1<=N<=300000),K(1<=K<=N)。
第二行包含N个整数,代表数组A,1<=ai<=10^6。

Output
一行一个实数,代表最大的平均值。允许在0.001以内的绝对误差。


结题思路

根据wyc大佬的原话:题目给出了spj,显然二分答案。

然后应该怎么判断呢?我们可以将所有a[i]-=mid,若一段长度>=k的区间和,则答案合法。

前缀和优化。


代码

#include<cstdio>
#include<algorithm>
#define db double
#define rr register 
#define fre(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout)
using namespace std;
const int maxn=300005; 
const db e=1e-7; 
int n,k,a[maxn]; db b[maxn],ans,l=0,r,mid;
inline bool check(db x){
	db c=-2147483647.0*2147483647; 
	for(rr int i=1;i<=n;i++) b[i]=b[i-1]+(db)(a[i]-x); 
	for(rr int i=n-k+1;i>=1;i--) if ((c=max(c,b[i+k-1]))-b[i-1]>=0) return 1;
	return 0; 
}
int main(){
//	fre(average); 
	scanf("%d%d",&n,&k); r=1000000; 
	for(rr int i=1;i<=n;i++) scanf("%d",&a[i]); 
	while (r-l>e) if (check((mid=(l+r)/2))) ans=mid,l=mid; else r=mid; 
	return 0&printf("%.6lf",ans); 
}

猜你喜欢

转载自blog.csdn.net/qq_39897867/article/details/86728609
今日推荐