单调队列(数列中长度不超过k的子序列和的最值)
★实验任务
小 F 很爱打怪,今天因为系统 bug,他提前得知了 n 只怪的出现顺序以及击 倒每只怪得到的成就值 ai。设第一只怪出现的时间为第 1 秒,这个游戏每过 1 秒 钟出现一只新怪且没被击倒的旧怪消失。小 F 决定发动一次技能,他的技能最多 维持 k 秒,他希望获得最大的成就值,请你帮他计算他发动技能的时间 l 和技能 结束时间 r(r-l+1<=k)。当存在多种方案使得成就值最大时,选择技能发动时间 l 最小的方案,再选择技能持续时间 r-l+1 最小的方案。
★数据输入
输入第一行为两个正整数 n(1<=n<=100000),k(0<k<=n),表示出现 n 只怪, 小 F 的技能最多维持 k 秒。 输入第二行为 n 个整数,表示小 F 击倒第 i 秒钟出现的怪能给有获得的成就 值 ai(-1000<=a[i]<=1000)。
★数据输出
输出为一行三个数。第一个数为可获得的最大成就值,第二个数为技能发动 时间 l,第三个数为技能结束时间 r。
测试样例
输入:
6 3
-1 2 6 5 -5 6
输出:
6 4 6
单调队列的自我理解(这个例子是从某个大神的博客中看到的):
例题:有一组数据1,5,9,4,7,8,6,他们会依此输入,同时,在某一时刻会让你求出后n个数中的最大值。
根据题意,我们可以得出这样一个结论,若后一个数大于前一个数,则结果必定不会是前一个数(比如现在输入了1,5,由于1<5,所以无论是后几个数中的最大值均不会为1),因此,我们只需维护一个单调递减的数组便可快速求得所需值。(数组变化如下:输入——1,数组——1;输入——5,由于5>1删去1添入5,数组——5;输入——9,由于9>5删去5添入9,数组——9;输入——4,由于4<9直接添入,数组——9,4;输入——7,由于7>4同时7<9因此删去4添入7,数组——9,7;输入——8,由于8>4同时8<9因此删去7添入8,数组——9,8;输入——6,由于6<8直接添入,数组——9,8,6。)总的来说,它的本质就是当你在插入一个值时,应将在他之前存入的所有小于他的数值剔除,再将他存入数组中。
xfdg题解题思路:显然暴力是行不通的,对于此类子序列求和以及存储下标的问题通常是可以用单调队列写的,用一个sum数组储存数列的前缀和,然后通过一个que数组根据题目意思存储数组下标。
代码:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define MAX 100005
#define INF 100000000
using namespace std;
int sum[MAX] = { 0 };
int que[MAX];
int main()
{
int n, k, i, j;
cin >> n >> k;
for (i = 1; i <= n; i++)
{
int tmp;
cin >> tmp;
sum[i] = sum[i - 1] + tmp;
}
int front = 0, tail = 0, ans = -INF;
int ansr, ansl;
for (i = 1; i <= n; i++)
{
while (tail > front&&sum[i - 1] < sum[que[tail - 1]])
tail--;
que[tail++] = i - 1;
while (tail > front&&i - que[front] > k)
front++;
if (ans < sum[i] - sum[que[front]])
{
ans = sum[i] - sum[que[front]];
ansl = que[front] + 1; ansr = i;
}
}
printf("%d %d %d\n",ans, ansl, ansr);
return 0;
}
还会写几道有关单调队列的题目,比如求数列中长度内的最大值最小值问题,然后给出链接,多个例题一起看会稍微更好理解一些,到时候再把链接贴上;
更新补充(POJ2823单调队列):博客链接
单调队列(数列中长度不超过k的子序列和的最值)的更多相关文章
- poj 3415 后缀数组 两个字符串中长度不小于 k 的公共子串的个数
Common Substrings Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 11469 Accepted: 379 ...
- HDU 3415 Max Sum of Max-K-sub-sequence【单调队列】
<题目链接> 题目大意: 给你一段从1~N的圆形序列,要你求出这段圆形序列中长度不超过K的最大连续子序列之和是多少,并且输出这子序列的起点和终点. 解题分析: 既然是求连续子序列之和,我们 ...
- 图中长度为k的路径的计数
题意 给出一个有向图,其中每条边的边长都为1.求这个图中长度恰为 $k$ 的路劲的总数.($1 \leq n \leq 100, 1 \leq k\leq 10^9$) 分析 首先,$k=1$ 时答案 ...
- 单调队列以及单调队列优化DP
单调队列定义: 其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的. 单调队列的一般应用: 1.维护区间最值 2 ...
- 单调队列 && 斜率优化dp 专题
首先得讲一下单调队列,顾名思义,单调队列就是队列中的每个元素具有单调性,如果是单调递增队列,那么每个元素都是单调递增的,反正,亦然. 那么如何对单调队列进行操作呢? 是这样的:对于单调队列而言,队首和 ...
- 单调栈&单调队列入门
单调队列是什么呢?可以直接从问题开始来展开. Poj 2823 给定一个数列,从左至右输出每个长度为m的数列段内的最小数和最大数. 数列长度:\(N <=10^6 ,m<=N\) 解法① ...
- 单调队列&单调栈
单调队列 例题: Poj 2823给定一个数列,从左至右输出每个长度为m的数列段内的最小数和最大数.数列长度:N<=106,m<=N 对于单调队列,我们这样子来定义: 1.维护区间最值 2 ...
- hdu 3415 单调队列
Max Sum of Max-K-sub-sequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K ...
- 单调队列优化DP(超详细!!!)
一.概念 1.单调队列定义: 其实单调队列就是一种队列内的元素有单调性(单调递增或者单调递减)的队列,答案(也就是最优解)就存在队首,而队尾则是最后进队的元素.因为其单调性所以经常会被用来维护区间最值 ...
随机推荐
- C语言学习记录_2019.02.08
\n:换行: \t:制表符,相当于大空格: a[5]={2};<------->a[5]={2,0,0,0,0}; 数组初始化的方法:a[5]={0};即全部初始化为0: 数组初始化的 ...
- go 交叉编译,部署
go web 部署 交叉编译 go 语言有个强大的地方就是 交叉编译 windows --cmd 设置环境变量-mac SET CGO_ENABLED=0 SET GOOS=darwin SET GO ...
- Docker:unauthorized: incorrect username or password.
用VS2017编译DockerCompose项目,显示错误:unauthorized: incorrect username or password. 打开命令行工具,输入docker login命令 ...
- 兼容性/pollyfill/shim/渐进增强/优雅降级
http://ued.ctrip.com/blog/browser-compatibility-testing-tools-in-firefox-compatibility-detector.html ...
- 牛客国庆集训派对Day1 B. Attack on Titan
B. Attack on Titan 链接 #include<cstdio> #include<algorithm> #include<cstring> #incl ...
- vivado与modelsim的联合仿真
转载: 一.在vivado中设置modelsim(即第三方仿真工具)的安装路径.在vivado菜单中选择“Tools”——>“Options...”,选择“General”选项卡,将滚动条拉倒最 ...
- 【轮子狂魔】手把手教你自造Redis Client
为什么做Redis Client? Redis Client顾名思义,redis的客户端,主要是封装了一些对于Redis的操作. 而目前用的比较广泛的 ServiceStack.Redis 不学好,居 ...
- Magic Trackpad 2 on win10 x64
可以使用操作: 触击 触击拖拽 双击 支手滚动:上下,左右 右键配置:左下角,右下角点击实现 可以试用28天,收费 $9.5 官方地址:http://www.trackpadmagic.com/mag ...
- hdu1272小希的迷宫(并查集判断回路和是否连通)
传送门 迷宫中不能有回路,还要连通 如果最后集合数是一个那就是连通,否则不联通 要合并的两个顶点在相同集合内,表示出现了回路 输入时注意一下 #include<bits/stdc++.h> ...
- 导入Cardboard SDK后Build到安卓平台出错:Unable to merge android manifests. (已解决)
报错说“Unable to merge android manifests. See the consoler for more details.” 解决方法: 打开SDK Manager ,安装An ...