单调性的应用
在做题过程中,利用题目的单调性或运用单调性会很好的帮助我们解题
经典的运用单调性的,有单调队列,单调栈。其他的在题目中的单调性,我们经常会运用到,平移,滑动等思想。
我们先来复习单调栈和单调队列,体会单调性的有趣。
单调栈
首先我们知道栈,是一种先进先出的线性数据结构。
那我们先来了解一下单调栈的简单应用
我们有多个矩阵,求被这些矩阵覆盖的最大矩阵面积
图片暂无
做法肯定是单调栈,那我们考虑如何找到与单调性有关的东西。
先来想,假设矩阵是单调递增的,如何做?
可以枚举每个矩阵的高,以该矩阵的高为答案矩阵的高,以该矩阵之后的宽度为答案矩阵的宽度。
那我们回来考虑之前的问题,如何处理不但单调的矩阵。
可以让矩阵变的单调,对于一个比栈队尾小的矩阵,我们把前一个矩阵大于当先矩阵的部分消除,就可以维护单调了。
并且我们直接消掉并不会对之后的答案产生什么影响。
对于消掉的矩阵,要计算可能的答案
for (int i = 1;i <= n;i ++) scanf("%d",&a[i]);
a[n + 1] = 0;
for (int i = 1;i <= n + 1;i ++) {
if (a[s[top]] <= a[i]) {
s[++top] = i;
w[top] = 1;
}
else {
int res = 0;
while (a[i] < a[s[top]]) {
res += w[top];
answer = max (answer, 1ll * a[s[top]] * res);
top --;
}
s[++top] = i;
w[top] = res + 1;
}
}
有一些例题
单调队列
单调队列,是在队列中维护单调性,最简单应用的是滑动窗口。
维护单调时,加入一些数,同时把一些不满足要求的数弹出。
for(int i = 1;i <= n;i ++)
{
if(h<=t && q[h] < i-m+1)h ++;
while(h<=t && f[i] <= f[q[t]])t--;
q[++t] = i;
if(i > m - 1)printf("%d ",f[q[h]]);
}
我们利用这一点可以,维护一个保持最优的待选集合,从而去优化DP
P1725 琪露诺
关于单调性还有很多技巧,作者水平有限,暂不介绍。之后可能会有修改补充。