Codeforces 817D Imbalanced Array
题目链接
https://codeforces.com/contest/817/problem/D
题目大意
给你一个序列,让你求出这个序列的每个区间最大值的和 - 最小值的和
解题思路
单调栈
单调栈经典问题。
我们先求出以 a[ i ] 为最小值的左右最长拓展 L1[i] , R1[i]
那么以 a[ i ] 为最小值的区间个数就为 (L1[ i ] + 1) * (R1[ i ] + 1)
再求出以 a[ i ] 为最大值的左右最长拓展 L2[ i ] , R2[ i ]
那么以 a[ i ] 为最大值的区间个数就为 (L2[ i ] + 1) * (R2[ i ] + 1)
最后线性扫一遍即可
(为了避免相同值区间长度被重复计算,需采用左开右闭的维护方式)
AC_Coder
#include<bits/stdc++.h> #define rep(i,a,n) for (int i=a;i<=n;i++) #define per(i,n,a) for (int i=n;i>=a;i--) #define int long long using namespace std; const int N = 1e6 + 10; int a[N] , sta[N] , l[N] , r[N] , ans; signed main() { int n ; cin >> n; rep(i , 1 , n) cin >> a[i]; int top = 0; rep(i , 1 , n) { while(top && a[sta[top]] >= a[i]) top -- ; if(!top) l[i] = i - 1; else l[i] = i - sta[top] - 1; sta[++ top] = i; } top = 0; per(i , n , 1) { while(top && a[sta[top]] > a[i]) top --; if(!top) r[i] = n - i; else r[i] = sta[top] - i - 1; sta[++ top] = i; } rep(i , 1 , n) ans -= a[i] * (l[i] + 1) * (r[i] + 1); top = 0; rep(i , 1 , n) { while(top && a[sta[top]] <= a[i]) top -- ; if(!top) l[i] = i - 1; else l[i] = i - sta[top] - 1; sta[++ top] = i; } top = 0; per(i , n , 1) { while(top && a[sta[top]] < a[i]) top --; if(!top) r[i] = n - i; else r[i] = sta[top] - i - 1; sta[++ top] = i; } rep(i , 1 , n) ans += a[i] * (l[i] + 1) * (r[i] + 1); cout << ans << '\n'; return 0; }
凡所不能将我击倒的,都将使我更加强大