AcWing 135 最大子序和 题解(动态规划—DP—单调队列优化DP)

原题传送门
请添加图片描述
有点类似于前缀和的思想,不过这题如果纯前缀和基本相当于暴力,肯定过不去

#include<bits/stdc++.h>

using namespace std;

const int N = 300010, INF = 1e9;

int n, m;
int q[N], s[N];

int main()
{
	scanf("%d%d", &n, &m);
	
	for(int i = 1; i <= n; i ++ ){
		scanf("%d", &s[i]);
		//s[i]记录的是从s[1]到s[i]的数值之和 
		s[i] += s[i - 1];
	}
	
	int res = -INF, tt = 0, hh = 0;
	//单调队列
	for(int i = 1; i <= n; i ++ ){
		//q单调队列内存的是下标 
		if(q[hh] < i - m) hh ++ ;//如果队首元素已经超出单调队列范围,就让他出队
		res = max(res, s[i] - s[q[hh]]);
		//单调队列是单调上升的,所以在长度不超过m的单调队列内最小值是用队首元素记录的
		//用s[i]减去队首元素即可得这段区间内最大的连续子序列和 
		while(hh <= tt && s[i] <= s[q[tt]]) tt -- ;//单调队列内的元素是递增的,所以如果队尾元素大于新加入的元素,就需要让队尾元素出队
		//以此维持单调队列内单调上升的序列
		q[ ++ tt] = i;//新元素入队 
	} 
	cout<<res<<endl;
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值