【AcWing】131. 直方圖中最大的矩形
阿新 • • 發佈:2021-07-21
簡單易懂
利用單調棧:尋找比p[i]小的下一個值的位置和上一個值的位置;
#include<bits/stdc++.h> using namespace std; #define ll long long #define LL long long #define MS 3000009 LL n,m; stack<LL > sta; LL ans; struct node{ int l,r; LL val; }p[MS]; void solve(){ p[n+1] = p[0] = {0,0,-1}; for(int i=1;i<=n+1;i++){ // 尋找 p[i] 後第一個比 p[i] 小的位置 if(sta.empty() || p[sta.top()].val <= p[i].val) sta.push(i); else{ while(!sta.empty() && p[sta.top()].val > p[i].val){ int t = sta.top(); sta.pop(); p[t].r = i-1; } sta.push(i); } } while(!sta.empty()) sta.pop(); for(int i=n;i>=0;i--){ // 尋找 p[i] 前第一個比 p[i] 小的位置 if(sta.empty() || p[sta.top()].val <= p[i].val) sta.push(i); else{ while(!sta.empty() && p[sta.top()].val > p[i].val){ int t = sta.top(); sta.pop(); p[t].l = i+1; } sta.push(i); } } while(!sta.empty()) sta.pop(); // getans LL ans = 0; for(int i=1;i<=n;i++){ ans = max(ans ,p[i].val*(p[i].r-p[i].l+1)); } cout << ans << "\n"; } int main(){ ios::sync_with_stdio(false); while(cin >> n && n){ for(int i=1;i<=n;i++){ cin >> p[i].val; p[i].l = p[i].r = i; } solve(); } return 0; }
小小優化
#include<bits/stdc++.h> using namespace std; #define ll long long #define LL long long #define MS 3000009 LL n,m; LL p[MS]; stack<LL > sta; LL ans; void solve(){ ans = 0; p[++n] = -1; for(int i=1;i<=n;i++){ if(sta.empty() || p[sta.top()] <= p[i]){ sta.push(i); } else{ LL t; while(!sta.empty() && p[sta.top()] > p[i]){ t = sta.top(); sta.pop(); ans = max(ans ,(i-t)*p[t] ); } // 由於p[i]這個值左邊可能向左擴充套件 // 所以直接將i的位置改到它能擴充套件的最左位置 // 這樣求面積遍歷陣列只要從左到右一遍過 sta.push(t); p[t] = p[i]; } } while(!sta.empty()) sta.pop(); cout << ans << "\n"; } int main(){ ios::sync_with_stdio(false); while(cin >> n && n){ for(int i=1;i<=n;i++){ cin >> p[i]; } solve(); } return 0; }