sliding windows (poj 2823) 题解

【问题描述】

给你一个长度为N的数组,一个长为K的滑动的窗体从最左移至最右端,你只能见到窗口的K个数,每次窗体向右移动一位,如下表:

【样例输入】

8 3

1 3 -1 -3 5 3 6 7

【样例输出】

-1 -3 -3 -3 3 3

3 3 5 5 6 7

【解题思路】

首先,不难想到用枚举的办法,对于每一个区间,枚举其中的最大值和最小值,但对于n<=1000000的数据来说,枚举必定超时,因此我们可以用到队列来进行优化。

我们取前k个数中的最大值和最小值,放入两个队列中,设放最大值的为k,放最小值的为q,对于之后的每一个数如果比k中的队尾元素大,那么k的队尾元素便可删去(因为可以证明,在之后的任何一个区间内都用不上该元素),若比队尾元素小,便入队。q队列则是反操作。于是,对于每一个区间的最小值和最大值,我们只需要记录q和k队列中的队首元素即可。由于输出的要求我在这用了两个过程,先求最小值,然后求最大值。详见代码。

【代码实现】

var q,a:array[1..1000000] of longint;
    n,k,i,j:longint;
procedure work;
var i,f,r:longint;
begin
 f:=1;
 r:=1;
 q[f]:=1;
 for i:=2 to k do
  begin
   while (f<=r)and(a[q[r]]>=a[i]) do
    dec(r);
   inc(r);
   q[r]:=i;
  end;//初始化q队列
 write(a[q[f]],‘ ‘);
 for i:=2 to n-k+1 do
  begin
   if q[f]<i then
    inc(f);
   while (f<=r)and(a[q[r]]>=a[i+k-1]) do//若当前元素比队尾元素小,删除队尾元素
    dec(r);
   inc(r);
   q[r]:=i+k-1;
   write(a[q[f]],‘ ‘);
  end;
end;
procedure work1;
var i,f,r:longint;
begin
 f:=1;
 r:=1;
 q[f]:=1;
 for i:=2 to k do
  begin
   while(f<=r)and(a[q[r]]<=a[i]) do
    dec(r);
   inc(r);
   q[r]:=i;
  end;
 write(a[q[f]],‘ ‘);//初始化k队列
 for i:=2 to n-k+1 do
  begin
   if q[f]<i then
    inc(f);
   while (f<=r)and(a[q[r]]<=a[i+k-1]) do//若当前数比队尾元素大,删除队尾元素
    dec(r);
   inc(r);
   q[r]:=i+k-1;
   write(a[q[f]],‘ ‘);
  end;
end;
begin
 readln(n,k);
 for i:=1 to n do
  read(a[i]);
 work;
 fillchar(q,sizeof(q),0);
 writeln;
 work1;
 writeln;
end.
时间: 2024-12-19 01:52:37

sliding windows (poj 2823) 题解的相关文章

Sliding Window POJ - 2823 单调队列模板题

Sliding Window POJ - 2823 单调队列模板题 题意 给出一个数列 并且给出一个数m 问每个连续的m中的最小\最大值是多少,并输出 思路 使用单调队列来写,拿最小值来举例 要求区间最小值 就是维护一个单调递增的序列 对于样例 8 3 1 3 -1 -3 5 3 6 7 我们先模拟一遍 1.队列为空 1 进队 队列:1 2.3>队尾元素 3 进队 队列: 1 3 3.-1小于队尾元素,一直从尾部出队知道找到比-1小的元素或者队列为空 队列:-1 当队列中元素大于m的时候从队头删

A - Sliding Window POJ - 2823

http://poj.org/problem?id=2823// 原题链接 题目大意,就是输出每个相邻 (i,i+k+1)区间中的最大值 /// 单调队列练习 1 #include <algorithm> 2 #include <stack> 3 #include <istream> 4 #include <stdio.h> 5 #include <map> 6 #include <math.h> 7 #include <vec

Sliding Window POJ - 2823

题解:从前往后,维护一个从栈底到栈顶递增的栈,那么每个区间的最小值就是栈底.从后往前,维护一个从栈顶到栈底递增的栈,那么每个区间的最大值就是栈底. //#include<bits/stdc++.h> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<bitset> #include<vector> #incl

poj 2823题解

这道题就是单调队列的裸题 今天刚学的单调队列  前几天刚学习完单调栈 感觉这两个东西非常相似哇 黄哥的一句话说破了他 他俩的区别就像队列和栈的区别233333 有关这道题倒没有太多说的 就是模拟队列 单调递增递减来找到区间最值 我这里用了数组模拟 问题就是G++ T了///  而C++ AC  就很迷...还是oj是 windows linux的区别吧大概 附上代码 1 #include<iostream> 2 #include<stdio.h> 3 #include<str

poj 2823 Sliding Window (单调队列入门)

1 /***************************************************************** 2 题目: Sliding Window(poj 2823) 3 链接: http://poj.org/problem?id=2823 4 题意: 给一个数列,找所有连续k个数的最小值和最大值. 5 算法: 单调队列(入门) 6 ******************************************************************

POJ 2823 Sliding Window 题解

POJ 2823 Sliding  Window 题解 Description An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the slidi

POJ 2823 Sliding Window 单调队列题解

本题是单调队列题解的入门,当然也可以使用RMQ 和 线段树,不过速度都没有单调队列那么快. 单调队列难点: 1 如何入列,保存数据 -- 最小单调队列的时候, 所有数都入列一次,在新的数据准备入列的时候,增加判断,如果当前数值小于队尾数值,那么队尾数值就出列.空队列的时候直接入列. 2 保存的数列是什么样的? 举例吧: 1 3 -1 -3 5 3 6 7 构建最小单调队列 第一个数值1的时候,空队列,那么入列,得到: 1 第二个数值3, 因为大于1:那么1不用出列,直接入列,得到: 1 3 第三

poj 2823 Sliding Window

poj 2823 Sliding Window 单调队列 单调队列是一个单调的状态(递增,或者递减) 所以需要维护这么一个状态 http://baike.baidu.com/link?url=ZcGM7Hzo8zVQUU6Oqqq18SlCMJ92ts3I1aXwQGDZw_NiDDlzIIV9GKlfs3X1fcHVppZHOU31geHZG4cOcRZOAK 固定 k 区间的单调 队列,求 最小值,如果 两个元素 A B ,如果 A 的 下标 比 B 小,但是 A 的 值 比 B 大,那么在

[ACM] poj 2823 Sliding Window(单调队列)

Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 36212   Accepted: 10723 Case Time Limit: 5000MS Description An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the very left