1215 陣列的寬度(單調棧)
阿新 • • 發佈:2018-12-19
【題目描述】
【思路】
單調棧處理左右第一處比自己小和大的位置,然後計算每個元素對答案的貢獻,注意若干相同元素不能重複計算,所以在處理左邊第一處大於自己的位置後,右邊就要處理第一處大於等於自己的位置,這樣才不會重複計算,比自己小的位置也同理
#include<stack> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=50005; int n; int a[maxn]; int Lmin[maxn],Rmin[maxn],Lmax[maxn],Rmax[maxn]; stack<int> st; int main(){ scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&a[i]); while(st.size()) st.pop(); for(int i=1;i<=n;++i){ while(st.size() && a[st.top()]>=a[i]) st.pop(); if(st.empty()) Lmin[i]=0; else Lmin[i]=st.top(); st.push(i); } while(st.size()) st.pop(); for(int i=1;i<=n;++i){ while(st.size() && a[st.top()]<=a[i]) st.pop(); if(st.empty()) Lmax[i]=0; else Lmax[i]=st.top(); st.push(i); } while(st.size()) st.pop(); for(int i=n;i>=1;--i){ while(st.size() && a[st.top()]>a[i]) st.pop(); if(st.empty()) Rmin[i]=n+1; else Rmin[i]=st.top(); st.push(i); } while(st.size()) st.pop(); for(int i=n;i>=1;--i){ while(st.size() && a[st.top()]<a[i]) st.pop(); if(st.empty()) Rmax[i]=n+1; else Rmax[i]=st.top(); st.push(i); } long long ans=0; for(int i=1;i<=n;++i){ ans+=(long long)(i-Lmax[i])*(Rmax[i]-i)*a[i]; ans-=(long long)(i-Lmin[i])*(Rmin[i]-i)*a[i]; } printf("%lld\n",ans); return 0; }