單調棧模板(Java版)
阿新 • • 發佈:2018-12-19
單調棧是一個很神奇的東西… 比如可以用來算出陣列中每個數作為最大/最小值能向左向右延伸到那裡,從而可以來算出區間的一些問題
單調棧的思想感覺有點像尺取法,就是在一個新的數要入棧的時候就判斷然後不斷地出棧(如果需要的話),然後通過出棧完的狀態(空棧或者還有棧頂元素)來記錄當前數的狀態。
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);
}
}
}