题目链接:

AcWing

牛客

题目描述

输入一个长度为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,m \leq 300000\))

第二行有n个数,要求在n个数找到最大子序和

输出描述:

一个数,数出他们的最大子序和

示例1

输入

6 4
1 -3 5 1 -2 3

输出

7

思路

单调队列

单调队列模板题

首先这是区间和的问题,先求前缀和 \(sum\)。题目转化为求最大的 \(sum[r] - sum[l]\) 且 \(r - l <= m\)。

枚举右端点 \(r\),维护左端点 \(l \in [r - m, r - 1]\),保持 \(sum[l]\) 最小。

如果某个位置 \(k < l\),且 \(sum[k] \ge sum[l]\),那么直接舍弃 \(k\)。因为 \(l\) 更靠近 \(r\) 且 \(sum[l] <= sum[k]\),这意味着 \(l\) 的生存能力更强。

因此维护一个前缀和递增的单调队列,保持队尾的元素的下标与队首的元素的下标之差不超过 \(m\)。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e5 + 10; int n, m;
ll sum[maxn];
int q[maxn]; void solve() {
ll ans = 0;
int l = 1, r = 1;
q[l] = 0;
for(int i = 1; i <= n; ++i) {
while(l <= r && i - q[l] > m) ++l;
ans = max(ans, sum[i] - sum[q[l]]);
while(l <= r && sum[i] <= sum[q[r]]) --r;
q[++r] = i;
}
cout << ans << endl;
} int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m;
for(int i = 1; i <= n; ++i) {
ll x;
cin >> x;
sum[i] = sum[i - 1] + x;
}
solve();
return 0;
}

deque 版本

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e5 + 10; int n, m;
struct Node {
int id; ll val;
} node[maxn]; void solve() {
ll ans = 0;
deque<Node> q;
for(int i = 1; i <= n; ++i) {
while(!q.empty() && i - q.front().id > m) q.pop_front();
ans = max(ans, node[i].val - q.front().val);
while(!q.empty() && node[i].val <= q.back().val) q.pop_back();
q.push_back(node[i]);
}
cout << ans << endl;
} int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m;
for(int i = 1; i <= n; ++i) {
ll x;
cin >> x;
node[i].val = node[i - 1].val + x;
node[i].id = i;
}
solve();
return 0;
}

参考

《算法竞赛进阶指南》 李煜东 著

CH1201 最大子序和 (单调队列)的更多相关文章

  1. CH 1201 - 最大子序和 - [单调队列]

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

  2. CH1201 最大子序和

    http://contest-hunter.org:83/contest/0x10%E3%80%8C%E5%9F%BA%E6%9C%AC%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9 ...

  3. hdu 6319 逆序建单调队列

    题目传送门//res tp hdu 维护递增单调队列 根据数据范围推测应为O(n)的. 我们需要维护一个区间的信息,区间内信息是"有序"的,同时需要在O(1)的时间进行相邻区间的信 ...

  4. 单调栈&单调队列学习笔记!

    ummm,,,都是单调系列就都一起学了算了思想应该都差不多呢qwq 其实感觉这俩没有什么可说的鸭QAQ就是维护一个单调的东西,区别在于单调栈是一段进一段出然后单调队列是一段进另一段出?没了 好趴辣重点 ...

  5. 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 输 ...

  6. 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 输入 ...

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

    输入一个长度为n的整数序列,从中找出一段长度不超过m的连续子序列,使得子序列中所有数的和最大. 输入格式 第一行输入两个整数n,m. 第二行输入n个数,代表长度为n的整数序列. 同一行数之间用空格隔开 ...

  8. 【动态规划】【单调队列】tyvj1305 最大子序和

    http://blog.csdn.net/oiljt12138/article/details/51174560 单调队列优化dp #include<cstdio> #include< ...

  9. tyvj1305 最大子序和(单调队列

    题目地址:http://www.joyoi.cn/problem/tyvj-1305 最大子序和 题目限制 时间限制 内存限制 评测方式 题目来源 1000ms 131072KiB 标准比较器 Loc ...

随机推荐

  1. python 的装饰器,

    昨天去面试,发现了装饰器还是不太熟悉, 笔试题目是: 随意编写两个对输入参数做加减乘除运算的函数(需要有除法),写完后,用装饰器实现对函数出现除数为0的异常捕获,如果有异常,使用print打印日志. ...

  2. js类型问题

    js比较数据一定要记得鉴别类型是否一致,number类型转换string 需要用到toString方法

  3. c# DataTable select 过滤返回新DataTable

    Select(); Select("id>='3' and name='3--hello'");//支持and Select("id>='3' or id=' ...

  4. sublime useful packages

    Package control Prefixr Emmet

  5. 解决:The “https://packagist.laravel-china.org/packages.json” file could not be downloaded

    使用composer安装错误提示: The "https://packagist.laravel-china.org/packages.json" file could not b ...

  6. 用php写爬虫去爬数据

    参考文档1 参考文档2 这里是我自己写的一个小需求 <?php /** 采集http://www.959.cn/school,即时更新的最新的文章内容:每分钟采集一次.采集结束后实时入库并展示. ...

  7. POJ 1797 Heavy Transportation (最大生成树)

    题目链接:POJ 1797 Description Background Hugo Heavy is happy. After the breakdown of the Cargolifter pro ...

  8. sparkSQL获取DataFrame的几种方式

    sparkSQL获取DataFrame的几种方式 1. on a specific DataFrame. import org.apache.spark.sql.Column df("col ...

  9. tushare积分怎么获得 tushare pro 积分充值 积分转让

    本人是做量化投资的,团队转型,换了交易策略,手头有多个离职同事的闲置转让.600分:原价50元,仅需39元1500分:原价150元,仅需109元(售罄)2000分:原价200元,仅需149元5000分 ...

  10. Javascript中的Date()对象

    创建一个指定的事件对象 需要在构造函数中传递一个表示时间的字符串作为参数例:var d2=new Date("8/27/2019"); 如果直接使用构造函数创建一个Date对象,则 ...