1 条题解

  • 0
    @ 2025-8-24 21:24:54

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar kkksc03
    洛谷吉祥物 DA✩ZE

    搬运于2025-08-24 21:24:53,当前版本为作者最后更新于2013-08-12 22:36:25,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    By tinylic

    首先看出答案满足单调性,可以二分答案,转化为判定性问题。

    令最优平均值为k,对于所有合法序列[l..r],

    尝试将分式变为整式:s[l..r]>k*(r-l+1)无解。

    移项,令b[i]=a[i]-k,s’[i]为b[1]..b[n]的和,则有

    寻找长度在[s,t]内的子段和的最大值可以用单调队列解决,参考POJ2823。

    这样就能通过O(n)的时间判定k是否可行,总复杂度O(nlogn)。

    具体实现的细节参考标程。

    
    
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #define maxn 100010
    
    using namespace std;
    
    int n, s, t, i;
    double l, r, mid, ans;
    double a[maxn];
    int b[maxn];
    double sum[maxn];
    int q[maxn];
    
    bool check(double x) {
        int i, l = 1, r = 0;
        for (i = 1; i <= n; i++)
            a[i] = (double)b[i] - x;
        sum[0] = 0;
        for (i = 1; i <= n; i++)
            sum[i] = sum[i - 1] + a[i];
        for (i = 1; i <= n; i++) {
            if (i >= s) {
                while (r >= l && sum[i - s] < sum[q[r]])    r--;
                q[++r] = i - s;
            }
            if (l <= r && q[l] < i - t) l++;
            if (l <= r && sum[i] - sum[q[l]] >= 0) return true;
        }
        return false;
    }
    
    int main() {
    
        scanf("%d", &n);
        scanf("%d%d", &s, &t);
        for (i = 1; i <= n; i++)
            scanf("%d", &b[i]);
        ans = l = -10000; r = 10000;
        while (r - l > 1e-5) {
            mid = (l + r) / 2;
            if (check(mid))
                ans = l = mid;
            else r = mid;
        }
    
        printf("%.3lf\n", ans);
        return 0;
    }
    
    
    
    • 1

    信息

    ID
    413
    时间
    1000ms
    内存
    125MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者