链接:
http://codeforces.com/contest/817/problem/D
题意:
给你n个数a[1..n]定义连续子段imbalance值为最大值和最小值的差,要你求这个数组的imbalance总值
题解:
考虑每个位置作为最值向两边的最大拓展,最小值取负号,最大值取正号,求和即可。怎么去找呢?可以维护一个单调递增栈、单调递减栈
代码:
31 int n; 32 int a[MAXN]; 33 int l_min[MAXN], r_min[MAXN], l_max[MAXN], r_max[MAXN]; 34 35 int main() { 36 ios::sync_with_stdio(false), cin.tie(0); 37 cin >> n; 38 rep(i, 1, n + 1) cin >> a[i]; 39 l_min[1] = l_max[1] = 0; 40 rep(i, 2, n + 1) { 41 l_min[i] = l_max[i] = i - 1; 42 while (l_min[i] >= 1 && a[l_min[i]] > a[i]) 43 l_min[i] = l_min[l_min[i]]; 44 while (l_max[i] >= 1 && a[l_max[i]] < a[i]) 45 l_max[i] = l_max[l_max[i]]; 46 } 47 r_min[n] = r_max[n] = n + 1; 48 per(i, 0, n) { 49 r_min[i] = r_max[i] = i + 1; 50 while (r_min[i] <= n && a[r_min[i]] >= a[i]) 51 r_min[i] = r_min[r_min[i]]; 52 while (r_max[i] <= n && a[r_max[i]] <= a[i]) 53 r_max[i] = r_max[r_max[i]]; 54 } 55 ll ans = 0; 56 rep(i, 1, n + 1) { 57 ans -= 1LL * a[i] * (i - l_min[i])*(r_min[i] - i); 58 ans += 1LL * a[i] * (i - l_max[i])*(r_max[i] - i); 59 } 60 cout << ans << endl; 61 return 0; 62 }