Acwing 135 最大子序和

Posted Jozky86

tags:

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

Acwing 135 最大子序和

题目:

输入一个长度为 n 的整数序列,从中找出一段长度不超过 m 的连续子序列,使得子序列中所有数的和最大。

题解:

在这里插入图片描述
我们把这个问题的集合分成n份,第k份表示以A[k]结尾的最大连续子序列是多少
我们以A[k]结尾为例,我们从A[k]开始向前延申长度j,j的范围是[1,m],我们引入前缀和,S[k]表示前k个数的前缀和,那么图中长度为j,以A[k]结尾的连续子序列答案就是:S[k]-S[k-j],
现在S[k]是固定的,我们要让值最大,就要使得S[k-j]最小,就相当于在长度为m的区间(即从[k-m,k])内找最小值,这不就把问题引入到滑动窗口
在这里插入图片描述

代码:

#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\\n",a,b);
typedef long long ll;
using namespace std;

inline int read(){
   int s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
   return s*w;
}
const int INF=1e9;
const int maxn=3e5+9;
int n,m;
int s[maxn],q[maxn];

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",&s[i]);
		s[i]+=s[i-1];
	}
	int res=-INF;
	int hh=0,tt=0;
	for(int i=1;i<=n;i++){
		if(q[hh]+m<i)hh++;//如果超过范围 
		res=max(res,s[i]-s[q[hh]]);
		while(hh<=tt&&s[q[tt]]>=s[i])tt--;//维护一个递减序列 
		q[++tt]=i;
	}
	cout<<res;
	return 0; 
}

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

AcWing135. 最大子序和 单调队列

Acwing -- 单调队列优化的DP问题

135. 最大子序和前缀和 单调队列

最大子序和

最大子序和

代码题(25)— 最大子序和最长上升子序列