POJ-2823 Sliding Window
来源:互联网 发布:java第三方登录接口 编辑:程序博客网 时间:2024/06/17 17:40
Sliding Window
Time Limit: 12000MSMemory Limit: 65536KCase Time Limit: 5000MS
Description
An array of size n ≤ 106 is given to you. There is a sliding window of sizek which is moving from the very left of the array to the very right. You can only see thek numbers in the window. Each time the sliding window moves rightwards by one position. Following is an example:
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 -13 1 [3 -1 -3] 5 3 6 7 -33 1 3 [-1 -3 5] 3 6 7 -35 1 3 -1 [-3 5 3] 6 7 -35 1 3 -1 -3 [5 3 6] 7 36 1 3 -1 -3 5 [3 6 7]37
The array is [1 3 -1 -3 5 3 6 7], and k is 3.
Your task is to determine the maximum and minimum values in the sliding window at each position.
Input
The input consists of two lines. The first line contains two integersn andk which are the lengths of the array and the sliding window. There aren integers in the second line.
Output
There are two lines in the output. The first line gives the minimum values in the window at each position, from left to right, respectively. The second line gives the maximum values.
Sample Input
8 31 3 -1 -3 5 3 6 7
Sample Output
-1 -3 -3 -3 3 33 3 5 5 6 7
Source
POJ Monthly--2006.04.28, Ikki
——————————————————焦急的分割线——————————————————
思路:单调队列……单调队列……单调队列……咳咳,好吧,找最值的问题。首先你想到了二分查找。可是对于一个相当大的n和一个相当小的k,会调用多少次二分呢?妥妥地超时。据说线段树也可以解决此题,但是……我不会。而且线段树是比较耗时的。我们考虑这样一个问题,每一次在长度为k的区间内,找它里面的最大最小值,两个值都要找,暂时简化一下,只考虑找最大值。
怎么样扫一次就找到它呢?明显,每次区间向右移动一个数字而已。我们假设找到了第一个区间的最大值。那么每移动一次,只需要比较新的数字和最大值谁大。且慢,最大值如果在区间头部,就会丢弃。最大值丢了,新数字跟谁比较?无解了。但是牵扯到的数据结构绝对是队列。
解决方法是维护一个单调队列。寻找最大值的时候维护单调递减。那么队首一直是区间内的最大值。每次新数字进队,输出队首即可,一旦新数字与队首之间下标差值超过了区间长度,队首出队。一旦新数字比队尾大,出队直到第一个比它大的数。
这样一来,我们成功维护了一个区间长度“不变”(仅仅是涵义上不变)的队列。
代码如下:
——————————————————焦急的分割线——————————————————
思路:单调队列……单调队列……单调队列……咳咳,好吧,找最值的问题。首先你想到了二分查找。可是对于一个相当大的n和一个相当小的k,会调用多少次二分呢?妥妥地超时。据说线段树也可以解决此题,但是……我不会。而且线段树是比较耗时的。我们考虑这样一个问题,每一次在长度为k的区间内,找它里面的最大最小值,两个值都要找,暂时简化一下,只考虑找最大值。
怎么样扫一次就找到它呢?明显,每次区间向右移动一个数字而已。我们假设找到了第一个区间的最大值。那么每移动一次,只需要比较新的数字和最大值谁大。且慢,最大值如果在区间头部,就会丢弃。最大值丢了,新数字跟谁比较?无解了。但是牵扯到的数据结构绝对是队列。
解决方法是维护一个单调队列。寻找最大值的时候维护单调递减。那么队首一直是区间内的最大值。每次新数字进队,输出队首即可,一旦新数字与队首之间下标差值超过了区间长度,队首出队。一旦新数字比队尾大,出队直到第一个比它大的数。
这样一来,我们成功维护了一个区间长度“不变”(仅仅是涵义上不变)的队列。
代码如下:
#include <stdio.h>#include <string.h>#include <math.h>#include <stdlib.h>#define N 1000010typedef struct{ int val; int id;}Que;//使用结构体保存队列中每个数字的下标和数值int num[N], ans[N], len, L, fron, rear, k, j;//num[]用来保存输入数据,ans[]、j、k仅仅用来输出,len是数组长度,L是区间长度Que a[N];//一个单调队列用两次,省一点儿内存void fun(int True){//True为1,维护寻找最小值的单调递增队列,反之维护寻找最大值的 k = fron = rear = 0;//初始化不要忘了 a[rear].val = num[0]; a[rear].id = 0;//第一个数先入队 for(int i = 1; i < len; i++){ if(i - a[fron].id >= L) fron++;//一旦新数字与队首下标之差达到区间长度,踢了队首那个最值 if(True){ if(num[i] > a[rear].val){//保持了单调性,进队操作 a[++rear].val = num[i]; a[rear].id = i; } else{//打破单调性,出队操作 while(a[rear].val >= num[i] && fron <= rear) rear--; a[++rear].val = num[i];//完成出队之后,要用新数字覆盖最后一个出队的 a[rear].id = i; } } else{//与True为1时同理,复制一下,更改一下大于号 if(num[i] < a[rear].val){ a[++rear].val = num[i]; a[rear].id = i; } else{ while(a[rear].val <= num[i] && fron <= rear) rear--; a[++rear].val = num[i]; a[rear].id = i; } } if(i >= L-1) ans[k++] = a[fron].val;//在本区间找到最值,保存到ans[]之中 } for(j = 0; j < k-1; j++)//输出解 printf("%d ", ans[j]); printf("%d\n", ans[j]);}int main(){while(~scanf("%d%d", &len, &L)){ for(int i = 0; i < len; i++) scanf("%d", num+i); if(L == 1){//这个比较坑人,区间长度为1的时候一定要按原样输出 int i; for(i = 0; i < len-1; i++) printf("%d ", num[i]); printf("%d\n", num[i]); for(i = 0; i < len-1; i++) printf("%d ", num[i]); printf("%d\n", num[i]); } else{ fun(1);//找最小值 fun(0);//找最大值 } }return 0;}
0 0
- POJ 2823 Sliding Window
- poj 2823 Sliding Window
- poj 2823 Sliding Window
- POJ 2823 Sliding Window
- POJ-2823-Sliding Window
- POJ 2823 Sliding Window
- POJ 2823 Sliding Window
- POJ 2823 Sliding Window
- poj 2823 Sliding Window
- POJ 2823(Sliding Window)
- POJ-2823-Sliding Window
- poj 2823 Sliding Window
- POJ 2823 Sliding Window
- POJ 2823 Sliding Window
- Sliding Window poj 2823
- POJ 2823 Sliding Window
- poj 2823 Sliding Window
- POJ 2823 Sliding Window
- JVM学习笔记-操作数栈(Operand Stack)
- Ruby on rails 实战圣经:ActiveRecord 数据表关系
- pat 1036
- Java里的堆(heap)栈(stack)和方法区(method)
- .net工程师面试复习内容
- POJ-2823 Sliding Window
- C++String构造函数
- redis实践使用大总体
- cocos2d-x学习:CCSprite总结
- 2013第四届蓝桥杯 C/C++本科A组 部分解答
- EGL接口介绍(转)
- c++ map 的基本用法
- 回车实现方式:Carriage Return in PeopleCode
- UVa 167 - The Sultan's Successors 递归回溯