單調棧的簡單操作
阿新 • • 發佈:2018-12-19
單調棧的模板題 單調棧的定義: 單調遞增或單調減的棧,跟單調佇列差不多,但是隻用到它的一端 1.維護從左往右遞增棧可以得到左邊第一個比a[i]小的元素位置L[i]。 2.維護從左往右遞減棧可以得到左邊第一個比a[i]大的元素位置L[i]。 3.維護從右往左遞增棧可以得到右邊第一個比a[i]小的元素位置R[i]。 4.維護從右往左遞減棧可以得到右邊第一個比a[i]大的元素位置R[i]。
模板
Stack<int> S; int a[N], L[N]; for(int i=1 ;i<=n ;i++){ while(S.size() && a[S.top()] >= a[i]) S.pop();//嚴格單調or非嚴格? if(S.empty()) L[i] = 0; else L[i] = S.top(); S.push(i); }
例題:HDU - 1506 新增連結描述 程式碼:
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<stack> #include<cstring> using namespace std; const int n=100100; typedef long long ll; stack<int>s; int l[n],r[n]; ll f[n]; int main(){ int m; while(scanf("%d",&m)!=EOF){ if(m==0) break; for(int i=1;i<=m;i++) scanf("%d",&f[i]); while(s.size()) //清空棧 s.pop(); for(int i=1;i<=m;i++){ while(s.size()&&f[s.top()]>=f[i])//找到左面第一個比他小的陣列的下標 s.pop(); if(s.empty())//如果是空棧了就預設為第一個比他小的陣列下標是第一個,這個通過自己畫畫圖就可以知道 l[i]=1; else l[i]=s.top()+1; s.push(i); } while(s.size()) s.pop(); for(int i=m;i>=1;i--){ while(s.size()&&f[s.top()]>=f[i])//找到右邊第一個比他小的陣列下表 s.pop(); if(s.empty()) r[i]=m; else r[i]=s.top()-1; s.push(i); } ll ans=0; for(int i=1;i<=m;i++) ans=max(ans,f[i]*(r[i]-l[i]+1)); printf("%lld\n",ans); } return 0; }