CH1201 最大子序和 (单调队列)
题目链接:
题目描述
输入一个长度为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 最大子序和 (单调队列)的更多相关文章
- CH 1201 - 最大子序和 - [单调队列]
题目链接:传送门 描述输入一个长度为n的整数序列,从中找出一段不超过m的连续子序列,使得整个序列的和最大. 例如 $1,-3,5,1,-2,3$. 当 $m=4$ 时,$S=5+1-2+3=7$:当 ...
- 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 ...
- hdu 6319 逆序建单调队列
题目传送门//res tp hdu 维护递增单调队列 根据数据范围推测应为O(n)的. 我们需要维护一个区间的信息,区间内信息是"有序"的,同时需要在O(1)的时间进行相邻区间的信 ...
- 单调栈&单调队列学习笔记!
ummm,,,都是单调系列就都一起学了算了思想应该都差不多呢qwq 其实感觉这俩没有什么可说的鸭QAQ就是维护一个单调的东西,区别在于单调栈是一段进一段出然后单调队列是一段进另一段出?没了 好趴辣重点 ...
- 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 输 ...
- 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 输入 ...
- AcWing:135. 最大子序和(前缀和 + 单调队列)
输入一个长度为n的整数序列,从中找出一段长度不超过m的连续子序列,使得子序列中所有数的和最大. 输入格式 第一行输入两个整数n,m. 第二行输入n个数,代表长度为n的整数序列. 同一行数之间用空格隔开 ...
- 【动态规划】【单调队列】tyvj1305 最大子序和
http://blog.csdn.net/oiljt12138/article/details/51174560 单调队列优化dp #include<cstdio> #include< ...
- tyvj1305 最大子序和(单调队列
题目地址:http://www.joyoi.cn/problem/tyvj-1305 最大子序和 题目限制 时间限制 内存限制 评测方式 题目来源 1000ms 131072KiB 标准比较器 Loc ...
随机推荐
- 微信小程序,获取二维码
微信小程序,获取二维码 找到一篇很实用的博客,他已经写得很详细了,自己也懒得写,亲测有效 参考网址
- Mosaic
Mosaic 是最古老的WEB浏览器,这是个套件FOR WINDOWS(包括TCP/IP,拨号,EMAIL等).
- textarea高度随文本内容变化,且不出现滚动条
通常文本域的写法如下 <textarea type="text" class="form-control pull-left" id="desc ...
- 【Java】 java判断字符串是否为空的方法总结
以下是java 判断字符串是否为空的四种方法: 方法一: 最多人使用的一个方法, 直观, 方便, 但效率很低: if(s == null ||"".equals(s));方法二: ...
- wait/notify方法
执行wait方法会释放锁,执行notify不会释放锁 package com.qf.test05.pojo; /** * @author qf * @create 2018-09-18 10:41 * ...
- java.sql.BatchUpdateException: ORA-01861: 文字与格式字符串不匹配
解决: to_date(#runtime#,'yyyy-MM-dd HH24:mi:ss'), <!-- 执行时间:DATE -->
- 配置ssh免密登录问题
有小伙伴的系统需要做免密登录.配置比较简单,ssh-keygen然后生成authorized_keys 文件即可. 但是配置好之后,修改相应用户的家目录权限后,则免密登录就失效了. 经过试验,发现家目 ...
- ubuntu 下 使用 Git 维护 linux kernel版本
学习linux内核一段时间,意识到内核的版本需要严格控制.利用Git工具可以很轻松的完成不同开发人员不同模块之间的代码融合与版本控制 . 1. 首先,安装Git .可以参考廖雪峰的博客 https: ...
- Makefile中的$(addprefix),添加前缀,指定目标生成目录
先给大家看段Makefile的代码吧: INCLUDE_DIR=usr/java/jdk1..0_25/include \ usr/java/jdk1..0_25/include/linux INCL ...
- Oracle数据库创建与连接
一.Oracle数据库的安装 1.下载Oracle数据库 网址:Oracle 数据库软件下载 | Oracle 技术网 | Oracle 由于需要注册,所以我就没有采用这种下载方式, 右击该网页查看 ...