标签:单调队列
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 33 3 5 5 6 7
一开始这题用线段树做,后来用单调队列试了一下。单调队列的思想是用数组模拟一个队列,队列中的元素满足从队伍的头到尾元素大小单调递增或递减(注意:这里是严格递增或递减,即没有相同的,因为如果有两个相同的元素,后面的元素进队的时间一定小于前面一个元素,可以用后面的元素代替,所以前面的无意义),也满足从队伍的头到尾元素进队时间单调递增或递减,每次进入一个元素,从后面开始找,一直找到大于或者小于这个数为止,后面的元素全部删除。
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<map> #include<string> using namespace std; #define maxn 1000005 int a[maxn],num1[maxn],num2[maxn]; int q1[1111111][2]; int q2[1111111][2]; int main() { int n,k,i,j,front1,rear1,front2,rear2; while(scanf("%d%d",&n,&k)!=EOF) { for(i=1;i<=n;i++)scanf("%d",&a[i]); front1=front2=1;rear1=rear2=0; for(i=1;i<=k-1;i++){ //单调递增 ,得到最小值 while(front2<=rear2 && q2[rear2][0]>=a[i]){ rear2--; } rear2++; q2[rear2][0]=a[i];q2[rear2][1]=i; } for(i=k;i<=n;i++){ while(front2<=rear2 && q2[rear2][0]>=a[i]){ rear2--; } rear2++; q2[rear2][0]=a[i];q2[rear2][1]=i; while(q2[front2][1]+k-1<i)front2++; num2[i]=q2[front2][0]; if(i==n)printf("%d\n",num2[n]); else printf("%d ",num2[i]); } for(i=1;i<=k-1;i++){ //单调递减 ,得到最大值 while(front1<=rear1 && q1[rear1][0]<=a[i]){ rear1--; } rear1++; q1[rear1][0]=a[i];q1[rear1][1]=i; } for(i=k;i<=n;i++){ while(front1<=rear1 && q1[rear1][0]<=a[i]){ rear1--; } rear1++; q1[rear1][0]=a[i];q1[rear1][1]=i; while(q1[front1][1]+k-1<i)front1++; num1[i]=q1[front1][0]; if(i==n)printf("%d\n",num1[n]); else printf("%d ",num1[i]); } } return 0; }
标签:单调队列
原文地址:http://blog.csdn.net/kirito_acmer/article/details/45743169