zoukankan      html  css  js  c++  java
  • HDOJ 2993 MAX Average Problem(斜率优化经典)

    题意:

    一个长度为 N 的数列,求大于给定长度 k 的区间的最大平均值。

    思路:

    1. sum[i] 代表 1~i 数列的元素和,则求区间最大平均值相当于 ave(i, j) = (sum[j] - sum[i-1]) / (j - (i-1));

    2. 本题要求大于长度 k 的区间,如果我们要维护以 i + k 为结尾,区间长度大于 k 的最大平均值,则要枚举 0~i 种情况,此时时间复杂度为 O(n * n);

    3. 于是可以尝试用单调队列来优化这一情况,队列中存放的是斜率值,并且保证队列中存放的点所构成的图形是下凸的,这样才能保证 i + k 与队列中点的切线斜率最大。

    4. 对于进队列可以用 3 中的方法维护,出队列则要考虑切线的情况了,由于斜率都是大于 0 且队列中是下凸的,则每次考虑 i + k 与 deq[s] 的连线是否最优即可。

    5.“浅谈数形结合思想在信息学竞赛中的应用”中有一个图,看了一目了然:

                        

    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 100010;
    
    int sum[MAXN], deq[MAXN];
    
    inline double slope(int i, int j)
    {
        return ((double)(sum[i] - sum[j])) / (i - j);
    }
    
    int main()
    {
        int N, k;
        while (scanf("%d %d", &N, &k) != EOF)
        {
            sum[0] = 0;
            for (int i = 1; i <= N; ++i)
                scanf("%d", &sum[i]), sum[i] += sum[i-1];
    
            double ans = 0.0;
            int s = 0, e = -1;
    
            for (int i = 0; i + k <= N; ++i)
            {
                while (s < e && slope(deq[e], deq[e-1]) >= slope(i, deq[e]))
                    --e;
    
                deq[++e] = i;
    
                while (s < e && slope(i+k, deq[s]) <= slope(i+k, deq[s+1]))
                    ++s;
    
                ans = max(ans, slope(i+k, deq[s]));
            }
            printf("%.2lf\n", ans);
        }
        return 0;
    }
  • 相关阅读:
    SQL单表查询
    SQL基础
    python生成器yield和send
    python模块
    python异常
    python单例设计模式
    python类方法、类属性和静态方法
    python继承
    react native window下的环境搭建和调试方案
    打通前后端全栈开发node+vue进阶【课程学习系统项目实战详细讲解】(3):用户添加/修改/删除 vue表格组件 vue分页组件
  • 原文地址:https://www.cnblogs.com/kedebug/p/2940053.html
Copyright © 2011-2022 走看看