这里写目录标题
一、单调栈
入门
#include<bits/stdc++.h>
using namespace std;
int main(){
int stk[100000], tt = 0;
int x, n;
cin >> n;
for (int i = 0; i < n;i++){
scanf("%d", &x);
while(tt&&stk[tt]>=x)
tt--;
if(tt)
cout << stk[tt] << " ";
else
cout << -1 << " ";
stk[++tt] = x;
}
}
//求左边最近的小的数
// stk[1]是最左边没有比他小的数,stk[i]是左边的数,如此一直更新
进阶(直方图中的最大矩形)
分析过程
#include <bits/stdc++.h>
using namespace std;
#define LL long long
int q[1000000], a[1000000], l[1000000], r[10000000];
int n;
int main()
{
while (scanf("%d", &n), n)
{
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
}
a[0] = a[n + 1] = -1;
int tt = -1;
q[++tt] = 0;
for (int i = 1; i <= n; i++)
{
while (a[q[tt]] >= a[i])
{
tt--;
}
l[i] = i - q[tt];
q[++tt] = i;
}
tt = -1;
q[++tt] = n + 1;
for (int i = n; i >= 1; i--)
{
while (a[q[tt]] >= a[i])
{
tt--;
}
r[i] = q[tt] - i;
q[++tt] = i;//重点
}
LL res = 0;
for (int i = 1; i <= n; i++)
{
res = max(res, (LL)a[i] * (r[i] + l[i] - 1));
}
printf("%lld\n", res);
}
}
// q[tt] ->q[1]代表左边都比它高的 个数,
// a[i]-> 6 8 4 5 2
// q[i]-> \ \ 3(q[1]) 4(q[2]) 5(q[1])
二、单调队列(滑动窗口)
基本思想:去除多余元素,从而维护单调性。
题解:
#include <bits/stdc++.h>
using namespace std;
int a[1000000], q[1000000];
int main()
{
int n, k;
cin >> n >> k;
for (int i = 0;i<n;i++){
scanf("%d", &a[i]);
}
int hh = 0,tt = -1;
for (int i = 0;i<n;i++){
if(hh<=tt&&q[hh]<i-k+1)
hh++;
while (hh <=tt && a[q[tt]] >=a[i]){
tt--;
}
q[++tt] = i;
if(i>=k-1){
printf("%d ", a[q[hh]]);
}
}
puts("");
hh = 0, tt = -1;
for (int i = 0; i < n; i++)
{
if (hh <=tt && q[hh] < i - k + 1)
hh++;
while (hh <= tt && a[q[tt]] <=a[i])
{
tt--;
}
q[++tt] = i;
if (i >= k - 1)
{
printf("%d ", a[q[hh]]);
}
}
}