单调栈是一个很神奇的东西…
比如可以用来算出数组中每个数作为最大/最小值能向左向右延伸到那里,从而可以来算出区间的一些问题
单调栈的思想感觉有点像尺取法,就是在一个新的数要入栈的时候就判断然后不断地出栈(如果需要的话),然后通过出栈完的状态(空栈或者还有栈顶元素)来记录当前数的状态。
hdu1506 求最大的矩形面积,其实也就相当于求每个高度作为区间的最小值能延伸到哪里,那对应的矩形面积就是这个高度乘以这个延伸到的区间长度
以这题来看,具体就是当一个数要入栈时,先判断栈是否为空,如果非空而且当前高度小于等于栈顶高度,那这个栈顶元素就要出栈,只要栈顶元素大于要加入的元素,即保持这个栈的单调性(栈底最小,栈顶最大),出栈完之后就要记录要加入这个数的状态了,因为栈中存的就是数组下标,所以这个要加入的数作为最小值就能延伸到栈顶元素的下标+1了,而如果是空栈,那就说明可以延伸到第一个元素,然后就将这个元素加入栈中,进行下一个元素的操作
import java.util.Scanner;
import java.util.Stack;
public class Main {
static int n;
static final int N=(int)1e5+50;
static long[] a=new long[N];
static int[] ll=new int[N],rr=new int[N];
static long solve(){
Stack<Integer> s=new Stack<>();
for(int i=1;i<=n;i++){
while(s.size()>0 && a[i]<=a[s.peek()]){
s.pop();
}
if(s.size()==0){
ll[i]=1;
}
else{
ll[i]=s.peek()+1;
}
s.push(i);
}
s=new Stack<>();
for(int i=n;i>=1;i--){
while(s.size()>0 && a[i]<=a[s.peek()]){
s.pop();
}
if(s.size()==0){
rr[i]=n;
}
else{
rr[i]=s.peek()-1;
}
s.push(i);
}
for(int i=1;i<=n;i++){
System.out.print(ll[i]+" ");
}
System.out.println();
for(int i=1;i<=n;i++){
System.out.print(rr[i]+" ");
}
System.out.println();
long ans=0;
for(int i=1;i<=n;i++){
ans=Math.max(ans,a[i]*(rr[i]-ll[i]+1));
}
return ans;
}
public static void main(String[] args) {
Scanner cin=new Scanner(System.in);
while(cin.hasNext()){
n=cin.nextInt();
if(n==0){
break;
}
for(int i=1;i<=n;i++){
a[i]=cin.nextLong();
}
long ans=solve();
System.out.println(ans);
}
}
}