单调队列是这样一个队列,队列中的所有元素是单调递增或者单调递减。它可以在队首或队尾删除元素,但是只能在队尾插入元素。由于每个元素入队和出队一次,所以维护队列的均摊时间复杂度为O(1)。
题目:http://poj.org/problem?id=2823
题意:给一个数组a[],求它连续m个元素中的最小值和最大值。比如输入:
8 3
1 3 -1 -3 5 3 6 7
那么输出:
-1 -3 -3 -3 3 3
3 3 5 5 6 7
分析:我们用一个数组q[]来记录这个单调队列所有元素的下标,h为队首,t为队尾。那么现在就来模拟样例:
首先h初始化为1,t初始化为0。
(1)插入第一个元素 q[] = {1},h = 1,t = 1 队列中的元素个数小于3,不输出。
(2)插入第二个元素 q[] = {1,2},h = 1,t = 2 队列中的元素个数小于3,不输出。
(3)插入第三个元素 q[] = {3},h = 1,t = 1 因为3号元素比1和2号元素都小,所以一直挤到最
前面,1号和2号元素出队,此时队列中的元素个数等于3,输出队首元素值。
(4)插入第四个元素 q[] = {4},h = 1,t = 1 同样的道理,3号元素出队,输出队首元素值。
(5)插入第五个元素 q[] = {4,5},h = 1,t = 2 输出队首元素。
(6)插入第六个元素 q[] = {4,6},h = 1,t = 2 输出队首元素。
(7)插入第七个元素 q[] = {6,7},h = 2,t = 3 输出队首元素。
(8)插入第八个元素 q[] = {6,7,8},h = 2,t = 4 输出队首元素。
#include <iostream> #include <string.h> #include <stdio.h> using namespace std; const int N = 1000005; int n,m; int a[N],q[N]; void MinQ() { int t = 0 ,h = 1; q[1] = 1; for(int i=1; i<=n; i++) { if(i - q[h] == m) h++; if(t == h-1 || a[i] > a[q[t]]) { t++; q[t] = i; } else { while(t >= h && a[i] <= a[q[t]]) { q[t] = i; t--; } t++; } if(i >= m) printf("%d ",a[q[h]]); } puts(""); } void MaxQ() { int t = 0 ,h = 1; q[1] = 1; for(int i=1; i<=n; i++) { if(i - q[h] == m) h++; if(t == h-1 || a[i] < a[q[t]]) { t++; q[t] = i; } else { while(t >= h && a[i] >= a[q[t]]) { q[t] = i; t--; } t++; } if(i >= m) printf("%d ",a[q[h]]); } puts(""); } int main() { scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) scanf("%d",&a[i]); MinQ(); MaxQ(); return 0; }
题目:http://acm.fzu.edu.cn/problem.php?pid=1894
#include <iostream> #include <string.h> #include <stdio.h> using namespace std; const int N = 1000005; struct Node { int id; int val; Node(int id = 0,int val = 0) { this->id = id; this->val = val; } }; Node q[N]; char str[105]; int main() { int T; scanf("%d",&T); q[0] = -1; while(T--) { scanf("%s",str); int i = 0,j = 1; int head = 1,tail = 0; while(scanf("%s",str)) { if(!strcmp(str,"END")) break; if(str[0] == 'C') { int val; scanf("%s %d",str,&val); while(head <= tail && q[tail].val <= val) tail--; q[++tail] = Node(++i,val); } else if(str[0] == 'G') { while(head <= tail && q[head].id <= j) head++; j++; } else printf("%d\n",head > tail ? -1:q[head].val); } } return 0; }