每日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)空间复杂度完美解决问题。理解"舍弃负贡献"的核心思想是关键,这种贪心策略在许多序列问题中都有广泛应用。实际编码时需特别注意全负数等边界情况的处理。

相关推荐
咚咚轩1 小时前
蓝桥杯13届 卡牌
蓝桥杯·贪心
fallzzzzz1 小时前
C++ stl中的list的相关函数用法
c++·list
悦悦子a啊2 小时前
PTA:jmu-ds-最短路径
c++·算法·图论
Despacito0o3 小时前
RGB矩阵照明系统详解及WS2812配置指南
c语言·线性代数·矩阵·计算机外设·qmk
小王努力学编程3 小时前
高并发内存池(三):TLS无锁访问以及Central Cache结构设计
jvm·数据结构·c++·学习
字节高级特工5 小时前
【C++】”如虎添翼“:模板初阶
java·c语言·前端·javascript·c++·学习·算法
.Vcoistnt5 小时前
Codeforces Round 1024 (Div. 2)(A-D)
数据结构·c++·算法·贪心算法·动态规划·图论
越甲八千5 小时前
MFC listctrl修改背景颜色
c++·mfc
炯哈哈5 小时前
【上位机——MFC】序列化机制
开发语言·c++·mfc·上位机
隐世16 小时前
C++多态讲解
开发语言·c++