1. 程式人生 > >[51nod1102]面積最大的矩形(單調棧||預處理)

[51nod1102]面積最大的矩形(單調棧||預處理)

return 棧模板 模板題 type its 長度 bit -- blog

題意:求序列上某區間最小值乘區間長度的最大值。

解題關鍵:很早就在《挑戰程序設計競賽》中見過了,單調棧模板題,註意彈棧時如何處理後面的元素。

法一:單調棧

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
stack<int>s;
ll a[50002];
int main(){
    int n;
    cin>>n;
    for(int i=0;i<n;i++) cin>>a[i];a[n]=-1;
    ll ans=0,tmp;
    
for(int i=0;i<=n;i++){ if(s.empty()||a[i]>a[s.top()]) s.push(i); else if(a[i]<a[s.top()]){ while(!s.empty()&&a[i]<a[s.top()]){ tmp=s.top(); s.pop(); ans=max(ans,1ll*(i-tmp)*a[tmp]); } s.push(tmp); a[tmp]
=a[i]; } } cout<<ans<<"\n"; return 0; }

法二:預處理,向左向右到達的範圍。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[50002],l[50002],r[50002];
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for
(int i=1;i<=n;i++){ int k=i-1; while(a[k]>=a[i]){ k=l[k]-1; } l[i]=k+1; } for(int i=n;i>=1;i--){ int k=i+1; while(a[k]>=a[i]){ k=r[k]+1; } r[i]=k-1; } ll ans=0; for(int i=1;i<=n;i++){ ans=max(ans,(r[i]-l[i]+1)*a[i]); } cout<<ans<<"\n"; return 0; }

[51nod1102]面積最大的矩形(單調棧||預處理)