單調棧 四個例題

2021-09-29 11:13:20 字數 3212 閱讀 2600

普通棧就5個操作

#include0.stack《型別》 名字;   建立

1.名字.push(元素); 壓入棧變為新的棧頂

2.m=名字.top(); 獲取棧頂元素

3.名字.pop() ; 彈出棧頂元素

4.length=名字.size() 獲取棧內元素長度

ps: 對於 順序棧和鏈棧 相對於普通棧來說 效率會相對高一點

(普通棧考慮太多東西從而使效率降低 而對某一專一問題用順序棧 和 鏈棧 就可以解決效率高些嘛… )

然後 三類題目;

1.最基礎的應用就是給定一組數,針對每個數,尋找它和它右邊第乙個比它大的數之間有多少個數。 poj3250

2.給定一串行,尋找某一子串行,使得子串行中的最小值乘以子串行的長度最大。poj2559

3.給定一串行,尋找某一子串行,使得子串行中的最小值乘以子串行所有元素和最大。poj3494

小生不才,百思不得其解…於是偷瞄答案…我去還可以醬紫~;

0.poj3250

仔細看看大神**

個人題解

//為什麼會超過int型…… 

#include

#include

#include

#include

#define inf 0x3f3f3f3f

using

namespace std;

typedef

long

long ll;

intmain()

else

st.push

(i);

//當所有破壞棧的單調性的元素都出棧後,將當前元素入棧 }}

printf

("%lld\n"

,ans);}

return0;

}

1.poj2559

這個要好好看 ,我是真沒看懂

用紙和筆推演了一遍才看明白

(最好能自己推…看我寫的注意點…容易變傻(我都感覺太細了))

#include

#include

#include

#include

using

namespace std;

typedef

long

long ll;

intmain()

else

st.push

(top)

;//只將可以延伸到的最左端的位置入棧

a[top]

=a[i]

;//並修改該位置的值 }}

printf

("%lld\n"

,ans);}

return0;

}

注意點:

0.我用c++寫的 tle 了幾次 可能要用scanf() 以及printf();

wr a陣列沒有用long long ;然後終於…ac!

1.由於咱們這個 棧是單調遞增的所以後面的元素一定大於前面的;

醬紫就意味著 i到top(這個是棧頂元素也就是a的下標吧)之間的資料的公共部分是a[top];

也就是tmp 是目前的的 公共面積值;

2.更新單調棧內元素 只要把最後乙個大於a[i] 的下標送進去也就是top

然後把 a[top]更新為新的最小的值a[i]至於原因嗎:因為到i為止最大的就是他了…

相當於更新 新的單調遞增棧 ; 其次就是我們要用距離 * 最小值=tmp所以

一定要將i能變成的a的最小的下標加入到單調棧中去嘛~可以當作x-y座標系來看這個題;

2.poj3494

感覺很巧,大神思路很すごい

大神**

感覺還是看我的**吧…自己看思路寫的…你仔細研究過2559應該能看懂吧…大神**有解析

#include

#include

#include

#include

using

namespace std;

intmain()

a[n+1]

=-1;

//設最後元素為最小值,以最後讓棧內元素出棧

for(j=

1;j<=n+

1;j++

)else

st.push

(top)

;//將最後一次出棧的棧頂元素延伸併入棧

a[top]

=a[j]

;//修改其對應的值 }}

}printf

("%d\n"

,ans);}

return0;

}

3.poj2796

…心態也就呢樣了…

個人解析在下面…也就理解理解了…感覺就會說句 なるほど

#include

#include

#include

using

namespace std;

typedef

long

long ll;

intmain()

a[n+1]

=-1;

//將最後乙個設為最小值,以最後讓棧內元素全部出棧

ans=0;

for(i=

1;i<=n+

1;i++

)else

} st.

push

(top)

;//將最後一次出棧的棧頂元素入棧

a[top]

=a[i]

;//將其向左向右延伸並更新對應的值 }}

printf

("%lld\n"

,ans)

;printf

("%d %d\n"

,pos1,pos2-1)

;}return0;

}

現將每乙個的字首和求出

對a陣列單調遞增 …將其下標加入棧中然後遇到小於的棧頂的 就求區間和(sum[i-1]-sum[top-1])*a[top];

彈出棧頂就這個樣子 因為單調遞增 所以如果每次彈出的棧頂一定是區間 內最小的a; 別忘記更新棧

將最後乙個彈出的棧頂入棧 並且將其值更新為新的最小值

入棧原因感覺就像是 劃分了乙個區域(看做乙個點)/斷點(新的起點) 比如1234 1234-1 或者1234 0 12345-1

參考文章

單調佇列和單調棧例題

1 單調佇列 給出乙個長度為n的序列和區間長度k 從左向右對每乙個長度為k的區間詢問最大值和最小值。思路 對於最小值,考慮維護乙個遞增的雙端佇列,每次入隊時將隊尾比當前入隊元素的全部刪除,每次取隊首並且判斷是否在當前區間內即可 author hairu,wu from ahut include in...

單調棧與單調佇列簡單例題

poj3250 題意 有n只奶牛排成一列向右看,每頭奶牛只能看到比自己矮的奶牛,即會被高的奶牛擋住後面,問共有多少只奶牛能被看到 思路 考慮每頭奶牛能被前面牛看到的次數,也就是從他左邊開始單調遞減的序列的長度,用單調棧維護即可 include includeusing namespace std c...

單調棧 模板及相應例題

單調棧可以存一段元素每個之前第乙個比它小的元素的下標,沒有的置為 1。以下是單調遞增棧的模板,即棧中的元素為單調遞增的。在入棧之前記錄當前元素左邊第乙個比他小的元素的下標 for int i 1 i n i 以下是單調遞減棧的模板,即棧中的元素為單調遞減的,若當前元素比棧頂元素大,所以棧頂元素為第乙...