每日c/c++题 备战蓝桥杯(洛谷P1115 最大子段和)

洛谷P1115 最大子段和 题解

题目描述

最大子段和是一道经典的动态规划问题。题目要求:给定一个包含n个整数的序列,找出其中和最大的连续子序列,并输出该最大和。若所有数均为负数,则取最大的那个数。

输入格式

  • 第一行一个整数n(1 ≤ n ≤ 2×10⁵)
  • 第二行n个整数a₁,a₂,...,aₙ(-10⁴ ≤ aᵢ ≤ 10⁴)

输出格式

  • 输出一个整数,表示最大子段和

样例输入

复制代码
5
-2 11 -4 13 -5 -2

样例输出

复制代码
20

(对应子序列[11,-4,13])

解题思路

1. 动态规划(Kadane算法)

核心思想:维护两个关键变量

  • current_sum:以当前元素结尾的最大子段和
  • max_sum:全局最大子段和

状态转移方程
c u r r e n t _ s u m = { a i if c u r r e n t _ s u m < 0 c u r r e n t _ s u m + a i otherwise current\_sum = \begin{cases} a_i & \text{if } current\_sum < 0 \\ current\_sum + a_i & \text{otherwise} \end{cases} current_sum={aicurrent_sum+aiif current_sum<0otherwise
m a x _ s u m = max ⁡ ( m a x _ s u m , c u r r e n t _ s u m ) max\_sum = \max(max\_sum, current\_sum) max_sum=max(max_sum,current_sum)

2. 算法流程

  1. 初始化current_sum = 0max_sum = -∞
  2. 遍历数组中的每个元素:
    • 如果current_sum < 0,说明之前累计的和为负数,应舍弃,从当前元素重新开始
    • 否则,将当前元素加入累计和
    • 每次更新全局最大值max_sum
  3. 最终max_sum即为答案

代码解析

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

int main() {
    long long sum = 0;         // 当前子段和
    int x;                     // 临时存储输入值
    int n;
    cin >> n;
    
    // 初始化最大值为最小可能的long long值
    long long maxx = 0xffffffffffff;
    maxx *= -1;               // 等价于 LLONG_MIN
    
    for (int i = 1; i <= n; ++i) {
        cin >> x;
        if (sum > 0) {        // 累计和为正,继续扩展子段
            sum += x;
            maxx = max(maxx, sum);
        } else {              // 累计和为负,重新开始
            sum = x;
            maxx = max(maxx, sum);
        }
    }
    cout << maxx;
    return 0;
}

关键点说明

  1. 初始值设置

    • maxx初始化为0xffffffffffff * -1,等价于-2^48,确保能正确处理全负数情况
    • 更规范的写法是使用#include <climits>中的LLONG_MIN
  2. 决策逻辑

    • sum > 0时,继续累加当前元素可能获得更大和
    • sum ≤ 0时,舍弃之前所有元素,从当前元素重新开始
  3. 时间复杂度:O(n)

    • 仅需一次线性扫描即可完成计算

复杂度分析

指标 复杂度 说明
时间复杂度 O(n) 单次遍历数组
空间复杂度 O(1) 仅使用常数级额外空间

边界情况测试

测试用例 预期输出 实际输出 说明
1 -5 -5 -5 单个负数元素
3 -1 -2 -3 -1 -1 全负数序列
4 1 2 -3 4 6 6 包含负数的中间最优子段
5 -2 11 -4 13 -5 -2 20 20 经典样例

优化方向

  1. 输入优化

    • 使用scanf/printf替代cin/cout可提升IO速度
    • 添加ios::sync_with_stdio(false)加速C++流
  2. 代码简化

    cpp 复制代码
    // 简化版代码(功能完全等价)
    #include<bits/stdc++.h>
    using namespace std;
    int main() {
        int n, x;
        cin >> n;
        long long sum = 0, maxx = LLONG_MIN;
        while(n--) {
            cin >> x;
            sum = max((long long)x, sum + x);
            maxx = max(maxx, sum);
        }
        cout << maxx;
        return 0;
    }

总结

本题是动态规划的经典入门题,Kadane算法通过O(n)时间复杂度和O(1)空间复杂度完美解决问题。理解"舍弃负贡献"的核心思想是关键,这种贪心策略在许多序列问题中都有广泛应用。实际编码时需特别注意全负数等边界情况的处理。

相关推荐
qwertyuiop_i26 分钟前
pe文件结构(TLS)
c++·tls·pe文件结构
岁忧1 小时前
(nice!!!)(LeetCode每日一题)2434. 使用机器人打印字典序最小的字符串(贪心+栈)
java·c++·算法·leetcode·职场和发展·go
无敌的小笼包1 小时前
第四讲:类和对象(下)
数据结构·c++
鑫鑫向栄2 小时前
[蓝桥杯]解谜游戏
数据结构·c++·算法·职场和发展·蓝桥杯
闻缺陷则喜何志丹3 小时前
【分治法 容斥原理 矩阵快速幂】P6692 出生点|普及+
c++·线性代数·数学·洛谷·容斥原理·分治法·矩阵快速幂
鑫鑫向栄3 小时前
[蓝桥杯]整理玩具
数据结构·c++·算法·蓝桥杯·动态规划
景彡先生4 小时前
C++中的变量
c语言
计信金边罗11 小时前
是否存在路径(FIFOBB算法)
算法·蓝桥杯·图论
南郁13 小时前
007-nlohmann/json 项目应用-C++开源库108杰
c++·开源·json·nlohmann·现代c++·d2school·108杰