【洛谷P1886】滑动窗口
2024-09-02 10:03:12
滑动窗口
【题目描述】
有N个数字,以及一个大小为k的窗口。现在这个窗口从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。
思路:
k<=N<=1000000,暴力是拿不到全分的,要想解决这个问题,理想的时间复杂度应是O(n),我们可以用一个单调队列维护。
单调队列原理:
以维护最大值为例:
对于每个新加入区间的值,显而易见的是:对于向右移动的“窗口”,即当前长度为n的区间中,若存在data[q[i]]比data[q[j]]大且q[i]>q[j](q[i]表示队列中的第i个元素的编号,data[i]表示编号为i的元素的值),则可以保证q[j]在以后的区间取最大值时是不会产生影响的,我们便可以将q[j]删除,从而得到更加优秀的时间复杂度,所以,当一个新的值入队时,便可以将在其前面入队且值比它小的元素删除。 我们便可以发现可以用一个单调队列维护。 当然,对于不在当前区间内的“老”元素,要把它从队列中删除。
贴代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,k,a[],queue[],tail,head=,i;
int main()
{
scanf("%d%d",&n,&k);
for(i=;i<=n;i++)
scanf("%d",&a[i]);
//最小值 单调递减的队列
for(i=;i<=k;i++) //前k个数入队
{
while(a[i]<=a[queue[tail]]&&tail>=head)
tail--;
queue[++tail]=i;
}
for(i=k;i<=n;i++) //k+1~n依次入队
{
while(a[i]<=a[queue[tail]]&&tail>=head)
tail--;
queue[++tail]=i;
if(queue[head]<i-k+) head++;
printf("%d ",a[queue[head]]);
}
puts("");
//最大值 单调递增的队列
memset(queue,,sizeof(queue));
for(i=;i<=k;i++)
{
while(a[i]>=a[queue[tail]]&&tail>=head)
tail--;
queue[++tail]=i;
}
for(i=k;i<=n;i++)
{
while(a[i]>=a[queue[tail]]&&tail>=head)
tail--;
queue[++tail]=i;
if(queue[head]<i-k+) head++;
printf("%d ",a[queue[head]]);
}
return ;
}
最新文章
- Koa2 的安装运行记录(二)
- jQuery 2.0.3 源码分析 事件绑定 - bind/live/delegate/on
- java 连接数据库之一个完整的函数
- spring 声明式事务管理
- C#遍历指定文件夹中的所有文件和子文件夹
- FL2440驱动添加(3)LCD驱动添加学习笔记
- python实现简易数据库之二——单表查询和top N实现
- HTML你应该知道的三大基本元素
- cocos2dx-lua 批量打包及修改
- Windows 下 Composer 与 Laravel 4 的安装
- apache solr简单搭建
- Laravel之路——事务
- 3D objects key rendering steps
- mongodb分页优化
- Android自己定义组件系列【5】——高级实践(1)
- Openjudge-计算概论(A)-1的个数
- ssh用法及命令
- 把mysql脚本或其他数据库脚本导入Powerdesigner
- Alpha冲刺-(9/10)
- [原]Windows Azure开发之Linux虚拟机