zoukankan      html  css  js  c++  java
  • 102.最佳牛围栏

    原题链接:102. 最佳牛围栏


    解题思路

    本题题意为:给定正整数序列A,求一个平均数最大的、长度不小于L的(连续的)子段。

    首先我们可以这样理解,我们要寻找一段数列,这个数列满足,长度不小于L,并且它的子段和非负。也就是我们需要的二分判定。

    二分:首先我们的mid=(l+r)/2,记住这里不要是>>1,因为这是浮点数除法。然后呢,我们可以进行前缀和运算,s[i]=s[i−1]+a[i]−mid,因为首先我们找的mid是这个平均值,其次前缀和,是为了处理子段和,比如说我要算出[3,5]的子段和,那么我们只需要输出s[5]−s[2]即可。

    这里呢,我们要找到这个满足题意的最优解[l,r],那么也就是说a[l−1]要尽量地小,然后a[r]要尽量地大,所以说我们就需要枚举这个l,但是这样的话时间吃不消,那么怎么办呢?我们发现,每一次r变大后,l的取值范围从[1,l]变成了[1,l+1],所以说我们只需要一个变量,存储当前的最小值即可。具体可看代码实现。

    样例代码

    #include<bits/stdc++.h>
    using namespace std;
    double a[100001],b[100001],sum[100001];
    int main()
    {
        int N,L;
        cin>>N>>L;
        for(int i=1;i<=N;i++)
            cin>>a[i];
        double eps=1e-5;
        double l=-1e6,r=1e6;
        while(r-l>eps)
        {
            double mid=(l+r)/2;
            for(int i=1;i<=N;i++)
                b[i]=a[i]-mid;
            for(int i=1;i<=N;i++)
                sum[i]=(sum[i-1]+b[i]);
            double ans=-1e10;
            double min_val=1e10;
            for(int i=L;i<=N;i++)
            {
                min_val=min(min_val,sum[i-L]);
                ans=max(ans,sum[i]-min_val);
            }
            if(ans>=0)
                l=mid;
            else
                r=mid;
        }
        cout<<int(r*1000)<<endl;
        return 0;
    }
    
  • 相关阅读:
    8.使用axios实现登录功能
    7.django配置跨域并开发测试接口
    9.Vue组件
    2.初始化项目结构
    1.Django基础
    团队冲刺——第七天
    团队冲刺——第六天
    十天冲刺——第五天
    十天冲刺——第四天
    十天冲刺——第三天
  • 原文地址:https://www.cnblogs.com/hnkjdx-ssf/p/14201693.html
Copyright © 2011-2022 走看看