洛谷 P1115 最大子段和(前缀和详解)c++

题目链接:P1115 最大子段和 - 洛谷

1.题目分析

2.算法原理

解法:利用前缀和

思考:如何求出以a[i]为结尾的所有子区间中最大的子段和

假设 i 等于5,以 a[ i ] 为结尾的区间一共是五段(黑色线条部分),在这5段中找出最大的子段和,或者针对 i = 4 也能找到最大的子段和,i 等于1,2,3都能找到最大的子段和的话,在这所有情况里面取一个max就是最终结果了

先解决眼前的问题,如何找出以 a [ i ] 为结尾的最大子段和,只要能找到这一个,所有位置的最大子段和都能找出来,在所有情况下取一个最大值就可以了,当我想求黑色部分的时候,是拿所有区间的和减去红色部分,正好是 f [ i ](前缀和)- f [ x ](前面某一个区间的和),1 <= x <= i - 1,所以如何找出以 a [ i ] 为结尾的最大子段和,就是在找这个公式中所有计算的最大值,f [ i ] 是个定值,表示从1到 i 区间的和,f [ x ] 是变化的,如果想要减式的结果最大,那就要让减数最小就可以了,让整段区间的和,减去前面区间里最小的区间和,此时找到的就是最大的区间和

用 f [ i ] 减去 [1, i - 1] 中所有前缀和的最小值即可,假设现在 i 是 5,用1到 i 的区间和减去计算的前缀和中最小的值,就是以 i 为结尾的最大区间和了,再把下标6的位置求出来,7的位置求出来,在所有情况里面取一个最大值就可以了

如何快速找出 [1, i - 1] 中所有前缀和的最小值,一边计算 f [ i ] 的时候,一边更新前缀最小值,prevmin表示前缀最小值,假设计算下标5的前缀和的时候,prevmin表示1-4区间的前缀和最小值,计算完 f [ i ] 的时候,prevmin和 f [ i ] 取一个min,同时在赋值给prevmin,就可以在往后递推的过程中,计算 f [ i ] 的时候,prevmin里面就存着1-5区间里面前缀和的最小值,当计算下一个位置的前缀和的时候,prevmin记录着前面区间里面所有前缀和的最小值,计算完当前位置的时候,再对prevmin与当前位置的 f [ i ] 取个最小值就可以了,所以我们就可以在从前往后循环的过程中,搞一个变量计录一下前缀和的最小值就ok了

代码:

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

typedef long long LL;
const int N = 2e5 + 10;
int n;
LL f[N]; // 前缀和数组

int main()
{
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        LL x; cin >> x;
        f[i] = f[i - 1] + x;
    }

    LL ret = -1e20;
    LL prevmin = 0;

    for(int i = 1; i <= n; i++)
    {
        ret = max(ret, f[i] - prevmin);
        prevmin = min(prevmin, f[i]);
    }

    cout << ret << endl;

    return 0;
}
相关推荐
沐知全栈开发6 小时前
Java 文档注释
开发语言
沐怡旸6 小时前
【穿越Effective C++】条款3:尽可能使用const ——C++不变性的艺术
c++
程序_白白6 小时前
探讨一下java将来未来两年内的就业以及发展
java·开发语言
哼?~6 小时前
C++之智能指针
开发语言·c++
violet-lz7 小时前
数据结构八大排序:希尔排序-原理解析+C语言实现+优化+面试题
数据结构·算法·排序算法
mjhcsp7 小时前
C++ long long 类型深度解析:大整数处理的基石
开发语言·c++·策略模式·long long
ezl1fe7 小时前
第一篇:把任意 HTTP API 一键变成 Agent 工具
人工智能·后端·算法
Larry_Yanan7 小时前
QML学习笔记(四十五)QML与C++交互:信号槽的双向实现
c++·笔记·qt·学习·ui·交互
冯诺依曼的锦鲤7 小时前
算法练习:双指针专题
c++·算法
WaWaJie_Ngen7 小时前
【设计模式】工厂模式(Factory)
c++·设计模式·简单工厂模式·工厂方法模式·抽象工厂模式