最大子序和
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);
以上是关于最大子序和的主要内容,如果未能解决你的问题,请参考以下文章