88888888y

导航

 

题目1:http://ybt.ssoier.cn:8088/problem_show.php?pid=1434

思路:二分加DP。判断mid比答案大还是小,就要用到"前缀存压缩"的方法。把数列的每个值都减去这个平均值,如果这种操作之后的区间内数字和大于等于0,说明这个数列存在比mid还大的平均值。

!注意:区间长度要大于等于L。

 

#include<bits/stdc++.h>
using namespace std;
int n,m,a[100001];
double b[100001],sum[100001];
bool check(double mid){
	int i;
	for(i=1;i<=n;++i){
		b[i]=a[i]*1.0-mid;//减去假定的平均值
	}
	for(i=1;i<=n;++i){
		sum[i]=sum[i-1]+b[i];//压缩
	}
	double ans=-1e9,minn=1e9;
	for(i=m;i<=n;++i){//开始表演
		minn=min(minn,sum[i-m]);
		ans=max(ans,sum[i]-minn);
	}
	if(ans>=0){//区间和大于等于0
		return 1;//打回“真”,肯定还能有更大的
	}
	return 0;//认怂
}
int main(){
	int i;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;++i){
		scanf("%d",&a[i]);
	}
	double l=0.0,r=1e9,q=1e-6;//注意,q的精度不能太高
	while(r-l>q){
		double mid=(l+r)/2.0;//正常操作
		if(check(mid)){//区间和真的大于等于0了
			l=mid;//往前推,我还能再大一点
		}
		else{//否则
			r=mid;//认怂
		}
	}
	printf("%d\n",(int)(r*1000));//要求是一千倍
    //那个(int)是为了消除遗留的小数
    return 0;
}
   
 
posted on 2022-02-25 11:01  88888888y  阅读(36)  评论(0)    收藏  举报