1. 程式人生 > >D - Bad Hair Day POJ - 3250 -單調棧-第一彈

D - Bad Hair Day POJ - 3250 -單調棧-第一彈

  • 單調棧是什麼:

  • 單調棧就是一個單調遞增/遞減的棧,每個元素僅入棧一次,例如維護一個遞增的單調棧的話,若入棧元素小於棧頂元素就要將棧中小於入棧元素的元素全部pop出去,再push這個元素,這樣就在O(n)的複雜度內維護了一個單調棧
  • 單調棧能做什麼

  • 1.最基礎的應用就是給定一組數,針對每個數,尋找它和它右邊第一個比它大的數之間有多少個數。
  • 2.給定一序列,尋找某一子序列,使得子序列中的最小值乘以子序列的長度最大。
  • 3.給定一序列,尋找某一子序列,使得子序列中的最小值乘以子序列所有元素和最大。
  • 應用1對應題目:
  • D - Bad Hair Day

  •  POJ - 3250 
  • 題意:cow 可以看見右邊strictly shorter嚴格比他矮的cow 求一下所有cow 能看見的總數
  • 思路:維護一個單調遞減的棧,入棧元素為結構體(需要儲存其高度與位置),遇到當前元素
  • 大於等於棧內元素時,棧頂元素開始出棧,出棧是累計結果,因為直到此處是棧內元素所能看見的cow的數量。
  • 最後再依次處理一下棧內剩下的元素。它們所能看到的就是一直到結尾了 ,
  • #include<stdio.h>
    #include<stack>
    using namespace std;
    #define ll long long
    struct node
    {
        int id,h;
    } a;
    stack<node>stk;
    ll n,ans;
    int main()
    {
        scanf("%lld",&n);
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a.h);
            a.id=i;
            if(stk.empty())
                stk.push(a);
            else
            {
                while(!stk.empty()&&stk.top().h<=a.h)
                {
                    ans+=i-stk.top().id-1;
                    stk.pop();
                }
                stk.push(a);
            }
        }
        while(!stk.empty())
        {
            ans+=n-stk.top().id;
            stk.pop();
        }
        printf("%lld\n",ans);
        return 0;
    }
  •