我所学习到的内容:
1.二分答案,本题要处理平均数,前缀和处理时,每个值都减去答案,大于0则表示这个前缀平均值大于答案,小于0则表示小于答案,把前缀和相减,大于0则表示这段区间的平均值大于答案
2.对于至少要选择f块地,要算出一段大于f的区间平均值的最大值,看它是否大于0,大于0则满足条件,要算出这个最大值,使用公式s[i]-s[j-1](s数组表示前缀和)的值即是这段区间的平均值,可以使用双指针,i,j=i-f,用一个数minn存下来0~j中前缀和数组中的最小值,s[i]-minn即表示以i为右区间的的边界,长度大于等于f的区间的平均值的最大值, 对于每个i取max,最后与0比较,返回结果
本题题解即和我学习到的内容差不多
对于本题输出要输出r*1000而不能使用l我个人保持疑问
//对本题要输出r有疑问
//输入时写成了for(i=i;i<=n;i++)调试了好长时间
#include<iostream>
using namespace std;
const int N=1e5+10;
int edd[N];
double ess[N];
int n,f;
bool check(double mid){
for(int i=1;i<=n;i++)ess[i]=ess[i-1]+edd[i]-mid;
double eps=0;
for(int i=0,j=f;j<=n;i++,j++){
eps=min(eps,ess[i]);
if(ess[j]-eps>0)return 1;
}
return 0;
}
int main(){
cin>>n>>f;
for(int i=1;i<=n;i++)scanf("%d",&edd[i]);
double l=1,r=2000;
while(abs(r-l)>1e-9){
double mid=(l+r)/2;
if(check(mid))l=mid;
else r=mid;
}
cout<<(int)(r*1000)<<endl;
return 0;
}