最大子序和

Posted dongdong25800

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最大子序和相关的知识,希望对你有一定的参考价值。

 

https://www.acwing.com/problem/content/137/

 

技术图片

通俗做法是n2的,就是求前缀和,sum[i]-sum[j]的最大值就是1~n枚举每个sum[i]也就是右端点,对于每个数找一个范围内最大的sum[j]左端点,然后求最大值。

过程中可以优化,对于每个右端点来说,没必要遍历一遍它的所有的左端点去找最小值,我们可以维护一个从左往右单调递增的序列,可以直接确定这个左端点最小值就是这个序列最左的值。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=3e5+10;
int q[maxn];
ll sum[maxn];
int main()

    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++)
    
        ll t;
        scanf("%lld",&t);
        sum[i]=sum[i-1]+t;
    
    int head=1;
    int tail=0;
    ll maxx=-1e18;
    for(int i=1; i<=n; i++)
    
        while((i-q[head])>m)
        
            head++;
        
        maxx=max(maxx,sum[i]-sum[q[head]]);
        while(head<=tail&&sum[i]<sum[q[tail]])
        
            tail--;
        
        q[++tail]=i;
    
    printf("%lld",maxx);

 

倒着写了一遍,更理解含义了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=3e5+10;
int q[maxn];
ll sum[maxn];
int main()

    int n,m;
    scanf("%d%d",&n,&m); // 0~n
    for(int i=1; i<=n; i++)
    
        ll t;
        scanf("%lld",&t);
        sum[i]=sum[i-1]+t;
    
    int head=1;
    int tail=0;
    ll maxx=-1e18;
    q[head]=n;
    for(int i=n; i>=0; i--)
    
        while((q[head]-i)>m)
        
            head++;
        
        maxx=max(maxx,sum[q[head]]-sum[i]);
        while(sum[i]>sum[q[tail]]&&head<=tail)
        
            tail--;
        
        q[++tail]=i;
    
    printf("%lld",maxx);

 

以上是关于最大子序和的主要内容,如果未能解决你的问题,请参考以下文章

53.最大子序和

最大子序和

1.(53)最大子序和

LeetCode53. 最大子序和

动态规划 解决二维最大子序和问题---滚动数组

动态规划 解决二维最大子序和问题---滚动数组