Time Limit: 12000MS | Memory Limit: 65536K | |
Total Submissions: 32200 | Accepted: 9566 | |
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
Source
一、 什么是单调(双端)队列
单调队列,顾名思义,就是一个元素单调的队列,那么就能保证队首的元素是最小(最大)的,从而满足动态规划的最优性问题的需求。
单调队列,又名双端队列。双端队列,就是说它不同于一般的队列只能在队首删除、队尾插入,它能够在队首、队尾同时进行删除。
【单调队列的性质】
一般,在动态规划的过程中,单调队列中每个元素一般存储的是两个值:
1、在原数列中的位置(下标)
2、 他在动态规划中的状态值
而单调队列则保证这两个值同时单调。
从以上看,单调队列的元素最好用一个类来放,不这样的话,就要开两个数组。。。
单调队列:单调队列 即保持队列中的元素单调递增(或递减)的这样一个队列,可以从两头删除,只能从队尾插入。单调队列的具体作用在于,由于保持队列中的元素满足单调性,对手元素便是极小值(极大值)了。
#include<iostream> #include<cstdio> using namespace std; const int MAXN=1000000+10; int da[MAXN],Inc[MAXN],Dec[MAXN]; int n,k,front1,rear1,front2,rear2; struct node { int Min,Max; }; //维护双端单调队列 void Queue() { front1=0,rear1=-1,front2=0,rear2=-1; int i,ans=0,start=0; node tmp; for(i=0;i<k;i++) { while(front1<=rear1&&da[Dec[rear1]]<=da[i])//保证Dec队列在start-i区间内的递减 rear1--; Dec[++rear1]=i; while(front2<=rear2&&da[Inc[rear2]]>=da[i])//保证inc队列在start-i区间内的递增 rear2--; Inc[++rear2]=i; } printf("%d ",da[Inc[front2]]); for(;i<n;i++) { while(front2<=rear2&&da[Inc[rear2]]>=da[i])//保证inc队列在start-i区间内的递增 rear2--; Inc[++rear2]=i; while(Inc[front2]<=i-k)//下标控制区间长度 front2++; if(i!=n-1) printf("%d ",da[Inc[front2]]); } printf("%d\n",da[Inc[front2]]); printf("%d ",da[Dec[front1]]); for(i=k;i<n;i++) { while(front1<=rear1&&da[Dec[rear1]]<=da[i])//保证inc队列在start-i区间内的递增 rear1--; Dec[++rear1]=i; while(Dec[front1]<=i-k)//下标控制区间长度 front1++; if(i!=n-1) printf("%d ",da[Dec[front1]]); } printf("%d\n",da[Dec[front1]]); } int main() { int i; while(~scanf("%d%d",&n,&k)) { for(i=0;i<n;i++) scanf("%d",&da[i]); Queue(); } return 0; }