题解 P1714 【切蛋糕】

· · 个人记录

可以称得上是单调队列模板题了

刚学单调队列,正好写个题解

先看题目,短小的题目题意相当明确,在n个数中取连续的k(k<=m)个数,输出其中所有可能的最大值。

注意k<=m,并不要求一定为m。这就超出我朴实前缀和的能力范围了,然而对于单调队列没有什么影响

前缀和是当然要用的,输入数据顺便求出前缀和。

然后维护一个队首最大的单调队列,O(n)复杂度就轻松搞定。

因为不想单调队列开两个数组,我用struct把入队时间index和价值value同时记录

#include<cstdio>
#include<algorithm>
int cake,n,m,ans=-2333333;//蛋糕幸运值有负数,安全起见ans初始化小一点 
int sum[500005];
struct node
{
    int index,value;//入队时间,前缀和 
}q[500005];
int main()
{
    int front=1,back=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) 
    {
        scanf("%d",&cake);
        sum[i]=sum[i-1]+cake;//计算前缀和 
    }
    for(int i=1;i<=n;i++)
    {
        if(q[front].index+m<i) front++;//将已经超出范围的蛋糕出队 
        while(front<=back&&q[back].value>=sum[i]) back--;//将比当前蛋糕幸运值高的蛋糕出队,维护队列单调递增 
        q[++back].index=i;q[back].value=sum[i];//当前蛋糕一定会入队 
        ans=std::max(ans,q[back].value-q[front].value);
    }
    printf("%d\n",ans);
    return 0;
 } 

蒟蒻求过qwq