POJ 2823 Sliding Window (线段树/单调队列)
题目不说了,可以用线段树或者单调队列,下面附上代码。
线段树:
#include <iostream>
#include <stdio.h>
#include <algorithm>
/*
AC
线段树每个节点存储对应区间的最大值、最小值,然后直接查询即可。6594MS。
*/
using namespace std;
const int maxn=;
const int INF=0x3f3f3f3f;
int minans[maxn],maxans[maxn];
int small,bigger;
int n,k;
struct Node{
int maxv,minv;
}tree[maxn<<]; void pushUp(int rt){
tree[rt].maxv=max(tree[rt<<].maxv,tree[rt<<|].maxv);
tree[rt].minv=min(tree[rt<<].minv,tree[rt<<|].minv);
} void build(int rt,int L,int R){
if(L==R){
scanf("%d",&tree[rt].minv);
tree[rt].maxv=tree[rt].minv;
return;
}
int mid=(L+R)>>;
build(rt<<,L,mid);
build(rt<<|,mid+,R);
pushUp(rt);
} void query(int rt,int l,int r,int L,int R){
if(l<=L && R<=r){
small=min(small,tree[rt].minv);
bigger=max(bigger,tree[rt].maxv);
return;
}
int mid=(L+R)>>;
if(r<=mid)
query(rt<<,l,r,L,mid);
else if(l>mid)
query(rt<<|,l,r,mid+,R);
else{
query(rt<<,l,r,L,mid);
query(rt<<|,l,r,mid+,R);
}
}
int main()
{
int idx=;
scanf("%d%d",&n,&k);
build(,,n);
for(int i=;i<=n-k+;i++){
bigger=-INF;
small=INF;
query(,i,i+k-,,n);
minans[idx]=small; //存储最小值序列
maxans[idx]=bigger; //存储最大值序列
idx++;
}
for(int i=;i<idx;i++){
if(i==)
printf("%d",minans[i]);
else
printf(" %d",minans[i]);
}
printf("\n");
for(int i=;i<idx;i++){
if(i==)
printf("%d",maxans[i]);
else
printf(" %d",maxans[i]);
}
printf("\n");
return ;
}
单调队列:
#include <iostream>
#include <stdio.h>
/*
AC 5204ms
利用单调队列,分两次处理,第一次求最小值序列,第二次求最大值序列。 以求最小值序列为例:
先处理前k-1个元素,每次从队尾加入队列之前,先与队尾元素比较,若比队尾元素值小,则删去队尾元素,直到有比它小的,或者队列为空,
将该元素插入到队尾。即每次保证队列为单调非减队列,队首元素始终是队列中最小的。 接下来依次读入一个元素,与队尾元素比较,若队尾元素大,则删去队尾元素,直至遇到比要插入的元素小或者队列为空为止,插入该元素。
由于要求的是连续的k个区间,所以还要把队列中在该区间之前的元素删去。
这里有个技巧,也就是队列中,存储的不是元素值,而是在数组中的位置,这样很容易判断某个元素是否在连续的k个区间内,
获取元素值的话,就通过存储的数组下标获取。 求最大值序列的时候,同最小值序列,保证队列为非增队列,即队列的首个元素一定是最大的。 */
using namespace std;
const int maxn=;
int n,k;
int a[maxn]; //n个元素值
int dequeue[maxn]; //单调队列
//求最小值序列
void minans(int k,int n) {
int head=;
int tail=;
//先处理前k-1个元素
for(int i=; i<k-; i++) {
while(head<=tail && a[dequeue[tail]]>=a[i]) {
tail--;
}
tail++;
dequeue[tail]=i; //存储的是元素在a中的索引
}
for(int i=k-; i<n; i++) {
while(head<=tail && a[dequeue[tail]]>=a[i]) {
tail--;
}
tail++;
dequeue[tail]=i;
while(dequeue[head]<i-k+) //将索引在i-k+1之前的元素删去
head++;
printf("%d ",a[dequeue[head]]); //输出队列首个元素,即最小的元素 }
}
//求最大值序列
void maxans(int k,int n) {
int head=;
int tail=;
for(int i=; i<k-; i++) {
while(head<=tail && a[dequeue[tail]]<=a[i]) {
tail--;
}
tail++;
dequeue[tail]=i;
}
for(int i=k-; i<n; i++) {
while(head<=tail && a[dequeue[tail]]<=a[i]) {
tail--;
}
tail++;
dequeue[tail]=i;
while(dequeue[head]<i-k+)
head++;
printf("%d ",a[dequeue[head]]); }
} int main() {
scanf("%d%d",&n,&k);
for(int i=; i<n; i++) {
scanf("%d",&a[i]);
}
minans(k,n);
printf("\n");
maxans(k,n);
//printf("\n");
return ;
}
POJ 2823 Sliding Window (线段树/单调队列)的更多相关文章
- POJ 2823 Sliding Window 线段树
http://poj.org/problem?id=2823 出太阳啦~^ ^被子拿去晒了~晚上还要数学建模,刚才躺在床上休息一下就睡着了,哼,还好我强大,没有感冒. 话说今年校运会怎么没下雨!!!说 ...
- POJ 2823 Sliding Window 线段树区间求和问题
题目链接 线段树区间求和问题,维护一个最大值一个最小值即可,线段树要用C++交才能过. 注意这道题不是求三个数的最大值最小值,是求k个的. 本题数据量较大,不能用N建树,用n建树. 还有一种做法是单调 ...
- POJ 2823 Sliding Window 再探单调队列
重新刷这个经典题,感觉跟以前不一样了,变得更加容易理解了,不讲解了,看代码.注意:要用C++提交,用G++会超时.. 代码: #include <iostream> #include &l ...
- PKU 2823 Sliding Window(线段树||RMQ||单调队列)
题目大意:原题链接(定长区间求最值) 给定长为n的数组,求出每k个数之间的最小/大值. 解法一:线段树 segtree节点存储区间的最小/大值 Query_min(int p,int l,int r, ...
- POJ 2823 Sliding Window + 单调队列
一.概念介绍 1. 双端队列 双端队列是一种线性表,是一种特殊的队列,遵守先进先出的原则.双端队列支持以下4种操作: (1) 从队首删除 (2) 从队尾删除 (3) 从队尾插入 (4) ...
- 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的窗口.现在这个从左边开始向右滑动,每 ...
- 【BZOJ-2892&1171】强袭作战&大sz的游戏 权值线段树+单调队列+标记永久化+DP
2892: 强袭作战 Time Limit: 50 Sec Memory Limit: 512 MBSubmit: 45 Solved: 30[Submit][Status][Discuss] D ...
- BZOJ 1012 线段树||单调队列
非常裸的线段树 || 单调队列: 假设一个节点在队列中既没有时间优势(早点入队)也没有值优势(值更大),那么显然不管在如何的情况下都不会被选为最大值. 既然它仅仅在末尾选.那么自然能够满足以上的条件 ...
随机推荐
- 数值积分NIntegrate中的具体算法
数值积分方法很多,Mathematica中至提供了NIntegrate.具体算法可参照官方帮助. http://reference.wolfram.com/language/tutorial/NInt ...
- DataGrid3
a标签,DataGrid的数据绑定 1.function aa(id, url) { //alert(id); window.open(url + '&am ...
- 在 linux x86-64 模式下分析内存映射流程
前言 在上一篇中我们分析了 linux 在 x86-32 模式下的虚拟内存映射流程,本章主要继续分析 linux 在 x86-64 模式下的虚拟内存映射流程. 讨论的平台是 x86-64, 也可以称为 ...
- 主引导记录MBR
作者:马 岩(Furzoom) (http://www.cnblogs.com/furzoom/)版权声明:本文的版权归作者与博客园共同所有.转载时请在明显地方注明本文的详细链接,未经作者同意请不要删 ...
- 可以支持jQuery1.10.1 的 fancybox 1.3.4, 並現在type為Ajax時,也可以定義窗口的大小。
官網上的 fancybox 1.3.4 太老了,不支持jQuery1.10.1,改動了一下源碼,現在可以支持了. type為Ajax時,也可以定義窗口的大小. $("#ajaxlink&qu ...
- Nginx+Center OS 7.2 开机启动设置(转载)
centos 7以上是用Systemd进行系统初始化的,Systemd 是 Linux 系统中最新的初始化系统(init),它主要的设计目标是克服 sysvinit 固有的缺点,提高系统的启动速度.关 ...
- Js apply() call()使用详解
Js apply方法详解我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这里 ...
- Stanford parser:入门使用
一.stanford parser是什么? stanford parser是stanford nlp小组提供的一系列工具之一,能够用来完成语法分析任务.支持英文.中文.德文.法文.阿拉伯文等多种语言. ...
- js Table冻结表头示例代码
Table冻结表头的js实现代码. Table冻结表头: <script type="text/javascript"> //冻结table的表头 function ...
- PHP CodeIgniter(CI)去掉 index.php
去掉CodeIgniter(CI)默认url中的index.php的步骤: 1.打开apache的配置文件,conf/httpd.conf : LoadModule rewrite_module mo ...