luogu P3594 [POI2015]WIL-Wilcze doły 单调队列dp+双指针

#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=2e6+5;
ll q[N];
ll sum[N],a[N],n,p,d;
ll l,r;//维护区间
ll hh,tt;//维护队列中的长度为d的最大的区间
ll ans;
//hh,tt维护单调队列
//l,r双指针,以r做循环变量
//q[]代表单调队列的元素对应编号,也可用dequeue来写
int main()
{
    scanf("%lld%lld%lld",&n,&p,&d);
    for(int i = 1; i<=n; ++i)
        scanf("%lld",&a[i]),sum[i] += sum[i-1]+a[i];
    ans = d;
    tt = 1;
    hh = 1;
    l = 1;
    q[tt++] = d;
    //在一个区间中寻找sum[i]-sum[i-d]]的最大值
    //队列中的是 区间 中 长度为d 的最大值   的右端点
    for(r = d+1; r<=n; ++r)
    {
        //维护长度为d的最大值
        while(hh<tt&&sum[r]-sum[r-d]>sum[q[tt-1]]-sum[q[tt-1]-d])
            tt--;
        q[tt++] = r;
        //维护单调队列
        while(hh<tt&&sum[r]-sum[l-1]-sum[q[hh]]+sum[q[hh]-d]>p)
        {
            l++;
            //维护双指针   确保长度为d的在区间内,把不被包含的区间,弹出
            while(hh<tt&&q[hh]-d+1<l)
                hh ++;
        }
        ans = max(ans,r-l+1);
    }
    printf("%lld",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/QingyuYYYYY/p/13043065.html