讲单调栈的博文 点击打开链接
给你一个区间里的每个数,求区间大小分别为1,2,3,4.....每个小区间的数中最小值,再求这些最小值中的最大值
用单调栈可以在on内算出每个数的左边右边第一个小于这个数的值的位置
然后int len=r[i]-l[i]+1,就可以算出区间长度为len的最小值
考虑到有些区间长度可能并不会出现,根据res[i-1]=max(res[i-1],res[i])
即区间长度为i-1的最小值的最大值至少为res[i]
所以最后需要在遍历一遍,补齐res数组
#include<iostream>
#include<stdio.h>
#include<stack>
#define N 200005
using namespace std;
int a[N],l[N],r[N],res[N];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
stack<int> ss;
for(int i=1;i<=n;i++)
{
while(!ss.empty() && a[ss.top()]>=a[i])
ss.pop();
if(ss.empty())
l[i]=1;
else
l[i]=ss.top()+1;//记录第i位为最小值的左端点
ss.push(i); //压进栈的不是数,而是这个数的位置
}
while(!ss.empty())
ss.pop();
for(int i=n;i>0;i--)
{
while(!ss.empty() && a[ss.top()]>=a[i])
ss.pop();
if(ss.empty())
r[i]=n;
else
r[i]=ss.top()-1;//记录第i位为最小值的右端点
ss.push(i);
}
for(int i=1;i<=n;i++)
{
int len=r[i]-l[i]+1;
res[len]=max(res[len],a[i]);
}
for(int i=n-1;i>=1;i--)
{
res[i]=max(res[i],res[i+1]);
}
for(int i=1;i<=n;i++){
printf("%d",res[i]);
if(i==n) printf("\n");
else printf(" ");
}
}