E12 单调队列 连续子序列的最大和

视频链接:https://www.bilibili.com/video/BV1m54y117uu/

 

E11【模板】单调队列 滑动窗口最值 - 董晓 - 博客园 (cnblogs.com)

 LOJ10176 最大连续和

f[i]表示选第 i 个数,且长度不超过m的最大连续和
f[i] = max(s[i]-s[j]) = s[i]-min(s[j]),  i-m<=j<=i-1,s为前缀和

复制代码
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int N=300010;
int n, m;
int s[N], f[N], q[N];

int main(){
  scanf("%d%d", &n, &m);
  for(int i=1; i<=n; i++) 
    scanf("%d",&s[i]),s[i]+=s[i-1]; //前缀和
  
  int h=1, t=0;                         //清空队列
  for(int i=1; i<=n; i++){              //枚举序列
    while(h<=t && s[q[t]]>=s[i-1]) t--; //队尾出队(队列不空且新元素更优)
    q[++t]=i-1;                         //队尾入队(存储下标 方便判断队头出队)
    if(q[h]<i-m) h++;                   //队头出队(队头元素滑出窗口) 
    f[i]=s[i]-s[q[h]];                  //更新答案
  }

  int res=-2e9;
  for(int i=1; i<=n; i++)res=max(res,f[i]);
  printf("%d\n", res);
}
复制代码
复制代码
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int N=300010;
int n, m;
int s[N], f[N], q[N];

int main(){
  scanf("%d%d", &n, &m);
  for(int i=1; i<=n; i++) 
    scanf("%d",&s[i]),s[i]+=s[i-1]; //前缀和
  
  int h=1, t=0;                         //清空队列
  for(int i=1; i<=n; i++){              //枚举序列
    while(h<=t && q[h]<i-m) h++;        //队头出队(队列不空且队头元素滑出窗口) 
    while(h<=t && s[q[t]]>=s[i-1]) t--; //队尾出队(队列不空且新元素更优)
    q[++t]=i-1;                         //队尾入队(存储下标 方便判断队头出队)
    f[i]=s[i]-s[q[h]];                  //更新答案
  }

  int res=-2e9;
  for(int i=1; i<=n; i++)res=max(res,f[i]);
  printf("%d\n", res);
}
复制代码

 

练习

Luogu P1714 切蛋糕

Luogu P2629 好消息,坏消息

posted @   董晓  阅读(622)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示