单调栈&单调队列****加粗样式
单调栈和单调队列简单的来说就是单调的栈和单调的队列(orz)。
单调栈
单调栈是维护一端,且先进后出,从栈底到栈顶单调。拿单调递增栈举例,当压入一个元素前,将栈顶元素弹出直到栈顶元素小于压入元素,从而保证队列的单调性。比如,用数列{5,4,6,2,4,3,6,5},以此构造一个单调递增栈。
根据这个原理,我们就可以写单调栈了~(推荐使用数组模拟)
int a[N];
int s[N],top=0;
for(int i=1;i<=n;i++)
{
while(top&&a[s[top]]>a[i]) top--;
if(s[top]==a[i]) s[top]=i;//去重复操作,视情况而定
s[++top]=i;
}
单调栈可以找到第i个元素之前比他大的第一个元素以及这个元素的位置。
但是,如果对于数组长度有限制,比如头尾元素之间要去元素数量<m,单调栈就用不上了,所以就需要单调队列。
单调队列
这里的队列是指双端队列,两端都可进可出
当队列内元素数目过多时,将左端点左移(和尺取法好像的说)。然后右端点安装单调栈操作就OK了~~比如,给定一个n个数的数列,从左至右输出每个长度为m的区间内的最小数。数列{2,5,4,5,3,4,6,8,5 },m=3。如图;
所以得到优先队列实现方式
int l=0,r=1;
int q[N];
for(int i=1;i<=n;i++)
{
while(l<=r&&a[q[r]]>a[i]) r--;
q[++r]=i;
while(l<-r&&q[l]<i-m+1) l++;//判断条件看情况
ans[i]=a[q[l]];
}
这东西还能优化dp ,先咕咕咕
然后转练习题!