洛谷P2034题解:动态规划+单调队列优化求解最大K段子段和问题

深度学习
• 阅读 1

洛谷P2034题解:动态规划+单调队列优化求解最大K段子段和问题 一、题目解读 洛谷P2034题目要求给定一个长度为n的整数数组,将其分成不超过k段,求各段和的最大值。该问题属于经典动态规划问题的扩展,需结合优化技巧高效求解。

二、解题思路 采用动态规划+单调队列优化的策略。核心思想是定义状态dp[i]表示前i个数分成不超过k段的最大和,通过维护单调队列优化决策点选择。关键在于利用前缀和计算子段和,并通过队列动态维护合法且最优的决策点,避免暴力枚举导致的超时。

三、解题步骤

  1. 前缀和计算:预处理数组前缀和prefix,方便O(1)获取任意区间和。

  2. 动态规划初始化:初始化dp[0]=0,表示不选任何数的和为0。

  3. 状态转移:遍历i=1~n+1时,通过队列头部元素j计算dp[i] = dp[j] + prefix[i-1] - prefix[j],即前j个数分成k段的最大和 + 剩余部分。

  4. 队列维护:

    弹出队首不符合区间限制的元素(i-j-1 > k);

    弹出队尾使dp[i]-prefix[i] >= dp[q.back()]-prefix[q.back()]的元素,确保队列单调递增。

  5. 结果:最终dp[n+1]即为答案。

四、代码与注释

#include <iostream>
#include <vector>
#include <deque>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr); // 加快输入输出速度

    int n, k;
    cin >> n >> k;
    vector<long long> a(n + 1), prefix(n + 1, 0);
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
        prefix[i] = prefix[i - 1] + a[i]; // 计算前缀和
    }

    vector<long long> dp(n + 2, 0); // dp[i]表示前i个数的最大和
    deque<int> q; // 单调队列维护最优决策点

    // 初始条件:不选任何数时和为0
    q.push_back(0);

    for (int i = 1; i <= n + 1; ++i) {
        // 维护队列头部,确保不超过k的限制
        while (!q.empty() && q.front() < i - k - 1) {
            q.pop_front();
        }

        // 状态转移:dp[i] = max(dp[j-1] - prefix[j]) + prefix[i-1]
        dp[i] = dp[q.front()] + prefix[i - 1] - prefix[q.front()];

        // 维护队列单调性
        while (!q.empty() && dp[i] - prefix[i] >= dp[q.back()] - prefix[q.back()]) {
            q.pop_back();
        }

        q.push_back(i);
    }

    cout << dp[n + 1] << endl;
    return 0;
}

五、总结 本解法通过动态规划将问题转化为子问题最优解的组合,利用单调队列优化决策点选择,将时间复杂度降至O(n),成功解决洛谷P2034的挑战。该思路对处理分段优化类问题具有重要参考价值,体现了算法设计与数据结构的巧妙结合。 参考:洛谷题

点赞
收藏
评论区
推荐文章
菜园前端 菜园前端
1年前
什么是动态规划?
原文链接:什么是动态规划?动态规划也是算法设计的一种方法/思想。它将一个问题分解为相互重叠的子问题,通过反复求解子问题,来解决原来的问题。基础案例场景一斐波那契数列当前数等于前面两个数的和。定义子问题:f(n)f(n1)f(n2)
贾蔷 贾蔷
3星期前
NOIP 2000 提高组 洛谷1004题(方格取数)解题思路与C++代码解析
一、题目描述简要描述题目:例如,在一个n×n的方格图中,每个格子包含一个正整数。需要选择两条从左上角到右下角的路径,路径可重复经过格子,但两条路径除起点和终点外不能相交。求两条路径数字和的最大值。二、解题思路与算法分析1.问题分析1.问题核心是求解两条不交
贾蔷 贾蔷
2星期前
2025年GESP七级等价消除(洛谷P11965)代码解析与优化策略
一、题目解读2025年GESP七级考试中的“等价消除(洛谷P11965)”问题要求统计给定字符串中满足等价条件的子串数量。所谓“等价子串”,是指子串中所有字符出现的次数均相同。题目需要高效算法解决,考验对字符串处理和状态压缩的掌握。二、解题思路采用位运算
贾蔷 贾蔷
7小时前
牛客12576题全解析:动态规划+质因数分解解决跳跃问题
一、题目解读牛客12576题是一道经典的算法题,要求给定起点N和终点M,求解从N到M的最少跳跃次数。题目考察的核心在于路径优化与动态规划思想,需结合数论中的质因数分解技巧,通过合理设计算法降低时间复杂度,避免暴力枚举的指数级耗时。二、解题思路采用“动态规划
贾蔷 贾蔷
7小时前
2023年GESP六级小杨握手问题(洛谷B3874):Fenwick树求解逆序对的代码解析
一、题目解读“小杨的握手问题”源自2023年GESP六级考试(对应洛谷题目B3874)。题目描述为:给定一个长度为N的排列,每次将当前数与之前未访问过的数握手,求总共握手次数。本质上是求排列中逆序对的个数,即统计每个数右侧比它小的元素数量。需设计高效算法在
贾蔷 贾蔷
7小时前
CSP-J 2019公交换乘题解析:基于队列优化的动态规划代码详解
一、题目解读CSPJ2019年的“公交换乘”题目(洛谷P5661)要求模拟地铁与公交交替出行的费用计算。题目核心在于地铁消费会产生优惠券,而公交可在45分钟内使用优惠券抵扣车费。需要处理n条出行记录,优化总费用。该问题考察对时间窗口与动态资源管理的理解,需
深度学习 深度学习
7小时前
【CSP-S 2019】括号树(洛谷P5658):栈+DFS
一、题目解读括号树问题(洛谷P5658)要求处理一个由括号序列转化的树结构:每个节点表示一个括号,'('为子节点,')'为父节点。题目给定一棵n个节点的树,需计算每个节点的深度(括号层数),并输出所有节点深度与节点编号乘积的异或和。核心在于将括号序列转化为
深度学习 深度学习
7小时前
洛谷1111题解:基于Kruskal算法与并查集的最小生成树实现
一、题目解读洛谷1111题是一道经典的图论问题,要求构建一个无向图的最小生成树,并输出其最大边权值。题目核心在于通过给定的边集合,找到连接所有节点的最小权值子集,同时保证无环。这通常涉及最小生成树算法(如Kruskal)的应用,需要高效处理边权重与节点连通
深度学习 深度学习
7小时前
2024蓝桥杯省赛B组前缀总分(洛谷P12124)解题思路与代码详解
一、题目解读2024年蓝桥杯省B组题目“前缀总分”(对应洛谷P12124)要求计算给定字符串集合中,所有前缀的最长公共前缀(LCP)的总分,并找出通过移动字符位置后可能获得的最大总分。题目考察字符串处理与动态规划能力,需高效计算LCP并优化得分策略。二、解
贾蔷 贾蔷
7小时前
2023年GESP六级题解:洛谷P10108闯关游戏动态规划解法详解
一、题目解读本文针对2023年GESP六级题目“闯关游戏”(洛谷P10108)进行详细解析。题目要求玩家通过不同关卡路径选择,计算从起点到终点的最大得分。关卡间存在跳跃规则,需结合动态规划思想设计高效算法,最终输出最优得分。二、解题思路采用动态规划(Dyn