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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

单调栈学习笔记

發布時間:2023/12/6 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 单调栈学习笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?線性結構——單調棧

①定義:棧內的元素,按照某種方式排序(單調遞增或單調遞減)如果新入棧的元素破壞了單調性,就彈出棧內元素,直到滿足單調性

②優點:可以很方便地求出某個數左邊或者右邊第一個比他大或者小的元素,總時間復雜度為O(n)

③如何維護單調棧(以遞增為例)

進棧操作:每次入棧前先檢驗棧頂元素和進棧元素x的大小,如果小于x,就讓x
???? 直接入棧。如果棧頂元素大于等于x,那么出棧,直到棧空或者棧頂元素小于x。
??? ?
【例1】最大矩形面積(poj2559)

1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=100002; 4 int h[N],n; 5 int line[N],L[N],R[N],top=0; 6 int main(){ 7 scanf("%d",&n); 8 for(int i=1;i<=n;i++) 9 scanf("%d",&h[i]); 10 for(int i=1;i<=n;i++){ 11 while(top&&h[line[top]]>=h[i]) top--; 12 L[i]=top?line[top]+1:1; 13 line[++top]=i; 14 } 15 top=0; 16 for(int i=n;i>=1;i--){ 17 while(top&&h[line[top]]>=h[i]) top--; 18 R[i]=top?line[top]-1:n; 19 line[++top]=i; 20 } 21 int maxn=0; 22 for(int i=1;i<=n;i++){ 23 int ans=h[i]*(R[i]-L[i]+1); 24 maxn=max(maxn,ans); 25 } 26 cout<<maxn<<endl; 27 return 0; 28 } 代碼戳這里

?

【例2】玉蟾宮(luogu P4147)

題目傳送門

講一講我自己的思路(其實是同學教的)吧,似乎不是很好的解?但我感覺比較好理解……

首先把輸入的字符矩陣轉移為數字,即s[i][j]代表第i行第j列這一格上面連續的F的個數(如果這一格是S的話就是0),所以預處理之后就把樣例變成了這樣:

0 1 1 1 1 1

1 2 2 2 2 2

0 0 0 3 3 3

1 1 1 4 4 4

2 2 2 5 5 5

代碼實現:

for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){char ch;cin>>ch;if(ch=='F') s[i][j]=s[i-1][j]+1;}

然后就有點類似于上面那道題了,每一行分開分析,找到每一個位置可以向左右擴展的最長的長度,這是矩形的長,而組成的矩形的寬就是這一格中對應的數字,所以向左右兩邊擴展的條件就是要擴展的那一格中的數字一定大于等于當前掃描到的這一格的數字。(似乎沒太講清楚啊QAQ)每一行處理出一個可以組成的矩形的最大面積,用一個maxn取最大值就可以找到最后的答案了。

代碼實現:

for(int i=1;i<=n;i++){int ans=0;//用于記錄當前這一行的矩形最大面積for(int j=1;j<=m;j++){int l=j,r=j;//l代表左邊能擴展到的最遠位置,r代表右邊能擴展到的最遠位置while(l>=1&&s[i][l]>=s[i][j]) l--;l++;while(r<=m&&s[i][r]>=s[i][j]) r++;r--;ans=max(ans,s[i][j]*(r-l+1));//當前這一行的最大矩形面積 }maxn=max(ans,maxn);//每一行的最大矩形面積比較取最大值 }

以下完整代碼(沒開O2的時候T了兩個點QAQ)

1 // luogu-judger-enable-o2 2 #include<cstdio> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 const int N=1002; 7 int K,n,m; 8 int s[N][N]; 9 int maxn=0; 10 int max(int x,int y){ 11 return x>y?x:y; 12 } 13 int main(){ 14 //scanf("%d",&K); 15 //while(K--){ 16 memset(s,0,sizeof(s)); 17 scanf("%d%d",&n,&m); 18 for(int i=1;i<=n;i++) 19 for(int j=1;j<=m;j++){ 20 char ch; 21 cin>>ch; 22 if(ch=='F') s[i][j]=s[i-1][j]+1; 23 } 24 for(int i=1;i<=n;i++){ 25 int ans=0;//用于記錄當前這一行的矩形最大面積 26 for(int j=1;j<=m;j++){ 27 int l=j,r=j;//l代表左邊能擴展到的最遠位置,r代表右邊能擴展到的最遠位置 28 while(l>=1&&s[i][l]>=s[i][j]) l--; 29 l++; 30 while(r<=m&&s[i][r]>=s[i][j]) r++; 31 r--; 32 ans=max(ans,s[i][j]*(r-l+1));//當前這一行的最大矩形面積 33 } 34 maxn=max(ans,maxn);//每一行的最大矩形面積比較取最大值 35 } 36 printf("%d\n",maxn*3);//最后別忘了乘3 37 //} 38 return 0; 39 } 代碼戳這里

?

轉載于:https://www.cnblogs.com/THWZF/p/10161208.html

總結

以上是生活随笔為你收集整理的单调栈学习笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。