单调队列简单应用——最大子序和

该博客介绍如何利用单调队列解决在长度为n的整数序列中找到不超过m的连续子序列,使其和最大的问题。当m分别为4、2、3时,给出了不同的最大子序和示例,并提出O(nlogn)复杂度的解决方案,通过前缀和和双端队列来优化算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description
输入一个长度为n的整数序列,从中找出一段不超过m的连续子序列,使得整个序列的和最大。 例如 1,-3,5,1,-2,3 当m=4时,S=5+1-2+3=7 当m=2或m=3时,S=5+1=6。
Input
第一行两个数n,m(n,m<=300000) 第二行有n个数,要求在n个数找到最大子序和。
Output
一个数,即最大子序和S(S值不超过long long int)。

数据很大,最多允许O(nlogn)的算法,暴力的省省吧;
通读题目,可能比较难以与单调队列扯上联系,但是又想到,子序和的求法,常用方法是前缀和相减,即对于任意k<j<n
序列k-j的和表示为sum[j]-sum[k],这两个数分别是前j个和前k个的数字和;
既然如此,为什么不用队列去维护呢?
考虑到这里我们求序列和,显而易见,对于从j开始的序列,j之前的序列无用,需要pop走,然而后来的队列需要排在后面,我们就用双端队列来维护。
代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
#define file
#define maxn 300005
#include<deque>
using namespace std;
struct node{
	long long int num,pos;
};
node sum[maxn];
deque<node> k;
long long ans=-999999999;
int main()
{
	#ifdef file
	freopen("sum.in","r",stdin);
	freopen("sum.out","w",stdout);
	#endif
	
	int m,n;
	cin>>m>>n;
	for(int r=1;r<=m;r++)
	{
		cin>>sum[r].num;
		sum[r].pos=r;
		sum[r].num+=sum[r-1].num;//存和,利用和之差直接求区间值 
### 单调递增/递减数组的最大算法 对于单调递增或递减数组的最大问题,可以采用动态规划的方法来解决。以下是详细的解释以及实现。 #### 动态规划的核心思想 通过分别维护两个数组 `inc` `dec` 来记录当前索引处的最长递增最长递减列的[^1]。 - 对于每一个位置 `i`,计算以该位置结尾的最长递增列的存储在 `inc[i]` 中。 - 类似地,计算以该位置开头的最长递减列的存储在 `dec[i]` 中。 - 最终的结果可以通过遍历整个数组并取 `inc[i] + dec[i] - nums[i]` 的最大值获得(因为 `nums[i]` 被加了两次)。 #### 算法步骤描述 定义输入数组为 `nums`,其长度为 `n`: 1. 初始化两个数组 `inc[n]` `dec[n]`,用于保存每个位置上的递增递减列的最大和。 2. 使用两层循环填充 `inc[]` 数组:外层从左向右迭代,内层查找之前所有可能构成递增关系的位置,并更新 `inc[i]` 值。 3. 同样方式构建 `dec[]` 数组,但是方向是从右往左。 4. 计算全局最大值作为最终结果。 下面是基于上述逻辑的具体 Python 实现: ```python def max_monotone_subsequence_sum(nums): n = len(nums) if n == 0: return 0 inc = [num for num in nums] # Initialize with the value of each element itself. dec = [num for num in nums] # Fill 'inc' array (longest increasing subsequence sum ending at index i). for i in range(1, n): for j in range(i): if nums[j] < nums[i]: if inc[i] < inc[j] + nums[i]: inc[i] = inc[j] + nums[i] # Fill 'dec' array (longest decreasing subsequence sum starting from index i). for i in reversed(range(n)): for j in range(i+1, n): if nums[j] < nums[i]: if dec[i] < dec[j] + nums[i]: dec[i] = dec[j] + nums[i] result = float('-inf') for i in range(n): current_max = inc[i] + dec[i] - nums[i] # Avoid double counting nums[i]. if result < current_max: result = current_max return result # Example usage: example_array = [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15] print(max_monotone_subsequence_sum(example_array)) # Output should be computed based on logic above. ``` 此代码实现了寻找任意数组中的最大单调的功能。它利用了动态规划的思想,在时间复杂度上达到了 O(n²),适合处理中小规模的数据集。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值