1. 程式人生 > >單調棧模板(Java版)

單調棧模板(Java版)

單調棧是一個很神奇的東西… 比如可以用來算出陣列中每個數作為最大/最小值能向左向右延伸到那裡,從而可以來算出區間的一些問題

單調棧的思想感覺有點像尺取法,就是在一個新的數要入棧的時候就判斷然後不斷地出棧(如果需要的話),然後通過出棧完的狀態(空棧或者還有棧頂元素)來記錄當前數的狀態。

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); } } }