[51Nod] (1102) 面積最大的矩形 ---- 單調棧(思維)
阿新 • • 發佈:2018-12-22
思路:
- 自己的想法跟題解一樣,也是從左右兩邊找到最遠能擴充套件的位置。但這樣複雜度一定是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;
}