P1419 寻找段落 -二分答案-单调队列

  • P1419 寻找段落 
  • 题意:给定一个长度为n的序列a_i,定义a[i]为第i个元素的价值。现在需要找出序列中最有价值的“段落”。
  • 段落的定义是长度在[S,T]之间的连续序列。最有价值段落是指平均值最大的段落,
  • 段落的平均值=段落总价值/段落长度。
  • 思路:我们将a全部减去mid,问题转化为判断是否存在一个长度在s~t范围内的区间它的和为正。
  • 如果有说明还有更大的平均值。用前缀和单调队列维护。
  • 然后用单调队列求出sum[i]-min(sum[i-t]~sum[i-s]),然后判断是否大于0即可。
  • #include<bits/stdc++.h>
    using namespace std;
    #define maxn 123456
    int n,m,s,t;
    double a[maxn],l,r,mid,b[maxn];
    bool ok(double x)
    {
        deque<int>q;
        q.clear();
        for(int i=1; i<=n; i++)
            b[i]=b[i-1]+a[i]-x;
        for(int i=s; i<=n; i++)
        {
            while(!q.empty()&&b[q.back()]>b[i-s])q.pop_back();
            q.push_back(i-s);
            while(!q.empty()&&i-q.front()>t)q.pop_front();
            if(!q.empty()&&b[i]-b[q.front()]>=0)return 1;
        }
        return 0;
    }
    int main()
    {
        scanf("%d%d%d",&n,&s,&t);
        for(int i=1; i<=n; i++)
            scanf("%lf",&a[i]);
        r=10000;
        l=-10000;
        while(1e-5<r-l)
        {
            mid=(l+r)/2;
            if(ok(mid))l=mid;
            else r=mid;
        }
        if(ok(r))l=r;
        printf("%.3lf\n",l);
        return 0;
    }
    

     

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值