[51nod1102]面积最大的矩形(单调栈||预处理)
题意:求序列上某区间最小值乘区间长度的最大值。
解题关键:很早就在《挑战程序设计竞赛》中见过了,单调栈模板题,注意弹栈时如何处理后面的元素。
法一:单调栈
#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; }