CodeForces - 817D Imbalanced Array(单调栈)
題目鏈接:點(diǎn)擊查看
題目大意:給出一個(gè)長度為 nnn 的序列,求出所有子區(qū)間的最大值與最小值之差的和
題目分析:不難看出最大值和最小值之差的和可以拆開,拆成最大值之和與最小值之和之差,現(xiàn)在問題轉(zhuǎn)換為如何求解所有子區(qū)間內(nèi)的最值之和
可以單調(diào)棧維護(hù)每個(gè)數(shù)字的可行范圍,這里以最小值為例,當(dāng)我們遍歷到 iii 位置時(shí),我們只需要求出左側(cè)首次小于 a[i]a[i]a[i] 的位置 lll,以及右側(cè)首次小于 a[i]a[i]a[i] 的位置 rrr,那么 a[i]a[i]a[i] 的貢獻(xiàn)就是:左端點(diǎn)屬于區(qū)間 [l,i][l,i][l,i],同時(shí)右端點(diǎn)屬于區(qū)間 [i,r][i,r][i,r] 的子區(qū)間了。
但是上述做法只適用于 nnn 個(gè)數(shù)字互不相同,如果遇到重復(fù)的數(shù)字會重復(fù)計(jì)算答案。
該怎么解決呢?其實(shí)仔細(xì)思考一下不難發(fā)現(xiàn),可以令區(qū)間變成左閉右開或左開右閉,換句話說我們只需要讓 lll 變成左側(cè)首個(gè)小于等于 a[i]a[i]a[i] 的位置或者讓 rrr 變成右側(cè)首個(gè)小于等于 a[i]a[i]a[i] 的位置就好了
具體證明可以口胡一下,對于一段連續(xù)數(shù)列 {2,2,2}\{2,2,2\}{2,2,2} 來說,如果 lll 表示的是左側(cè)首個(gè)小于 a[i]a[i]a[i] 的位置,rrr 表示的是右側(cè)首個(gè)小于等于 a[i]a[i]a[i] 的位置,那么得到的三個(gè)開區(qū)間就是 (0,2),(0,3),(0,4)(0,2),(0,3),(0,4)(0,2),(0,3),(0,4),發(fā)現(xiàn)確實(shí)是覆蓋了所有的區(qū)間
代碼:
// Problem: J - Imbalanced Array // Contest: Virtual Judge - 7.31限時(shí)訓(xùn)練(生成樹,樹的直徑,單調(diào)棧)2 // URL: https://vjudge.net/contest/450440#problem/J // Memory Limit: 262 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org)// #pragma GCC optimize(2) // #pragma GCC optimize("Ofast","inline","-ffast-math") // #pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #include<list> #include<unordered_map> #define lowbit(x) (x&-x) using namespace std; typedef long long LL; typedef unsigned long long ull; template<typename T> inline void read(T &x) {T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f; } template<typename T> inline void write(T x) {if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0'); } const int inf=0x3f3f3f3f; const int N=1e6+100; int l[N],r[N]; LL a[N]; stack<int>st; void init() {while(st.size()) {st.pop();} } int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);int n;LL ans=0;read(n);for(int i=1;i<=n;i++) {read(a[i]);}init();for(int i=1;i<=n;i++) {while(st.size()&&a[st.top()]<=a[i]) st.pop();if(st.empty()) l[i]=0;else l[i]=st.top();st.push(i);}init();for(int i=n;i>=1;i--) {while(st.size()&&a[st.top()]<a[i]) st.pop();if(st.empty()) r[i]=n+1;else r[i]=st.top();st.push(i);}for(int i=1;i<=n;i++) {ans+=a[i]*(r[i]-i)*(i-l[i]);}init();for(int i=1;i<=n;i++) {while(st.size()&&a[st.top()]>=a[i]) st.pop();if(st.empty()) l[i]=0;else l[i]=st.top();st.push(i);}init();for(int i=n;i>=1;i--) {while(st.size()&&a[st.top()]>a[i]) st.pop();if(st.empty()) r[i]=n+1;else r[i]=st.top();st.push(i);}for(int i=1;i<=n;i++) {ans-=a[i]*(r[i]-i)*(i-l[i]);}cout<<ans<<endl;return 0; }總結(jié)
以上是生活随笔為你收集整理的CodeForces - 817D Imbalanced Array(单调栈)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AtCoder - arc098_b X
- 下一篇: 洛谷 - P3246 [HNOI2016