最大子序和(数组模拟单调队列)

问题 B: 最大子序和

题目描述
输入一个长度为n的整数序列,从中找出一段不超过M的连续子序列,使得整个序列的和最大。
例如 1,-3,5,1,-2,3
当m=4时,S=5+1-2+3=7
当m=2或m=3时,S=5+1=6

输入
第一行两个数n,m
第二行有n个数,要求在n个数找到最大子序和
输出
一个数,数出他们的最大子序和

样例输入 Copy
6 4
1 -3 5 1 -2 3
样例输出 Copy
7
提示
30%满足 n,m<=100
50%满足 n,m<=3000
100%满足n,m<=300000

  • 思路分析:
    单调队列
    需要满足两个性质:

  • 队列内具有一定的单调性(优先队列)。
    满足普通队列性质,一端进,另一端出,不可以中间插队。
    但是这样就会现矛盾了,例如一个单调增的队列:1,5,8,9,我们要插入4,这时如果只能从尾端进去的话就打破了其单调性,呢么这时的做法就是从队尾到队头,把大于4的全部T了,然后插入后的队列就变成了1,4。

  • 应用
    常用于优化动态规划(DP)问题。
    代码

#include<iostream>//线性筛素数
#include<math.h>
#include<stdio.h>
#include<string.h>
#include <algorithm>
#define ll long long int
#define inf 0x3f3f3f3f
const int mod=998244353;
using namespace std;
const int maxn=300006;

ll n,q,m,t,p,l,r,sum,c[maxn];
ll a[maxn],b[maxn];

int main () {
	cin>>n>>m;
	b[0]=0;
	for(int i=1; i<=n; i++) {
		cin>>b[i];
		b[i]+=b[i-1];
	}
	l = 1, r = 1, sum= -maxn;
	c[1] = 0;
	for (int i = 1; i <= n; i++) {
		while (l <= r && c[l] < i - m) l++;
		sum = max(sum, b[i] - b[c[l]]);
		while (l <= r && b[c[r]] >= b[i]) r--;
		c[++r] = i;
	}
	cout<<sum<<endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值