[洛谷P1886]滑动窗口 (单调队列)(线段树)
---恢复内容开始---
这是很好的一道题
题目描述:
现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口。
现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。
例如:
队列 [1 3 -1 -3 5 3 6 7]
窗口大小为3.
则如下图所示:

输入输出格式:
输入格式:
输入一共有两行,第一行为n,k。
第二行为n个数(<INT_MAX).
输出格式:
输出共两行,第一行为每次窗口滑动的最小值
输入样例:
- -
输出样例:
- - - -
解决方案:
(一)st表
(二)线段树
这里用到了两个结构体,然后就是进行普通的线段树求最大最小,这里就不再赘述了q
第一个结构体是查询用的
第二个结构体就是线段树了,这里我用了一个构造函数;
其实这些操作只是为了加速我们的线段树过程(让它别T)
不过总体地实现还是相对比较优美(复杂)的q
Code:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define inf 2147483647
using namespace std;
int a[],n,k;
struct search_tree
{
int minn;
int maxn;
}q;
struct Segtree
{
int minv[],maxv[];
void pushup(int rt)
{
maxv[rt] = max(maxv[rt<<],maxv[rt<<|]);
minv[rt] = min(minv[rt<<],minv[rt<<|]);
}
void build(int rt,int l,int r)
{
if(l == r)
{
maxv[rt] = a[l];
minv[rt] = a[l];
return ;
}
int mid = (l + r)>>;
build(rt<<,l,mid);
build(rt<<|,mid+,r);
pushup(rt);
}
search_tree solve(int rt,int l,int r,int ll,int rr) //ll rr 为待求量
{
if(ll <= l && rr >= r)
return (search_tree)
{
minv[rt],
maxv[rt]
};
int mid = (l+r)>>;
int minn = inf , maxn = -inf;
search_tree ans;
if(ll <= mid)
{
ans = solve(rt<<,l,mid,ll,rr);
maxn = max(maxn,ans.maxn);
minn = min(minn,ans.minn);
}
if(rr > mid)
{
ans = solve(rt<<|,mid+,r,ll,rr);
maxn = max(maxn,ans.maxn);
minn = min(minn,ans.minn);
}
return (search_tree)
{
minn,
maxn
};
}
}segtree;
int main()
{
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
segtree.build(,,n);
for(int i=;i<=n - k + ;i++)
{
q = segtree.solve(,,n,i,i + k - );
printf("%d ",q.minn);
a[i] = q.maxn;
}
printf("\n");
for(int i=;i<=n-k+;i++)
printf("%d ",a[i]);
return ;
}
(三)单调队列
单调队列概念:
队列中的元素其对应在原来的列表中的顺序必须是单调递增的。
队列中元素的大小必须是单调递*(增/减/甚至是自定义也可以)
这保证了单调队列的双有序
但是单调队列有一个特殊的特点就是可以双向操作出队。
但是我们并不是把单调队列里的每一个数都要存一遍,我们只需要存储这些单调队列里有序环境中有序的数(即我们所要求的目的)
这个概念还是很抽象的q
不过从这个题来看还是可以有所帮助的q
并不是每一个数的记录都是有意义的;
我们只需要存储那些对于我们来说有意义的数值;
以此题求最小值为栗子:
若有ai和aj两个数,且满足i<j。
如果ai>aj,那么两个数都应该记录;
但是如果ai≤aj,那么当aj进入区间后,ai的记录就没有意义了。
我们假设每个数能作为区间最大值的次数(即它可以存在区间内的次数)为它的贡献,当aj进入区间以后,在区间中存在的时间一定比ai长,也就说明ai一定不会再做贡献了;
我们确定没有贡献的点,便可以直接删去
Code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define MAXN 1008666
using namespace std;
struct Node
{
int v;
int pos;
}node[MAXN << ];
int n,a[MAXN << ],h = ,t,k;
int m;
int main()
{
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
for(int i=;i<=n;i++) //维护单调递减队列
{
while(h <= t && node[h].pos + k <= i)
h++;
while(h <= t && node[t].v >= a[i])
t--;
node[++t].v = a[i];
node[t].pos = i;
if(i >= k)
printf("%d ",node[h].v);
}
h = ;
t = ;
printf("\n");
for(int i=;i<=n;i++) //维护单调递增队列
{
while(h <= t && node[h].pos + k <= i)
h++;
while(h <= t && node[t].v <= a[i])
t--;
node[++t].v = a[i];
node[t].pos = i;
if(i >= k)
printf("%d ",node[h].v);
}
return ;
}
[洛谷P1886]滑动窗口 (单调队列)(线段树)的更多相关文章
- 洛谷 P1886 滑动窗口(单调队列)
题目链接 https://www.luogu.org/problemnew/show/P1886 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始 ...
- 洛谷P1886 滑动窗口(POJ.2823 Sliding Window)(区间最值)
To 洛谷.1886 滑动窗口 To POJ.2823 Sliding Window 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每 ...
- 洛谷P4198 楼房重建 单调栈+线段树
正解:单调栈+线段树 解题报告: 传送门! 首先考虑不修改的话就是个单调栈板子题昂,这个就是 然后这题的话,,,我怎么记得之前考试好像有次考到了类似的题目昂,,,?反正我总觉着这方法似曾相识的样子,, ...
- 洛谷 P1886 滑动窗口(单调队列)
嗯... 题目链接:https://www.luogu.org/problem/P1886 首先这道题很典型,是标准的单调队列的模板题(也有人说单调队列只能解决这一个问题).这道题可以手写一个队列,也 ...
- [Luogu P1886]滑动窗口--单调队列入门
题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array i ...
- 洛谷 P1886 滑动窗口 (数据与其他网站不同。。)
题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array i ...
- 洛谷 P1886 滑动窗口
题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array i ...
- 洛谷——P1886 滑动窗口|| POJ——T2823 Sliding Window
https://www.luogu.org/problem/show?pid=1886#sub || http://poj.org/problem?id=2823 题目描述 现在有一堆数字共N个数字( ...
- [POJ2823][洛谷P1886]滑动窗口 Sliding Window
题目大意:有一列数,和一个窗口,一次能框连续的s个数,初始时窗口在左端,不断往右移动,移到最右端为止,求每次被框住的s个数中的最小数和最大数. 解题思路:这道题是一道区间查询问题,可以用线段树做.每个 ...
随机推荐
- try? try! try do catch try 使用详解
当一个使用一个方法发现后面 throws 说明可能会抛出异常 需要try 进行处理 1 try? 如果解析成功就有值 否则返回nil (推荐) 2 try! 如果解析成功就有值 否则直接崩溃 ...
- ionic3 点击输入 框弹出白色遮罩 并把 界面顶到上面
这个蛋疼 问题 ,在android 上面遇到这种情况 ,键盘弹出的时候 总有一个白色的遮罩在后面出现,网上查了很久都没发现原因. 偶然发现一个方法 ,试下了下 问题解决了. 代码如下: IonicMo ...
- 小学生都看得懂的C语言入门(6): 字符串
1.字符用 char 表示 #include<stdio.h> int main() { char c; char d; c=; d='; if (c==d){ printf(" ...
- jenkins持续集成:jenkins+SVN
实现jenkins从svn拉取最新的代码,再执行驱动脚本进行自动化测试 新建一个任务 输入任务名,选“构建一个自由风格的软件项目”,点左下角“确定” 丢弃旧的构建,如下设置为保留3天内的10条构建记录 ...
- 开放系统的直连式存储(Direct-Attached Storage,简称DAS)
开放系统的直连式存储(Direct-Attached Storage,简称DAS)已经有近四十年的使用历史,随着用户数据的不断增长,尤其是数百GB以上时,其在备份.恢复.扩展.灾备等方面的问题变得日益 ...
- windows 下命令行启动停止mysql
MySQL比较好玩一点就是它可以用多种方式启动,当然它也可以用多种方式关闭.下面我就mysql的几种启动方式简单的谈一谈,希望可以给大家提供一些参考. 第一种,用mysqld-nt来启动. 在没有进行 ...
- 论文阅读笔记十一:Rethinking Atrous Convolution for Semantic Image Segmentation(DeepLabv3)(CVPR2017)
论文链接:https://blog.csdn.net/qq_34889607/article/details/8053642 摘要 该文重新窥探空洞卷积的神秘,在语义分割领域,空洞卷积是调整卷积核感受 ...
- linux基础练习题(1)
Linux命令作业(关卡一) 练习题1 理解操作系统的作用,以及各种操作系统的不同 要求: 简述什么是OS 简述应用程序.硬件.OS的关系 列举出3种常见的操作系统 简述Ubuntu和Linux的关系 ...
- 华为设备默认console密码
admin@huawei.com Admin@huawei.com Admin@huawei huawei.com huawei@123 huawei Change_Me
- cmake方式使用vlfeat
目录 environment statement compile vlfeat with cmake compile example project with cmake 1. make sure c ...