POJ[2823]窗口 单调队列
2016-09-02 19:53
363 查看
题目地址poj.org/problem?id=2823
题目大意:
给你一个长度为N的数组,一个长为K滑动的窗体从最左移至最右端,你只能见到窗口的K个数,每次窗体向右移动一位,如下表:
你的任务是找出窗口在各位置时的Max value ,Min value。
输入格式:
第一行n,k,第二行长度为n的数组
输出格式:
第一行每个位置的Min value,第二行每个位置的Max value
样例:
Window.in
8 3
1 3 -1 -3 5 3 6 7
Window.out
-1 -3 -3 -3 3 3
3 3 5 5 6 7
数据范围:
20%:n≤500;
50%:n≤100000;
100%:n≤1000000;
时间限制:
12000ms
RMQ问题,线段树代码量太大于是用单调队列实现- -
单调队列具有队列内所有元素不是单调递增就是单调递减的性质,所以每次的最小(最大)值一定会在队首
程序实现过程中先将前k个元素入队,此后每次在队尾加入a[k+1...n],在插入元素中同时进行以下操作:
1、将队尾所有大于a[i]的值弹出队列
2、插入a[i]到队尾
3、判断队首元素位置是否超出i-k
注意:
1、在更新队列元素时要同时记录该元素在原数据的位置
2、在进行操作1时要用二分优化(可以用C++编译器卡时间AC,但换成G++和GCC就会TLE)
代码如下:
题目大意:
给你一个长度为N的数组,一个长为K滑动的窗体从最左移至最右端,你只能见到窗口的K个数,每次窗体向右移动一位,如下表:
Window position | Min value | Max 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 |
输入格式:
第一行n,k,第二行长度为n的数组
输出格式:
第一行每个位置的Min value,第二行每个位置的Max value
样例:
Window.in
8 3
1 3 -1 -3 5 3 6 7
Window.out
-1 -3 -3 -3 3 3
3 3 5 5 6 7
数据范围:
20%:n≤500;
50%:n≤100000;
100%:n≤1000000;
时间限制:
12000ms
RMQ问题,线段树代码量太大于是用单调队列实现- -
单调队列具有队列内所有元素不是单调递增就是单调递减的性质,所以每次的最小(最大)值一定会在队首
程序实现过程中先将前k个元素入队,此后每次在队尾加入a[k+1...n],在插入元素中同时进行以下操作:
1、将队尾所有大于a[i]的值弹出队列
2、插入a[i]到队尾
3、判断队首元素位置是否超出i-k
注意:
1、在更新队列元素时要同时记录该元素在原数据的位置
2、在进行操作1时要用二分优化(可以用C++编译器卡时间AC,但换成G++和GCC就会TLE)
代码如下:
#include<cstring> #include<cstdio> #define N 1000050 #define INF 2147483647 using namespace std; int n,k; int a ; struct Elem{ int k,num; }Queue ; int l=1,r=1; inline void GetMin(){ memset(Queue,0,sizeof Queue); Queue[0].k=-INF; l=1,r=1; for(int i=1;i<=k;i++){ while(Queue[r].k>=a[i] && r>=l) r--; Queue[++r].k=a[i]; Queue[r].num=i; } for(int i=k;i<=n;i++){ while(Queue[r].k>=a[i] && r>=l) r--; //维护单调性 Queue[++r].k=a[i]; Queue[r].num=i; while(Queue[l].num<=i-k) l++; //维护队列下标范围k以内 printf("%d ",Queue[l].k); } } inline void GetMax(){ memset(Queue,0,sizeof Queue); Queue[0].k=INF; l=1,r=1; for(int i=1;i<=k;i++){ while(Queue[r].k<=a[i] && r>=l) r--; Queue[++r].k=a[i]; Queue[r].num=i; } for(int i=k;i<=n;i++){ while(Queue[r].k<=a[i] && r>=l) r--; Queue[++r].k=a[i]; Queue[r].num=i; while(Queue[l].num<=i-k) l++; printf("%d ",Queue[l].k); } } int main(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",a+i); GetMin(); printf("\n"); GetMax(); return 0; }
相关文章推荐
- POJ 2823 Sliding Window 堆 / 单调队列
- poj 2823 Sliding Window(简单单调队列)
- poj 2823 Sliding Window 【单调队列】
- POJ 2823 Sliding Window【单调队列】
- poj 2823 Sliding Windows 单调队列维护最值
- poj 2823 Sliding Window (单调队列)
- poj 2823 (单调队列)
- POj 2823 单调队列 / 优先队列
- 单调队列 - 兼 ACM PKU POJ 3250 及 2823 解题报告 [转]
- 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【单调队列】
- POJ-2823 Sliding Window 单调队列
- 单调队列 - 兼 ACM PKU POJ 3250 及 2823 解题报告
- poj 2823 Sliding Window(单调队列)
- POJ 2823 Sliding Window(单调队列)