AcWing:135. 最大子序和(前缀和 + 单调队列)

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

输入格式

第一行输入两个整数n,m。

第二行输入n个数,代表长度为n的整数序列。

同一行数之间用空格隔开。

输出格式

输出一个整数,代表该序列的最大子序和。

数据范围

1≤n,m≤3000001≤n,m≤300000

输入样例:

6 4
1 -3 5 1 -2 3

输出样例:

7

算法:前缀和 + 单调队列

注意:单调队列需要使用双端队列deque,因为其中需要头部弹出以及尾部弹出。

#include <iostream>
#include <cstdio>
#include <deque>

using namespace std;

#define INF 0x3f3f3f3f

const int maxn = 3e5+7;

deque<int> que;

int arr[maxn];
int sum[maxn];

int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &arr[i]);
        sum[i] = sum[i - 1] + arr[i];
    }
    int ans = -INF;
    for(int i = 1; i <= n; i++) {
        while(!que.empty() && i - que.front() > m) {    //如果队列里面的数超过了m的话,就将前面的弹出
            que.pop_front();
        }
        int k;
        if(que.size() > 0) {
            k = que.front();
        } else {
            k = 0;
        }
        ans = max(ans, sum[i] - sum[k]);
        while(!que.empty() && sum[que.back()] >= sum[i]) {      //利用前缀和来维护单调队列,根据前缀和的性质,
            que.pop_back();
        }
        que.push_back(i);
    }
    cout << ans << endl;
    return 0;
}

原文地址:https://www.cnblogs.com/buhuiflydepig/p/11334070.html

时间: 2024-11-06 07:25:30

AcWing:135. 最大子序和(前缀和 + 单调队列)的相关文章

NC17070 矩阵(前缀和+单调队列)

最大子矩阵和问题,一般都是用前缀和先计算行,然后枚举行,在列方向做单调队列 这样的复杂度是N^3,对于几百的数据足够了 #include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<map> #include<string> using namespace std; typedef long long ll; const int N

tyvj 1305 —— 长度不超过m的最大连续和 【前缀和+单调队列】

题目:http://www.tyvj.cn/p/1305 定义: sum[i]=a[1]+a[2]+...+a[i] 即,sum[i]为序列a的前缀和 dp[i] = sum[i] - min(sum[j]) (i-j<m) 即,dp[i]为以i结尾的满足长度不大于m的最大连续和 则: 答案为 max(dp[i]) (1≤i≤n) #include <cstdio> #include <iostream> using namespace std; int sum[300005

Tyvj1305最大子序和(单调队列优化dp)

描述 输入一个长度为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个数找到最大子序和 输出格式 一个数,数出他们的最大子序和 测试样例1 输入 6 4 1 -3 5 1 -2 3 输出 7 备注 数据范围:100%满足n,m<=300000 是不超过m,不是选m个!!!!! /* 单调队列优化dp 单调队列维护的是前

TYVJ1305 最大子序和

P1305 最大子序和 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 输入一个长度为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个数找到最大子序和 输出格式 一个数,数出他们的最大子序和 测试样例1 输入 6 4 1 -3 5 1 -2 3 输出 7 备注 数据范围:10

leetCode-最大子序和53

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6 进阶: 如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解. ==========================方案=========================== 1 /** 2 * 53.Maximum Subarray(最大

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

1.53. 最大子序和 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6. class Solution { public: int maxSubArray(vector<int>& nums) { if(nums.empty()) return 0; int res = nums[0]; int

leetcode53. 最大子序和 &#127775;

题目: 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6.进阶: 如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解. 来源:力扣(LeetCode) 解答: leetcode优秀方案(来自力扣答案统计页,没有明确作者是谁,可留言告知): 1 class Solution: 2 "&qu

Leetcode之动态规划(DP)专题-53. 最大子序和(Maximum Subarray)

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6. 进阶: 如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解. 定义:dp[i] 表示从起点到index=i的这个段内的最大子序和. 例如:dp[1] = 在[-2,1]这个区间里面的最大子序和,dp[1]=1 写出状态转移方程:dp[i

【Leetcode】最大子序和

思路: 分治法.记最大子序和为maxResult,函数为int getMaxSub( *, * ) {}. 向量A= [a1, a2, a3, ...., ai, ai+1, a+2, ......, aj-1, aj], maxResult = max( maxresult(a1, ......, ai),  getMaxSub(*, i+1) ),其中sum(a1, ......, ai) <= 0. class Solution { public: int maxSubArray(vect