最大子序和 题解

最大子序和

508.最大子序和
本题使用 单调队列的思想来 求最大子序和 一道模板题

我们要求区间和,一般转化为两个前缀和相减。我们求出 s [ i ] s[i] s[i](前i项的和)
,要求 [ L , R ] [L,R] [L,R]的最大的区间和就变成了找到两个x, y, 使得 s [ y ] − s [ x ] s[y] - s[x] s[y]s[x]最大并且 y − x < = m y - x <= m yx<=m, 我们枚举区间右端点 i i i,寻找区间左端点 j j j , 在$[i - m,i] $ 中,使得s[j]最小, 这样我们得到的区间和最大, 可以发现此时这个序列必须保持单调递增的性质,才能有最大值,所以就可以用单调队列来写。

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N = 1e6 + 10, INF = -2e9;
int a[N], q[N];

signed main()
{
    int n, m;
    scanf("%lld %lld", &n, &m);
    
    for(int i = 1; i <= n;i ++ )
    {
        scanf("%lld", &a[i]);
        a[i] += a[i - 1]; //处理前缀和
    }
    int ans = INF;
    
    int l = 0, r = 0;
    for(int i = 1; i <= n; i ++ )
    {
        if(l <= r && q[l] < i - m) l ++; 
        //如果已经出了左端点的范围就右移队头,使得队头一直在寻找的区间内
        //因为每次队头最多只会移一位,所以用 if,这里用 while 也对
        ans = max(ans, a[i] - a[q[l]]); //求最大子序和
        
        while(l <= r && a[q[r]] >= a[i]) r --;
        
        q[++ r] = i;//把元素的下标插入队列中
    }
    
    printf("%lld", ans);
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值