目录
一、单调栈
1、算法原理
用单调递增栈,当该元素可以入栈的时候,栈顶元素就是它左侧第一个比它小的元素。
2、代码实现
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int N=10;
int stk[N],top;
void mStack(){
int x;
cin>>x;
while(top&&stk[top]>=x) top--;//当(栈顶数)大于(输入数)时,栈顶数弹出
if(!top) printf("-1 ");//但(栈顶数)为0时,说明前面没有元素比它小
else printf("%d ",stk[top]);//当(栈顶数)小于(输入数),输出栈顶数
stk[++top]=x;//更新栈顶
}
int main(){
int n;
cin>>n;
while(n--) mStack();
return 0;
}
3、实现过程
例如:
6
4 6 3 5 8 4
1、栈顶为空,4入栈,输出-1; 0
2、栈顶为4,6>4,6入栈,输出4; 4
3、栈顶为6,3<6,6出栈; 4 6
4、栈顶为4,3<4,4出栈; 4
5、栈顶为空,3入栈,输入-1; 0
6、栈顶为3,5>3,5入栈,输出3; 3
7、栈顶为5,8>5,8入栈,输出5; 3 5
8、栈顶为8,4<8,8出栈; 3 5 8
9、栈顶为5,4<5,5出栈; 3 5
10、栈顶为4,4>3,4入栈,输出3; 3
二、直方图中最大的矩形
1、题目
直方图是由在公共基线处对齐的一系列矩形组成的多边形。矩形具有相等的宽度,但可以具有不同的高度。
例如,由高度为 2,1,4,5,1,3,3 的矩形组成的直方图,矩形的宽度都为 1。现在,请你计算在公共基线处对齐的直方图中最大矩形的面积。
2、输入格式
8
2 1 4 5 1 3 3 0
51 1000 1000 1000 1
0
3、输出结果
8
3000
4、代码实现
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=1e5+10;
int n;
int h[N];
int stk[N],top;
int l[N],r[N];
int main(){
while(cin>>n,n){
for(int i=1;i<=n;i++) scanf("%d",&h[i]);
h[0]=h[n+1]=-1; //左右端点h[0]和h[n+1]为-1;
//左侧找到第一个比它小的数
top=0;
for(int i=1;i<=n;i++){
stk[0]=0;
while(top&&h[stk[top]]>=h[i]) top--;
l[i]=i-stk[top];
stk[++top]=i;
}
//右侧找到第一个比它小的数
top=0;
for(int i=n;i>=1;i--){
stk[0]=n+1;
while(top&&h[stk[top]]>=h[i]) top--;
r[i]=stk[top]-i;
stk[++top]=i;
}
LL res=0;
for(int i=1;i<=n;i++){
res=max(res,(LL)h[i]*(l[i]+r[i]-1));
}
printf("%lld\n",res);
}
return 0;
}
三、矩形牛棚
1、题目链接
1413. 矩形牛棚 - AcWing题库高质量的算法题库https://www.acwing.com/problem/content/1415/
2、代码实现
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=3010;
int n,m,p;
bool st[N][N];
int stk[N],top;
LL res=0;
int h[N],l[N],r[N];
int main(){
cin>>n>>m>>p;
for(int i=0;i<p;i++){
int x,y;
scanf("%d%d",&x,&y);
st[x][y]=true;
}
//从下往上依次遍历->把问题化作直方图面积最大
for(int i=n;i;i--){
h[0]=-1;
h[m+1]=-1;
for(int j=1;j<=m;j++){
st[0][j]=true;
int k=i;
while(st[k][j]==false){
k--;
}
h[j]=i-k;
}
top=0;
stk[0]=0;
for(int j=1;j<=m;j++){
while(top&&h[stk[top]]>=h[j]) top--;
l[j]=j-stk[top];
stk[++top]=j;
}
top=0;
stk[0]=m+1;
for(int j=m;j>=1;j--){
while(top&&h[stk[top]]>=h[j]) top--;
r[j]=stk[top]-j;
stk[++top]=j;
}
for(int j=1;j<=m;j++){
res=max(res,(LL)h[j]*(l[j]+r[j]-1));
}
}
printf("%lld\n",res);
return 0;
}