POJ 2823 Sliding Window(单调队列 || 线段树)题解
题意:求每个长度为k的数组的最大值和最小值
思路:
1.用线段树创建维护最大值和最小值,遍历询问,简单复习了一下...有点手生
2.单调队列:
可以看一下详解
单调队列顾名思义就是一个单调递增或者递减的队列,我们可以通过队列瞬间得到当前队列的最大值和最小值。以查找当前区间最小值为例,我们需要维护一个递增的队列,那么当前队列队首就是最小值。在维护队列的过程中要注意:
1、如果队列的长度一定,要判断队首元素是否在规定范围内,如果超范围则队首移动,直到在范围内为止。
2、每次加入元素时和队尾比较,如果队尾元素大于要插入的元素且队列非空,则队尾元素依次出队,直到满足队列的单调性为止,这是为了保证队列的单调性。
线段树:
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int N = 1e6+5;
int n,k,Max[N<<2],Min[N<<2],ansMa[N],ansMi[N],cnt;
void build(int l,int r,int rt){
if(l == r){
int a;
scanf("%d",&a);
Max[rt] = Min[rt] = a;
return;
}
int m = (l + r) / 2;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
Max[rt] = max(Max[rt<<1],Max[rt<<1|1]);
Min[rt] = min(Min[rt<<1],Min[rt<<1|1]);
}
int queryMa(int L,int R,int l,int r,int rt){
if(l == r) return Max[rt];
if(L <= l && R >= r){
return Max[rt];
}
int m = (l + r) / 2;
int MAX = -1e8;
if(L <= m) MAX = max(MAX,queryMa(L,R,l,m,rt<<1));
if(R > m) MAX = max(MAX,queryMa(L,R,m+1,r,rt<<1|1));
return MAX;
}
int queryMi(int L,int R,int l,int r,int rt){
if(l == r) return Min[rt];
if(L <= l && R >= r){
return Min[rt];
}
int m = (l + r) / 2;
int MIN = 1e8;
if(L <= m) MIN = min(MIN,queryMi(L,R,l,m,rt<<1));
if(R > m) MIN = min(MIN,queryMi(L,R,m+1,r,rt<<1|1));
return MIN;
}
int main(){
while(~scanf("%d%d",&n,&k)){
build(1,n,1);
for(int i = 1,j = k;i <= n-k+1;i++,j++){
ansMa[i] = queryMa(i,j,1,n,1);
ansMi[i] = queryMi(i,j,1,n,1);
}
for(int i = 1;i <= n-k+1;i++){
printf("%d ",ansMi[i]);
}
printf("\n");
for(int i = 1;i <= n-k+1;i++){
printf("%d ",ansMa[i]);
}
printf("\n");
}
return 0;
}
单调队列:
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int N = 1e6+5;
int a[N],q[N],pos[N],n,k;
int MAX[N],MIN[N];
void get_max(){ //单调递减队列
int head,tail;
head = tail = 0; //tail指向队尾(空)
for(int i = 1;i < k;i++){
while(head < tail && q[tail - 1] <= a[i]) //保证递减
tail--;
q[tail] = a[i];
pos[tail++] = i; //记录个数的位置,为后续查找q[head]是否超出范围准备
}
for(int i = k;i <= n;i++){
while(head < tail && q[tail - 1] <= a[i])
tail--;
q[tail] = a[i];
pos[tail++] = i;
while(head < tail && pos[head] < i-k+1)
head++;
MAX[i-k] = q[head];
}
for(int i = 0;i < n-k+1;i++) printf("%d ",MAX[i]);
printf("\n");
}
void get_min(){ ////单调递增队列
int head,tail;
head = tail = 0;
for(int i = 1;i < k;i++){
while(head < tail && q[tail - 1] >= a[i]) //保证递增
tail--;
q[tail] = a[i];
pos[tail++] = i;
}
for(int i = k;i <= n;i++){
while(head < tail && q[tail - 1] >= a[i])
tail--;
q[tail] = a[i];
pos[tail++] = i;
while(head < tail && pos[head] < i-k+1)
head++;
MIN[i-k] = q[head];
}
for(int i = 0;i < n-k+1;i++) printf("%d ",MIN[i]);
printf("\n");
}
int main(){
while(~scanf("%d%d",&n,&k)){
for(int i = 1;i <= n;i++) scanf("%d",&a[i]);
get_min();
get_max();
}
return 0;
}
POJ 2823 Sliding Window(单调队列 || 线段树)题解的更多相关文章
- 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 Sliding Windows (单调队列+输入输出挂)
Sliding Window Time Limit: 12000MS Memory Limit: 65536K Total Submissions: 73426 Accepted: 20849 ...
- 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 (线段树/单调队列)
题目不说了,可以用线段树或者单调队列,下面附上代码. 线段树: #include <iostream> #include <stdio.h> #include <algo ...
- 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 ...
随机推荐
- 对SQL SERVER数据类型理解最好的一篇文章
字符串前加N SQL SERVER中生成的语句中,字符串前加N,N 前缀必须是大写字母,是Unicode编码的意思. 一般来说,英文字符是一个字节组成,但是国际上的字太多了,因此就用两个字节来表示字符 ...
- (3.10)mysql基础深入——mysqld 服务器与客户端连接过程 源码分析【待写】
(3.10)mysql基础深入——mysqld 服务器与客户端连接过程 源码分析[待写]
- ubuntu,windows 卸载安装mysql
首先删除mysql: sudo apt-get remove mysql-* 1 然后清理残留的数据 dpkg -l |grep ^rc|awk '{print $2}' |sudo xargs dp ...
- eigen quick reference
参考: http://eigen.tuxfamily.org/dox/AsciiQuickReference.txt // A simple quickref for Eigen. Add anyth ...
- JS在不同js文件中互相调用
例如有这样一个html,里面有一个按钮,当按下时调用b.js文件中的方法b().而b()中又要调用a.js文件中的方法a().若要实现这个功能,必须注意,将要引入的Js文件代码放在</body& ...
- jxl(Java Excel API) 使用方法 【2】
JAVA EXCEL API简介 Java Excel是一开放源码项目,通过它Java开发人员可以读取Excel文件的内容.创建新的Excel文件.更新已经存在的Excel文件.使用该 API非Win ...
- 1.0ARM体系结构-ARM体系结构
对ARMcpu有整体而专业的认识. ARM只是设计arm核,而不生产. ARM 掌握的是标准.
- Qt5
最简单的分割窗体 #include <QApplication> #include <QLabel> #include <QSplitter> int main(i ...
- Vue项目使用AES做加密
1.先在vue项目中安装crypto-js 2.在项目中新建一个utils.js文件 3.utils.js文件中的内容 /** * 工具类 */ import Vue from 'vue' impor ...
- 好消息啊,有些c似乎不用加厂商前缀了
今天写程序,一个不小心,没写厂商前缀,然而,,,,,,, 可以运行了(我居然不知道这个消息!!!!) 赶紧写几个字纪念一下. (把鼠标移动到红色的字上边~~~) don' you think that ...