最大子序和

单调队列优化DP

原题链接

题目描述:求长度为n的序列中一段长度不超过m的连续子序列的最大和

一段区间的和可以用前缀和来搞定
状态定义:
f[i]表示以a[i]结尾的长度不超过m的连续子序列最大和
状态转移:

fi=max{sisj}(1ijm)

得到j的范围:imji1
可以得到:fi=simin{sj}
也就是求一个窗口内sj的最小值,自然想到滑动窗口
具体代码如下:

Code

#include <iostream>
#include <algorithm>

using ll = long long;

const int N = 3e5 + 5;

ll s[N], q[N];

int main() {
    int n, m;
    std::cin >> n >> m;
    for (int i = 1; i <= n; i ++ ) {
        std::cin >> s[i];
        s[i] += s[i - 1];
    }
    
    ll res = -1e18, hh = 0, tt = -1;
    q[ ++ tt] = 0; // 先将下标0放入队列,因为前缀和
    for (int i = 1; i <= n; i ++ ) {
        if (hh <= tt && i - m > q[hh]) hh ++ ;
        res = std::max(res, s[i] - s[q[hh]]);
        while (hh <= tt && s[q[tt]] >= s[i]) tt -- ;
        q[ ++ tt] = i;
    }
    
    std::cout << res << '\n';
    return 0;
}
posted @   zjh-zjh  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示