加载中…

返回上一页

栈和队列

什么是栈?

这还用废话,当然是一头的,往里塞往外拿的容器了呗!

它能用来干嘛?

在递归某个数群时会用到.

队列

那就是一头进另一头出了呗.

​​bfs 和最短路一般使用队列.

单调栈、单调队列

单调栈

主要用于寻找最值的连续段,也就是这个数最长在哪个区间里是最大/小值.

例题:Look Up 仰望

约翰的N(1≤N≤10^5)头奶牛站成一排,奶牛i的身高是Hi(l≤Hi≤1,000,000).现在,每只奶牛都在向左看齐.对于奶牛i,如果奶牛j满足i<j且Hi<Hj,我们可以说奶牛i可以仰望奶牛j. 求出每只奶牛离她最近的仰望对象.

实现:

点击查看代码
#include<bits/stdc++.h>
#define ll int
#define rg register
#define rll rg ll
#define maxn 10000001
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
inline ll read()
{
	rll f=0,x=0;rg char ch=getchar();while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar();return f?-x:x;
}
inline void write(rll x) { if(x<0) putchar('-'),x=-x;if(x>9) write(x/10);putchar(x%10|'0'); }
ll n,a[maxn],b[maxn];
stack<ll> s;
int main()
{
	n=read(); for(rll i=1;i<=n;i++) a[i]=read();
	for(rll i=n;i;i--)
	{
		while(!s.empty()&&a[i]>=a[s.top()]) s.pop(); if(!s.empty()) b[i]=s.top(); s.push(i);
	}
	for(rll i=1;i<=n;i++) write(b[i]),putn;
	return 0;
}

单调队列

主要用于寻找连续段的最值,和单调栈正好相反.

为了保证单调性,前后均可能会出队,所以一般用双端队列实现.

例题:滑动窗口

给你一个长度为N的数组,一个长为K的滑动的窗体从最左移至最右端,你只能见到窗口的K个数,每次窗体向右移动一位,如下表:

你的任务是找出窗口在各位置时的max value,min value.

实现:

点击查看代码
#include<bits/stdc++.h>
#define ll int
#define rg register
#define rll rg ll
#define maxn 3000001
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
inline ll read()
{
	rll f=0,x=0;rg char ch=getchar();while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar();return f?-x:x;
}
inline void write(rll x) { if(x<0) putchar('-'),x=-x;if(x>9) write(x/10);putchar(x%10|'0'); }
ll n,k,cnt,a[maxn],ans1[maxn],ans2[maxn];
deque<ll> q1,q2;
int main()
{
	n=read();k=read();
	for(rll i=1;i<=n;i++)
	{
		a[i]=read();
		while(!q1.empty()&&a[q1.back()]>=a[i]) q1.pop_back();while(!q2.empty()&&a[q2.back()]<=a[i]) q2.pop_back();
		while(!q1.empty()&&q1.front()+k<=i) q1.pop_front();while(!q2.empty()&&q2.front()+k<=i) q2.pop_front();
		q1.push_back(i);q2.push_back(i);if(i>=k) ans1[++cnt]=a[q1.front()],ans2[cnt]=a[q2.front()];
	}
	for(rll i=1;i<=cnt;i++) write(ans1[i]),put_;putn;for(rll i=1;i<=cnt;i++) write(ans2[i]),put_;
	return 0;
}
posted @ 2022-10-05 16:14  1Liu  阅读(5)  评论(0)    收藏  举报