POJ 2018 二分

题意

传送门 POJ 2018

题解

最大化平均值问题考虑二分答案,问题转化为判定是否存在一个长度大于等于 F F F 的子区间,使其平均数不小于二分值。设区间为 [ l , r ] [l,r] [l,r],当前二分值为 x x x,则判定不等式为
∑ i ∈ [ l , r ] C [ i ] r − l + 1 ≥ x \frac{\sum_{i\in [l,r]}C[i]}{r-l+1}\geq x rl+1i[l,r]C[i]x 左右两边乘上分母,移项后得到
∑ i ∈ [ l , r ] ( C [ i ] − x ) ≥ 0 \sum_{i\in[l,r]}(C[i]-x)\geq 0 i[l,r](C[i]x)0

问题转换为求长度不小于 F F F 的最大子区间和。设 [ 1 , i ] [1,i] [1,i] 的前缀和为 s u m [ i ] sum[i] sum[i],枚举右界,则答案为 m a x r ∈ [ F , N ] { s u m [ r ] − m a x l ∈ [ 0 , r − F ] s u m [ l ] } max_{r\in [F,N]}\{sum[r]-max_{l\in [0,r-F]}sum[l]\} maxr[F,N]{sum[r]maxl[0,rF]sum[l]}

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 100005
#define maxc 2005
#define eps 1e-6
int N, F, C[maxn];
double sum[maxn];

bool judge(double x)
{
    for (int i = 1; i <= N; ++i)
        sum[i] = C[i] - x + sum[i - 1];
    double res = -maxc * maxn, mn = maxc * maxn;
    for (int r = F; r <= N; ++r)
    {
        mn = min(mn, sum[r - F]);
        res = max(res, sum[r] - mn);
    }
    return res >= 0;
}

int main()
{
    scanf("%d%d", &N, &F);
    for (int i = 1; i <= N; ++i)
        scanf("%d", C + i);
    double lb = 0, ub = maxc;
    while (ub - lb > eps)
    {
        double mid = (lb + ub) / 2;
        if (judge(mid))
            lb = mid;
        else
            ub = mid;
    }
    printf("%d\n", int(1000 * ub));
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值