HDU - 2993 (读入优化)

题意

给你n个数和一个数字k,要求所有长度 ≥ k \geq k k的所有连续子序列中,平均值最大的值。

思路

设数组 s [ i ] s[i] s[i]代表序列的前缀和,所求的平均值即为
s [ i ] − s [ j ] i − j ( i − j ≥ k ) \frac{s[i]-s[j]}{i-j} (i-j\geq k) ijs[i]s[j](ijk)
这个值即是直线 s [ i ] = i ∗ k + b s[i]=i*k+b s[i]=ik+b的斜率。
需要注意要保证单调队列的队首元素即是对于每种情况的最优解。同时维护的是一个下凸壳。

要注意这个题需要快速读入。需要快速读入的板子。

代码
//
// Created by yjq on 2019/9/19.
//

#include <bits/stdc++.h>
//#include <cstdio>
//#include <cstring>
//#include <iostream>
//#include <algorithm>

using namespace std;

#define ll long long
//#define ld long double
//#define ull unsigned long long
//#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)

ll n, k;

inline char nc() {
    static char buf[100000], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}

inline bool _read(ll &sum) {
    char ch = nc();
    if (ch == EOF)
        return 0;
    sum = 0;
    while (!(ch >= '0' && ch <= '9'))ch = nc();
    while (ch >= '0' && ch <= '9')sum = sum * 10 + ch - 48, ch = nc();
    return sum;
}

const int maxn = 1e5 + 10;
ll a[maxn], s[maxn], q[maxn];

//inline int X(int i, int j) {
//    return j - i;
//}

//inline int Y(int i, int j) {
//    return s[j] - s[i];
//}

//inline double DP(int i, int j) {
//    return (double) (s[i] - s[j]) / (double) (i - j);
//}

int main() {
//    __;
    while (_read(n) && _read(k)) {
        for (int i = 1; i <= n; ++i) {
            _read(s[i]);
            s[i] += s[i - 1];
        }
/*    while (cin >> n >> k) {
        for (int i = 1; i <= n; ++i) {
            cin >> s[i];
            s[i] += s[i - 1];
        }*/
        int l = 0, r = 0;
        q[++r] = 0;
        double ans = 0;
        for (int i = 1; i <= n; ++i) {
            int cur = i - k + 1;
            while (l + 1 < r && (s[i] - s[q[l + 1]]) * (i - q[l + 2]) <= (i - q[l + 1]) * (s[i] - s[q[l + 2]]))
                ++l;
            if (i < k)continue;
            ans = max(ans, (double) (s[i] - s[q[l + 1]]) / (double) (i - q[l + 1]));
            while (l + 1 < r &&
                   (s[q[r]] - s[q[r - 1]]) * (cur - q[r]) >=
                   (q[r] - q[r - 1]) * (s[cur] - s[q[r]]))
                --r;
            q[++r] = cur;
        }
        printf("%.2f\n", ans);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值