POJ 2823 (滑动窗口)
这道题最容易想到的是用朴素的做法,即 每滑动一次,就遍历一次窗口找出最大最小值,这样时间复杂度为O(n*k),由于题目数据比较大,这种做法肯定是超时的。
另外,根据书上的讲解,还可以采用优先队列来求解。用优先队列存储元素下标,根据元素下标找到元素值并进行排序作为优先队列的排序规则。
优先队列的队列首一定是在特定排序规则下的第一个元素。假设优先队列中的元素是大值优先。先用未进行滑动的窗口内元素对优先队列初始化。每向右滑动一次,就需要添加当前元素和删除过期元素。我们需要把当前元素添加到队列中,并且把是当前最大值的过期元素删除,这一步需要循环进行以找出在窗口范围内的当前最大值。如果过期元素不是最大值就不需要删除了,因为反正存在他不会对当前的最大值产生什么影响。
#include <cstdio>
#include <queue>
#include <vector>
#include <iterator>
using namespace std;
vector<int> v;
struct cmp{
bool rev;
cmp(const bool rev=false):rev(rev){}
bool operator()(int s1, int s2){
if(rev) return v[s1] < v[s2];
else return v[s1] > v[s2];
}
};
int main(){
int n , k;
int cnt = ;
int dmax[],dmin[];
scanf("%d%d", &n, &k); for(int i = ; i < n; i++){
int d;
scanf("%d",&d);
v.push_back(d);
}
vector<int>::iterator it = v.begin();
advance(it,k);
priority_queue<int,vector<int>,cmp> qmax(cmp(true));
priority_queue<int,vector<int>,cmp> qmin;
for(int i = ; i < k; i++){
qmax.push(i);
qmin.push(i);
}
dmax[cnt] = v[qmax.top()];
dmin[cnt] = v[qmin.top()];
cnt++;
for(int i = k; i < n; i++,++cnt){
qmax.push(i);
qmin.push(i);
while(i - qmax.top() >= k){
qmax.pop();
}
dmax[cnt] = v[qmax.top()];
while(i - qmin.top() >= k){
qmin.pop();
}
dmin[cnt] = v[qmin.top()];
}
for(int i = ; i < cnt; i++){
printf("%d ",dmax[i]);
}
printf("\n");
for(int i = ; i < cnt; i++){
printf("%d ",dmin[i]);
}
printf("\n");
return ;
}
这种做法时间复杂度为O((n-k)logk)。然而提交之后还是超时。因此只能寻求更高效的解决方法——单调队列。
单调队列中的元素是严格单调的。我们在求解这个问题的时候需要维护他的单调性。队首元素即为当前位置的最大值。
假设要求滑动窗口中的最大值。我们就需要确保滑动窗口中的元素从队首到队尾是递减的。每滑动一次就判断当前元素和队尾元素的关系,如果放入队尾满足单调递减,那么放入即可;如果放入不满足,就需要删除队尾元素直到放入当前元素之后满足队列单调递减。同时要确保已经出窗口的最大值(队首元素)被删除掉。
#include <cstdio>
#include <deque>
#include <vector>
using namespace std;
const int maxn = + ;
vector<int> v;
int dmax[maxn];
int dmin[maxn];
int main(){
int n, k;
scanf("%d%d", &n, &k);
for(int i = ; i < n; i++){
int d;
scanf("%d", &d);
v.push_back(d);
}
deque<int> qmax;
deque<int> qmin;
for(int i = ; i < n; i++){
while(!qmax.empty() && v[i] > v[qmax.back()])
qmax.pop_back();
if(!qmax.empty() && i - qmax.front() >= k)
qmax.pop_front();
qmax.push_back(i);
while(!qmin.empty() && v[i] < v[qmin.back()])
qmin.pop_back();
if(!qmin.empty() && i - qmin.front() >= k)
qmin.pop_front();
qmin.push_back(i);
dmax[i] = v[qmax.front()];
dmin[i] = v[qmin.front()];
}
for(int i = k-; i < n-; i++)
printf("%d ", dmin[i]);
printf("%d\n", dmin[n-]);
for(int i = k-; i < n-; i++)
printf("%d ", dmax[i]);
printf("%d\n", dmax[n-]);
return ;
}
POJ 2823 (滑动窗口)的更多相关文章
- POJ 2823 滑动窗口 单调队列模板
我们从最简单的问题开始: 给定一个长度为N的整数数列a(i),i=0,1,...,N-1和窗长度k. 要求: f(i) = max{a(i-k+1),a(i-k+2),..., a(i)},i = 0 ...
- POJ 2823 滑动窗口 单调队列
https://vjudge.net/problem/POJ-2823 中文:https://loj.ac/problem/10175 题目 给一个长度为 $N$ 的数组,一个长为 $K$ 的滑动窗体 ...
- 洛谷P1886 滑动窗口(POJ.2823 Sliding Window)(区间最值)
To 洛谷.1886 滑动窗口 To POJ.2823 Sliding Window 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每 ...
- POJ - 2823 Sliding Window (滑动窗口入门)
An array of size n ≤ 10 6 is given to you. There is a sliding window of size kwhich is moving from t ...
- 【POJ 2823】【Luogu P1886】Sliding Window 滑动窗口
POJ 2823 Luogu P1886 [解题思路] 这是一个单调队列算法的经典题目,几乎学习单调队列的人都接触过这题. 利用单调队列算法求出每一个固定区间内的最(大/小)值. 以下以最大值为例: ...
- POJ 3320 Jessica's Reading Problem (滑动窗口)
题意:给定一个序列,求一个最短区间,使得这个区间包含所有的种类数. 析:最近刚做了几个滑动窗口的题,这个很明显也是,肯定不能暴力啊,时间承受不了啊,所以 我们使用滑动窗口来解决,要算出所有的种数,我用 ...
- POJ 2823 Sliding Window + 单调队列
一.概念介绍 1. 双端队列 双端队列是一种线性表,是一种特殊的队列,遵守先进先出的原则.双端队列支持以下4种操作: (1) 从队首删除 (2) 从队尾删除 (3) 从队尾插入 (4) ...
- Sliding Window POJ - 2823 单调队列模板题
Sliding Window POJ - 2823 单调队列模板题 题意 给出一个数列 并且给出一个数m 问每个连续的m中的最小\最大值是多少,并输出 思路 使用单调队列来写,拿最小值来举例 要求区间 ...
- Luogu P1886 滑动窗口
P1886 滑动窗口 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The a ...
随机推荐
- flume搭建新手测试环境
硬件环境: 腾讯云,两台服务器8G 双核 软件环境: flume1.8.jdk1.8,centos6 第一次搭建也是各种找文件,只知道flume是日志抓取服务,也听说了非常稳定强大的服务,正好公司需要 ...
- VxWorks 7 技术简介
VxWorks 7 是新一代的嵌入式实时操作系统,全新的架构设计,灵活化的组件配置,高可靠性与安全性,丰富的第三方软件包,极大的方便用户的开发和使用.本文对VxWorks7 的功能做个简要的记录. V ...
- 【C】关键字void的用法
void有两种功能 [1]没有 [2]任意类型 void出现的位置不同会有不同的解释 [1]void func( void ) func左边的void,代表『没有返回值』 func右边的括弧里的voi ...
- DOM中的事件傳播機制
要講到事件傳播機制之前,首先要瞭解的是 什麼是事件? 事件,發生在靜態頁面與動態行為之間的交互行為.是JavaScript 和 HTML的交互是通过事件实现的.比如,按鈕的點擊,鼠標的滑過,鍵盤的輸入 ...
- pip快速git项目安装
pip install git+https://github.com/xx/xx.git
- JZ2440开发板:UART(串口)使用(学习笔记)
查看UART在硬件上的信息,阅读JZ2440原理图可以看到: JZ2440开发板的UART0是可以跟USB相接的,用于打印调试,UART1,UART2两个串口用来外接模块.所以本文仅对UART0进行操 ...
- 成都Uber优步司机奖励政策(1月27日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- Android Stadio配置了gralde的本地路径,但是windos 命令行还是会下载gradle
如下图: 已经在stadio 里面设置了gradle 的路径,但是在cmd 命令行里面不会去用这个路径. 解决方案:需要在环境变量里面设置一个gradle home GRADLE_USER_HOME ...
- spring源码-bean之增强初始化-3
一.ApplicationContext的中文意思是“应用上下文”,它继承自BeanFactory接口,除了包含BeanFactory的所有功能之外,在国际化支持.资源访问(如URL和文件).事件传播 ...
- MAC 更新brew 镜像源
mac 更新brew镜像源 cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core" git remote set-url o ...