单调队列stl及手写实现,附例题

单调队列: 有单调性的队列(单调递增或递减),相比普通队列不同在于可以在队尾进行pop操作
特点: 可以快速取出最大值最小值(队首元素)
严格单调序列:a1 时间复杂度: 每个元素出队入队各一次,总复杂度O(n),均摊下来每次维护队列的操作为O(1)
维护方法:
不严格单调递增为例:

  • 每次入队时与队尾元素比较,如果队列非空且小于(大于)队尾元素,就将队尾元素pop,重复上述操作直到队列为空或大于等于队尾元素,再将元素压入队尾。

STL实现方法:#include

deque是双端队列,既有队列的性质也有栈的性质。
deque对象创建:deque que
deque的一些成员函数:

函数名 功能
push_back() 队尾入队
push_front() 队首入队
pop_front() 队首元素出队
pop_back() 队尾元素出队
empty() 判断队列是否为空
front() 返回队首元素
back() 返回队尾元素

入队操作:

	while(!que.empty()&&que.back()>value)que.pop_back();
	que.push_back(value);//value 为要入队的元素

如果要维护长度的话另加操作

手写实现:

#include
using namespace std;
const int MAX_N=1e4; 	//确保大小够用 
int que[MAX_N],head=0,tail=0;		//队首队尾指针,队列大小即为 tail-head 
int main()
{
	int arr[10]={135,6,4,9,7,1,6,3,8,8};
	for(int i=0;i<10;i++)
	{
		if(i>=3&&que[head]==arr[i-3])head++;	//头后移,出队 
		while(head<tail&&que[tail-1]>arr[i])tail--;	//队尾前移,出队 
		que[tail++]=arr[i];	//入队
		cout<<que[head]<<" ";
	} 
	return 0;
}

经典例题:P1440 求m区间内的最小值

题解:

#include
#include
using namespace std;
const int MAX_N=2e6+1;
int arr[MAX_N];
int que[MAX_N],head=0,tail=0; 
inline int read()
{
	int sum=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){sum=(sum<<1)+(sum<<3)+c-48;c=getchar();}
	return sum*f;
}
inline void write(int x)
{
    char ch[20];
    int len=0;
    if(x<0)
      {
        putchar((1<<5)+(1<<3)+(1<<2)+1);
        x=~x+1;
      }
    do 
      {
        ch[len++]=x%10+(1<<4)+(1<<5);
        x/=10;
      }while(x>0);
    for(int i=len-1;i>=0;i--) 
       putchar(ch[i]);
    return ;
} 
int main()
{
	int n=read(),m=read();
	cout<<0<<endl;
	for(int i=0;i<n-1;i++)
	{
		arr[i]=read();
		if(i>=m&&que[head]==arr[i-m])head++;
		while(head!=tail&&arr[i]<que[tail-1])tail--;
		que[tail++]=arr[i];
		write(que[head]);
		putchar('\n');
	}
	return 0;
}

你可能感兴趣的:(队列,队列,数据结构)