Time Limit: 12000MS | Memory Limit: 65536K | |
Total Submissions: 36315 | Accepted: 10756 | |
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 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 |
单调队列里存得是下标。这里为了好理解些,假设队列里存得是元素。
要求最大值,则维护一个单调递减的队列。队首即为答案。
1 3 -1 -3 5 3 6 7 K=3
准备插入1 队列为空, 插入1
准备插入3 因为队尾是1,1<3,删除1 ,插入3,3为队首也为队尾
准备插入-1 因为3>-1,单调递减,插入-1 这时候队列为 3 -1 前三个的最大值为队首3
准备插入-3,单调递减 ,3 -1 -3,第二个三个的和最大值也为队首,为3
准备插入5 单调递减,把-3 -1 3全部删除,插入5,为首元素,这时候最大值为5,
以此类推。
代码:
#include <iostream> #include <stdio.h> using namespace std; const int maxn=1000005; int n,k; int q1[maxn],q2[maxn],num[maxn],Min[maxn],Max[maxn]; int front1,rear1,front2,rear2,cnt1,cnt2; void in1(int i)//入队,单调递增,保存最小值 { while(front1<=rear1&&num[q1[rear1]]>num[i]) rear1--; q1[++rear1]=i; } void in2(int i)//单调递减,保存最大值 { while(front2<=rear2&&num[q2[rear2]]<num[i]) rear2--; q2[++rear2]=i; } void out1(int i) { if(q1[front1]<=i-k) front1++; Min[cnt1++]=num[q1[front1]]; } void out2(int i) { if(q2[front2]<=i-k) front2++; Max[cnt2++]=num[q2[front2]]; } int main() { while(~scanf("%d%d",&n,&k)) { front1=front2=cnt1=cnt2=0; rear1=rear2=-1; for(int i=1;i<=n;i++) scanf("%d",&num[i]); for(int i=1;i<k;i++)//前k-1个数只入队,因为不可能达到出队条件 { in1(i);in2(i); } for(int i=k;i<=n;i++) { in1(i);out1(i); in2(i);out2(i); } for(int i=0;i<cnt1-1;i++) printf("%d ",Min[i]); printf("%d\n",Min[cnt1-1]); for(int i=0;i<cnt2-1;i++) printf("%d ",Max[i]); printf("%d\n",Max[cnt2-1]); } return 0; }