poj 2823 Sliding Windows (单调队列+输入输出挂)
Time Limit: 12000MS | Memory Limit: 65536K | |
Total Submissions: 73426 | Accepted: 20849 | |
Case Time Limit: 5000MS |
Description
The array is [1 3 -1 -3 5 3 6 7], and k is 3.
Window position | Minimum value | Maximum value |
---|---|---|
[1 3 -1] -3 5 3 6 7 | -1 | 3 |
1 [3 -1 -3] 5 3 6 7 | -3 | 3 |
1 3 [-1 -3 5] 3 6 7 | -3 | 5 |
1 3 -1 [-3 5 3] 6 7 | -3 | 5 |
1 3 -1 -3 [5 3 6] 7 | 3 | 6 |
1 3 -1 -3 5 [3 6 7] | 3 | 7 |
Your task is to determine the maximum and minimum values in the sliding window at each position.
Input
Output
Sample Input
8 3
1 3 -1 -3 5 3 6 7
Sample Output
-1 -3 -3 -3 3 3
3 3 5 5 6 7
题目大意:
给你长度为n的数列,要你输出1..k, 2..k+1, 3..k+2, ...区间的最大值和最小值。
单调队列经典题。
维护单调不减序列和单调不增序列的下标,这样队首就分别是最小值和最大值的下标。
以单调不减序列举例:
每次向后移动,先删除队尾元素直至小于等于新元素。贪心的思想,之前队尾元素如果比它大,那该队尾元素永远不可能成为某个区间的最小值。
再判断队首元素是否在k区间内。
单调不增序列同理。
单调队列可以用deque写。
对这两个队列考虑,(平摊分析)每个元素最多入队出队两次。复杂度O(n)。
所以TLE总是让人觉得僵硬。On, 1e6, T???
其实是io太慢了。
scanf printf 相对cin cout 来说确实快了,但这个可是1e6+2e6啊 。。 ̄へ ̄
第一次真正明白输入输出挂的含义。
scanf printf 其实就是对putchar getchar 等函数的封装,功能强大但臃肿。所以,要用一些速度比scanf快,但功能比putchar全面的函数取而代之。
输入输出挂(正负整数)。
template <class T>
inline bool scan_d(T &ret)
{
char c;
int sgn;
if (c = getchar(), c == EOF)
{
return ; //EOF
}
while (c != '-' && (c < '' || c > ''))
{
c = getchar();
}
sgn = (c == '-') ? - : ;
ret = (c == '-') ? : (c - '');
while (c = getchar(), c >= '' && c <= '')
{
ret = ret * + (c - '');
}
ret *= sgn;
return ;
} template <class T>
inline void print_d(T x)
{
if(x < )
{
putchar('-'); x = -x;
}
if (x > )
{
print_d(x / );
}
putchar(x % + '');
}
由上面的代码可以看出,输出一个整数的复杂度并不是o1的,取决于输出数的位数,是o(m),m是常数。如果数是int,n又很大(1e6),复杂度其实是o(mn),用printf的话可以当成onlogn+算了,t也不奇怪吧。
不过该挂对C++极度无感(不知道为啥。。),对G++就很真实了。从下图来说,scanf用c++会快一点,不过真遇到大量输出,g++&挂是最佳选择,所以忘了c++吧。
AC代码:
#include <cstdio>
#include <queue>
#include <deque>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
typedef long long ll;
const int maxn=; template <class T>
inline bool scan_d(T &ret)
{
char c;
int sgn;
if (c = getchar(), c == EOF)
{
return ; //EOF
}
while (c != '-' && (c < '' || c > ''))
{
c = getchar();
}
sgn = (c == '-') ? - : ;
ret = (c == '-') ? : (c - '');
while (c = getchar(), c >= '' && c <= '')
{
ret = ret * + (c - '');
}
ret *= sgn;
return ;
} template <class T>
inline void print_d(T x)
{
if(x < )
{
putchar('-'); x = -x;
}
if (x > )
{
print_d(x / );
}
putchar(x % + '');
} int arr[maxn+];
int temp[maxn+];
int ans[maxn][]; int cmp(int x,int y)
{
return arr[x]<arr[y];
} int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++)
scan_d(arr[i]); std::deque<int> incq;//单调不减序列
std::deque<int> decq;//单调不增序列 for(int i=;i<=k;i++)
temp[i]=i;
std::sort(temp+,temp++k,cmp);
for(int i=;i<=k;i++)
{
incq.push_back(temp[i]);
decq.push_front(temp[i]);
}
ans[][]=arr[incq.front()];
ans[][]=arr[decq.front()]; for(int i=k+;i<=n;i++)
{
while(!incq.empty())
{
if(incq.front()+k-<i)
incq.pop_front();
else
break;
}
while(!incq.empty())
{
if(arr[incq.back()]>arr[i])
incq.pop_back();
else
break;
}
incq.push_back(i);
while(!decq.empty())
{
if(decq.front()+k-<i)
decq.pop_front();
else
break;
}
while(!decq.empty())
{
if(arr[decq.back()]<arr[i])
decq.pop_back();
else
break;
}
decq.push_back(i);
ans[i-k+][]=arr[incq.front()];
ans[i-k+][]=arr[decq.front()];
} for(int i=;i<=n-k+;i++)
{
if(i==)
print_d(ans[i][]);
else
{
putchar(' ');
print_d(ans[i][]);
}
}
putchar('\n');
for(int i=;i<=n-k+;i++)
{
if(i==)
print_d(ans[i][]);
else
{
putchar(' ');
print_d(ans[i][]);
}
}
putchar('\n'); return ;
}
poj 2823 Sliding Windows (单调队列+输入输出挂)的更多相关文章
- POJ 2823 Sliding Window + 单调队列
一.概念介绍 1. 双端队列 双端队列是一种线性表,是一种特殊的队列,遵守先进先出的原则.双端队列支持以下4种操作: (1) 从队首删除 (2) 从队尾删除 (3) 从队尾插入 (4) ...
- poj 2823 Sliding Window (单调队列入门)
/***************************************************************** 题目: Sliding Window(poj 2823) 链接: ...
- POJ 2823 Sliding Window (单调队列)
单调队列 加了读入挂比不加更慢.... 而且这份代码要交c++ 有大神G++跑了700ms..... orzorzorz #include<iostream> #include<cs ...
- 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$ 的滑动窗体 ...
- POJ 2823 Sliding Window 题解
POJ 2823 Sliding Window 题解 Description An array of size n ≤ 106 is given to you. There is a sliding ...
- 洛谷P1886 滑动窗口(POJ.2823 Sliding Window)(区间最值)
To 洛谷.1886 滑动窗口 To POJ.2823 Sliding Window 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每 ...
- POJ 2823 Sliding Window 【单调队列】
题目链接:http://poj.org/problem?id=2823 题目大意:给出一组数,一个固定大小的窗体在这个数组上滑动,要求出每次滑动该窗体内的最大值和最小值. 这就是典型的单调队列,单调队 ...
- POJ 2823 Sliding Window(单调队列入门题)
Sliding Window Time Limit: 12000MS Memory Limit: 65536K Total Submissions: 67218 Accepted: 190 ...
随机推荐
- 关闭Eslint检查
Eslint是一个JavaScript的校验插件,通常用来校验语法或代码的书写风格.不过有点过于严格,通常缩减不同也会报错... 这会影响工作效率啊,最好就是在创建项目的时候不要ESlint(选择No ...
- Docker (一) 安装 Oracle18c
通过Docker 安装 Oracle18c 1.拉取 oracle18c 镜像 docker pull registry.cn-hangzhou.aliyuncs.com/zhengqing/orac ...
- linux用户资源控制
/etc/security/limits.conf配置文件详解 这个文件主要是用来限制用户对资源的使用.是/lib64/security/pam_limits.so模块对应的/etc/serurity ...
- spring日志体系浅析(spring 5.x)
日志是进行软件开发必不可少的一项功能,目前流行着很多开源日志库,比如log4j.log4j2.logback.JDK Logging.commons-logging.slf4j等. 几种日志产品的介绍 ...
- python网络爬虫之入门[一]
目录 前言 一.探讨什么是python网络爬虫? 二.一个针对于网络传输的抓包工具fiddler 三.学习request模块来爬取第一个网页 * 扩展内容(爬取top250的网页) 后记 @(目录) ...
- spark graphX作图计算
一.使用graph做好友推荐 import org.apache.spark.graphx.{Edge, Graph, VertexId} import org.apache.spark.rdd.RD ...
- Intellij 生成exe可执行文件
生成jar包 编写源代码 此处我使用kotlin来编码,主函数实际功能就是输出一行文字. /** * 应用入口 * @author mazaiting */ object TestExe { @J ...
- NPOI插件生成导出word文档
因为之前没有接触NPOI过这个插件,所以几乎都是自己一边百度摸索一边学习. 这个插件对于Excel的数据导入和导出,可以说是很方便了, 但是对于导出word文档,可以说是很少的,百度了很多....也不 ...
- PHP如何获取视频总时长与码率等信息
利用PHP中的FFmpeg读取视频播放时长与码率等信息 function getVideoInfo($file) { define('FFMPEG_PATH', '/usr/local/ff ...
- php: $$str
这种写法称为可变变量有时候使用可变变量名是很方便的.就是说,一个变量的变量名可以动态的设置和使用.一个普通的变量通过声明来设置,例如: <?php$a = "hello";? ...