zoukankan      html  css  js  c++  java
  • Best Cow Fences

    题目链接

    题意

    把一个长度为N的序列取出一段长度不小于F的子段,求平均值最大的子段的平均值。

    思路

    答案似乎不容易看出单调性。。。

    换个思路, 一段序列减去平均值后得到的序列, 序列和一定为0.

    如果减去的值小于平均值, 则序列和为正, 反之为负。

    可以二分一个值, 然后减去这个值, 如果序列中长度不小于F的最大子段和为正, 说明平均值可以再大一些。。

    单调性就可以看出来了: 二分值越大, 序列所有数减去二分值后得到的最大子段段和就越小。

    关键便是快速判断最大子段和。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<queue>
    #include<vector>
    #include<set>
    #include<cmath>
    using namespace std;
    
    const int mx = 1e5 + 5;
    const int inf = 1e9;
    
    inline void fre(){ freopen("1.txt", "w", stdout); }
    
    int n, L;
    double a[mx], sum[mx];
    
    inline bool check(double mid){
        sum[0] = 0;
        double x;
        for(int i = 1; i <= n; i++) x = a[i] - mid, sum[i] = sum[i-1] + x;
        double minn = inf, res = -inf;
        for(int i = L; i <= n; i++){
            minn = min(minn, sum[i-L]);
            res = max(res, sum[i] - minn);
        } 
        if(res >= 0) return 1;
        return 0;
    }
    
    int main(){
        //fre();
        cin >> n >> L;
        double l = inf, r = 0;
        for(int i = 1; i <= n; i++) scanf("%lf", &a[i]), l = min(l, a[i]), r = max(r, a[i]);
        
        while(r - l > 0.000001){
            double mid = (l+r)/2;
            if(check(mid)) { l = mid;}
            else r = mid;
        }
        
        printf("%d
    ", (int)(r*1000));
        return 0;
    }
  • 相关阅读:
    5.14事务
    5.13Mysql数据库Database
    未来打算
    浅谈P NP NPC
    1222
    1219
    Linux初等命令
    惩罚因子(penalty term)与损失函数(loss function)
    12 14
    java 泛型思考
  • 原文地址:https://www.cnblogs.com/Maktub-blog/p/10995044.html
Copyright © 2011-2022 走看看