【二分答案】POJ2018简化SDNU_ACM_ICPC_2020_Winter_Practice_2nd第K题

题目求平均数最大的子段, 有长度下限f.

转化为答案判定, 就是对于给定的平均数aver, 能否找到一个长度不小于m的满足平均数不小于aver的子段。
把整个数组减去aver, 就变成了判断有没有和为非负的子段. 若有非负子段, 则aver还可以往大猜;否则aver要变小。
所以问题最终转化为了求最大连续子段和, 而连续字段和可以化为前缀和相减的形式。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<cmath>
#include<queue>
using namespace std;
#define N 100005
double ant[N],sum[N];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%lf",&ant[i]);
    }
    double l=0,r=2000;
     while(r-l>1e-5)
     {
         double mid=(l+r)/2;
         for(int i=1;i<=n;i++)
            sum[i]=sum[i-1]+ant[i]-mid;
         double minn=1e9,maxx=-1e9;
         for(int i=m;i<=n;i++)
         {
             minn=min(sum[i-m],minn);
             maxx=max(sum[i]-minn,maxx);
         }
         if(maxx>0)l=mid;
         else r=mid;
     }
     int ans=1000*r;
     printf("%d\n",ans);
     return 0;
}

注意: 实数域上的二分, 要求保留k位小数时, 则判断两数相等时一般当两数差的绝对值小于1e-(k+2)时就可认为相等, 精度太高也会WA

发布了9 篇原创文章 · 获赞 0 · 访问量 87

猜你喜欢

转载自blog.csdn.net/weixin_45502089/article/details/104111574