LibreOj-10012-「一本通-1-2-例-2」Best-Cow-Fences

题目地址

思路

二分平均值,区间为\(0\)~\(2000\)。将每个\(a[i]\)减去平均值,就只用考虑字段和是否\(>=0\)了。
关于计算子段和,可以使用前缀和表示,\(sum[i]\)表示前\(i\)个数的和。
\(L\)~\(n\)以循环子段的尾巴,关于每次循环:

  • 维护一个子段开头的最小值
  • 找到这个平均值中,最大的子段和
    注意:由于是\(*1000\)\(int\)结果,自然是保留到5位小数(4+1进位),故二分判断为\(r-l>1e-5\)
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
double sum[100001];
int n,L,a[100001];
int main() {
    scanf("%d%d",&n,&L);
    for(int i=1;i<=n;i++)scanf("%d",a+i);
    double l=0,r=2000,eps=1e-5;
    while(r-l>eps){
        double mid=(l+r)/2;
        for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i]-mid;
        double ans=-1e10,min_v=1e10;
        for(int i=L;i<=n;i++){
            min_v=min(min_v,sum[i-L]);
            ans=max(ans,sum[i]-min_v);
        }
        if(ans>=0)l=mid;
        else r=mid;
    }
    printf("%d",int(r*1000));
}

转载于:https://www.cnblogs.com/dmoransky/p/10742642.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值