您好,欢迎来到华佗小知识。
搜索
您的当前位置:首页最佳牛围栏(实数域上的二分)

最佳牛围栏(实数域上的二分)

来源:华佗小知识

传送门:

思路:

朴素思路:直接枚举田地的数量,用前缀和求不同区间长度下的区间和最大值除长度,然后取个max,但最差的情况下要1~1e5的区间长度都枚举一次,等差数列的时间复杂度,O(n^2),超时了

二分思路:二分平均值的大小,判断“是否存在一个长度不小于f的区间,平均数不小于mid”,这里因为答案是有小数的,有精度问题。将原本的数组减去mid的值之后,如果每个点原本的数小于mid会小于0,大于mid会大于0,算出前缀和数组后就可以知道某一段区间和的平均数与mid的关系了,可以转化为判断“是否存在一个长度不小于f的区间,区间和非负”

注意:最后答案要用r*1000,l*1000可能会有问题。

斜率优化思路:........

代码:

#include <iostream>
#include <cstring>
#include <map>
using namespace std;
typedef pair<int ,int> PII;
const int N=1e5+10;
double a[N];
double sum[N];
int n,f;
int main()
{
    cin>>n>>f;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    double  eps=1e-5;
    double l=-2e3+10;
    double r=2e3+10;
    while(r-l>eps)
    {
        double mid=(l+r)/2;
        for(int i=1;i<=n;i++) sum[i]=a[i]-mid;
        for(int i=1;i<=n;i++)
            sum[i]+=sum[i-1];
    double  ans=-1e9;
    double min_res=1e9;
      for(int i=f;i<=n;i++)
     {
         min_res=min(min_res,sum[i-f]);
         ans=max(ans,sum[i]-min_res);
     }
        if(ans>=0) l=mid;
        else  r=mid;
    }
    cout<<int(r*1000)<<endl;
return 0;
}

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- huatuo0.cn 版权所有 湘ICP备2023017654号-2

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务