日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

    歡迎訪問(wèn) 生活随笔!

    生活随笔

    當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

    编程问答

    单调栈讲解

    發(fā)布時(shí)間:2023/12/3 编程问答 41 豆豆
    生活随笔 收集整理的這篇文章主要介紹了 单调栈讲解 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

    以前一直有接觸,但是一直沒(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è)三列的矩陣…

    #include <bits/stdc++.h> using namespace std; typedef long long ll; int b[100010][110], up[110]; int main(){int T, cas=0;scanf("%d", &T);while(T--){int n, m, K;scanf("%d%d%d", &n, &m, &K);for(int i=0; i<=n; i++){for(int j=0; j<=m; j++){b[i][j]=0;up[j]=0;}}for(int i=0; i<K; i++){int x, y;scanf("%d%d", &x, &y);b[x][y]=1;}ll ans=0;for(int i=1; i<=n; i++){for(int j=1; j<=m; j++){if(b[i][j]){up[j]=i;}}for(int j=1; j<=m; j++){ll minn=0x7f7f7f7f7f7f7f7f;for(int k=j; k>0; k--){minn=min(minn, (ll)(i-up[k]));ans+=minn;}}}printf("Case #%d: %lld\n", ++cas, ans);}return 0; }

    總結(jié)

    以上是生活随笔為你收集整理的单调栈讲解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。