Time Limit: 12000MS | Memory Limit: 65536K | |
Total Submissions: 38520 | Accepted: 11415 | |
Case Time Limit: 5000MS |
Description
Window position | Minimum value | Maximum 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 |
Your task is to determine the maximum and minimum values in the sliding window at each position.
Input
Output
Sample Input
8 3 1 3 -1 -3 5 3 6 7
Sample Output
-1 -3 -3 -3 3 3 3 3 5 5 6 7
一道裸的单调队列,求区间最值问题。线段树8秒多过,单调队列4秒多过。可作为单调队列的学习题目。
先说一下单调队列是一种什么样的队列。单调队列分为递增和递减队列,下面以递增队列为例:
1.该队列时刻保持队头元素最小且递增。元素从队尾插入,如果小于队尾元素,那么就删去队尾元素,再插入。
2.同时需要一个数组保存元素下标,以本题为例,区间长度为k,队头元素的下标小于当前元素下标i-k+1时,也就是此时队头元素已经不在k区间内了,就把队头元素删去。
#include<iostream> #include<cstdio> #define M 1000001 using namespace std; int n,k; int a[M]; int q[M]; int p[M]; void get_min() { int head=1; int tail=0; for(int i=0;i<k-1;i++) { while(head<=tail&&a[i]<=q[tail]) --tail; q[++tail]=a[i]; p[tail]=i; } for(int i=k-1;i<n;i++) { while(head<=tail&&a[i]<=q[tail]) --tail; q[++tail]=a[i]; p[tail]=i; while(p[head]<i-k+1) { ++head; } cout<<q[head]<<" "; } cout<<endl; } void get_max() { int head=1; int tail=0; for(int i=0;i<k-1;i++) { while(head<=tail&&a[i]>=q[tail]) --tail; q[++tail]=a[i]; p[tail]=i; } for(int i=k-1;i<n;i++) { while(head<=tail&&a[i]>=q[tail]) --tail; q[++tail]=a[i]; p[tail]=i; while(p[head]<i-k+1) { ++head; } cout<<q[head]<<" "; } cout<<endl; } int main() { //freopen("d:\\test.txt","r",stdin); scanf("%d%d",&n,&k); for(int i=0;i<n;i++) { scanf("%d",&a[i]); } get_min(); get_max(); return 0; }
原文地址:http://blog.csdn.net/u012198382/article/details/38377903