1. 程式人生 > >[51Nod] (1102) 面積最大的矩形 ---- 單調棧(思維)

[51Nod] (1102) 面積最大的矩形 ---- 單調棧(思維)

題目傳送門

思路:

  • 自己的想法跟題解一樣,也是從左右兩邊找到最遠能擴充套件的位置。但這樣複雜度一定是O(n^2)
  • 顯然會超時,於是自己發現除了這個思路沒有好辦法了,於是去學習一波新技能√ ---- 單調棧!
  • 單調棧其實精湛的不是用棧去實現,而是一種思維,用這種單調的思維去降低複雜度。
  • 以這個題為例,我們可以給每個位置pos,記錄它向右最遠的擴充套件距離R[pos],向左最遠的擴充套件距離L[pos]。
  • 舉個栗子:
  • 如果從位置i 想左進行擴充套件,第一個index = i-1,如果val[index]>=val[i],證明可以繼續向左擴充套件,這時候index不需要向前走一步,而是走l[index]步,中間的這些一定也是>=val[i]的。即是單調的!醬紫就少了很多冗餘的判斷,使得整個過程幾乎是單調的。這就是單調棧精髓的地方!
  • 所以我們預處理好每個位置,然後找到max(l[i]+r[i]+1)*val[i] 即可

AC程式碼:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define IO          ios_base::sync_with_stdio(0),cin.tie(0)
#define pb(x)       push_back(x)
#define sz(x)       (int)(x).size()
#define abs(x) ((x) < 0 ? -(x) : x) #define mk(x,y) make_pair(x,y) #define fin freopen("in.txt","r",stdin) #define fout freopen("out.txt","w",stdout) typedef long long ll; typedef pair<int,int> P; const int mod = 1e9+7; const int maxm = 1e8+5; const int maxn = 1e5+5
; const int INF = 0x3f3f3f3f; const ll LINF = 1ll<<62; ll a[maxn]; ll l[maxn]; ll r[maxn]; int main() { // fin; // IO; int n; while(~scanf("%d",&n)) { for(int i=1;i<=n;i++) scanf("%lld",&a[i]); for(int i=1;i<=n;i++){ int index = i-1; l[i] = 1; while(a[i]<=a[index] && index>=1){ l[i]+=l[index]; index-=l[index]; } } for(int i=n;i>=1;i--){ int index = i+1; r[i] = 1; while(a[i]<=a[index] && index<=n) { r[i]+=r[index]; index+=r[index]; } } ll res = 0; for(int i=1;i<=n;i++){ res = max(a[i]*(l[i]+r[i]-1),res); } printf("%lld\n",res); } return 0; }