题解P1419 寻找段落(二分+单调队列)难度⭐⭐⭐★

Posted 繁凡さん

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解P1419 寻找段落(二分+单调队列)难度⭐⭐⭐★相关的知识,希望对你有一定的参考价值。

P1419 寻找段落

首先二分答案,即:二分最大平均值。
我们将a全部减去mid,问题转化为判断是否存在一个长度在s~t范围内的区间它的和为正,如果有说明还有更大的平均值。
用前缀和和单调队列维护。
不会单调队列的点这里
然后用单调队列求出sum[i]-min(sum[i-t]~sum[i-s]),然后判断是否大于0即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ifstream in("input.txt");
ofstream out("output.txt");
#define debug(x) cout<<"# "<<x<<endl
const ll N=100005;
const ll base=137;
const ll mod=2147483647;
const ll INF=1<<30;
ll n,m,a[N],s,t;
double sum[N],ans;

bool check(double mid)

    for(int i=1;i<=n;++i)
        sum[i]=sum[i-1]+(double)a[i]-mid;
    ll head=1,tail=0,q[N];
    for(int i=s;i<=n;++i)//区间的长度最少为s所以求前缀和,至少从s开始
    
        while(head<=tail&&sum[q[tail]]>=sum[i-s])//如果>=说明队列里出现了降序
            tail--;//把最前面的丢掉直到队列保持升序为止
        q[++tail]=i-s;
        //while(!q.empty()&&q.front.index<i-t)q.pop_front();
        while(head<=tail&&q[head]<i-t)//队列里的元素多于最大上限t就pop掉最先进入的值
            head++;
        if(head<=tail&&sum[i]-sum[q[head]]>=0)//如果队列里区间和>=0说明还有更大的平均值(前缀和嘛减后的值就是区间和)
            return 1;
    
    return 0;

int main()

    scanf("%lld",&n);
    scanf("%lld %lld",&s,&t);
    for(int i=1;i<=n;++i)
        scanf("%lld",&a[i]);
    double l=-10000.0,r=10000.0;
    while(r - l >= 1e-4)
    
        double mid=(l+r)/2.0;
        if(check(mid))ans=mid,l=mid;
        else r=mid;
    
    printf("%.3f\\n",ans);
    return 0;


有任何疑问欢迎评论哦虽然我真的很菜
点个关注再走吧

以上是关于题解P1419 寻找段落(二分+单调队列)难度⭐⭐⭐★的主要内容,如果未能解决你的问题,请参考以下文章

[二分 分数规划 单调队列 最优平均值] P1419 寻找段落

luoguP1419 寻找段落(二分答案+单调队列)

洛谷—— P1419 寻找段落

2096: [Poi2010]Pilots单调队列题解

HDU 3415 Max Sum of Max-K-sub-sequence 单调队列题解

HRBUST1356 Leyni,罗莉和队列 题解报告