单调栈
单调栈,指严格单调递增或单调递减的栈,跟单调队列差不多,但是只用到它的一端。
例题
例题来源:AcWing题库830
解题思路
如果用暴力搜索的方法,是会超时的,那么考虑单调栈优化。
时间复杂度在O(n)左右。
首先,如果不满足单调性,就将元素弹出栈。
当该元素可以入栈的时候,栈顶元素就是它左侧第一个比它小的元素。
如果栈空,就意味着左边没有比它小的数,输出-1。
最后输出栈顶。
AC代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
int stk[N],arr[N],t = -1;
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>arr[i];
for(int i=1;i<=n;i++)
{
while(t >= 0 && arr[i] <= stk[t]) t--;//先把不满足的出栈
if(t == -1)
{
cout<<-1<<" "; //如果栈空,左边没有小的
}
else
{
cout<<stk[t];
}
stk[++t] = arr[i];
}
}
单调队列
单调队列,即单调递减或单调递增的队列。使用频率不高,但在有些程序中会有非同寻常的作用。
例题
例题来源:AcWing题库154
解题思路
使用单调队列优化这道题,时间复杂度也在O(n)左右。
当队列不为空,且当前滑动窗口大小>设定的大小,就弹出元素维护。
当队列不为空且当队列队尾元素>=当前元素时,那么队尾元素就一定不是当前窗口的最小值,这时删去队尾元素,加入当前元素。
第二遍循环类比上面思路找最大值。
AC代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+5;
int arr[N],q[N];
int main()
{
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>arr[i];
}
int h = 0,t = -1;
for(int i=1;i<=n;i++)
{
if(h <= t && i-k+1 > q[h]) h++;
//当队列不为空,且当前滑动窗口大小>设定的大小,就弹出元素维护?
while(h <= t && arr[q[t]] > arr[i]) t--;
//队列不为空,对队尾元素大于当前元素,队尾元素就不是最小值,弹出,加入当前元素。
q[++t] = i;
if( i >= k) cout<<arr[q[h]]<<" ";
}
cout<<endl;
h = 0;t = -1;
for(int i=1;i<=n;i++)
{
if(h <= t && i-k+1 > q[h]) h++;
while(h <= t && arr[q[t]] <= arr[i]) t--;
q[++t] = i;
if( i >= k) cout<<arr[q[h]]<<" ";
}
return 0;
}