单调队列是这样一个队列,队列中的所有元素是单调递增或者单调递减。它可以在队首或队尾删除元素,但是只能在队尾插入元素。由于每个元素入队和出队一次,所以维护队列的均摊时间复杂度为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
#include
#include
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
#include
#include
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;
}