单调栈讲解
以前一直有接觸,但是一直沒(méi)單獨(dú)進(jìn)行分析處理
單調(diào)棧:維護(hù)其中元素單調(diào)性的棧
也就是從棧底到棧頂都是有序的
維護(hù):如果入棧的元素滿足單調(diào)性,直接入棧;如果不滿足,就讓棧頂元素出棧,直到能讓入棧元素滿足單調(diào)性為止,再將元素入棧
(已經(jīng)出棧的元素就被拋棄)
例題:
求直方圖中包含的最大矩陣面積
題解鏈接
單調(diào)棧問(wèn)題
我們可以用一個(gè)單調(diào)棧來(lái)維護(hù)每個(gè)矩陣的高度和寬度,
當(dāng)前矩陣高于棧頂,進(jìn)棧
當(dāng)前矩陣a小于棧頂時(shí),直到棧為空或者棧頂矩形的高度比當(dāng)前矩形小。在出棧過(guò)程中,我們累計(jì)被彈出的矩形的寬度和。每彈出一個(gè)矩形,就用他的高度(他指被彈出的矩陣)乘上累計(jì)的寬度取更新答案,因?yàn)槊看螐棾龅母叨纫壬洗螐棾龅男?#xff0c;相當(dāng)于依次求以從左往右以每個(gè)矩陣高的面積(如圖所示)。整個(gè)出棧過(guò)程結(jié)束后,我們把一個(gè)高度為當(dāng)前矩陣高度,寬度為累計(jì)值的新矩陣入棧。
全部掃描過(guò)后,我們要將棧內(nèi)剩余矩陣依次彈出,并利用相同的方法更新答案。
最大全 1 矩陣
給一個(gè)01矩陣,問(wèn)最大的全1矩陣是多少?
題解:
先預(yù)處理,求出每一行位置上連續(xù)的最大的1的矩陣的
高度是多少,再對(duì)每一行進(jìn)行一個(gè)單調(diào)棧處理即可
代碼:
STL的stack版
typedef pair<int, int>pa;int n, m; int a[2005][2005]; pa f[2005]; stack<pa>s;int main() {while(~scanf("%d%d", &n, &m)){for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){scanf("%d", &a[i][j]);if (a[i][j]) a[i][j] += a[i-1][j];//求連續(xù)的高度 }}int ans = 0;pa v;for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){if (s.empty() && !a[i][j]) continue;if (s.empty() || s.top().second <= a[i][j])//當(dāng)高度小于時(shí) s.push(make_pair(j, a[i][j]));else {while(!s.empty() && s.top().second > a[i][j]){v = s.top();s.pop();int area = (j-v.first)*v.second;//求面積 if (area > ans) ans = area; }s.push(make_pair(v.first, a[i][j]));}}}printf("%d\n", ans);}return 0; }手寫(xiě)stack版
for(int i=1;i<=n;i++){top=0;//每一行清空棧 for(int j=1;j<=m+1;j++){if(top==0||ri[i][j]>=ri[i][st[top]]){st[++top]=j;}else { int id; while(top!=0&&ri[i][j]<ri[i][st[top]]){id=st[top];top--;int w=min(j-id,ri[i][id]);ans=max(ans,w*w);ans2=max(ans2,(j-id)*ri[i][id]);}st[++top]=id;//將最后一次出棧的棧頂元素延申并入棧ri[i][id]=ri[i][j]; }}}ACM-ICPC 2018 南京賽區(qū)網(wǎng)絡(luò)預(yù)賽 B-The writing on the wal
給你一個(gè)n * m(1e5 * 100)的矩陣和k(1e5)個(gè)黑點(diǎn),黑點(diǎn)會(huì)給定坐標(biāo),問(wèn)有多少個(gè)不含這些黑點(diǎn)的子矩形。
參考代碼
這個(gè)講的巨詳細(xì)
題解:
相當(dāng)于每次從一個(gè)矩陣的最右下角開(kāi)始加一個(gè)一列的矩陣,加一個(gè)兩列的矩陣,加一個(gè)三列的矩陣…
總結(jié)
- 上一篇: VR产业及产品 2020-12
- 下一篇: 洛谷 P1903 [国家集训队]数颜色