题目链接:http://codeforces.com/contest/817/problem/D
题意:给你n个数a[1..n]定义连续子段imbalance值为最大值和最小值的差,要你求这个数组的imbalance总值
题解:首先要知道imbalance的值可以有所有区间的Max的和减去所有区间Min的和。那么就是怎么求所有区间的Max和与Min和。要知道如果是以a[i]为最小值那么最小值为a[i]的区间数为a[i]左边第一个小于a[i]的位置l,a[i]右边第一个大于等于a[i]的位置r,ans=r*l*a[i]。然后就是怎么快速求解。这里可以利用一下单调栈的思想。具体看一下代码。
#include <iostream> #include <cstring> #include <cstdio> using namespace std; typedef long long ll; const int M = 1e6 + 10; ll a[M] , dpl_Max[M] , dpl_Min[M] , dpr_Max[M] , dpr_Min[M]; int main() { int n; scanf("%d" , &n); for(int i = 1 ; i <= n ; i++) scanf("%lld" , &a[i]); dpl_Max[1] = 0 , dpl_Min[1] = 0; for(int i = 2 ; i <= n ; i++) { dpl_Max[i] = dpl_Min[i] = i - 1; while(dpl_Max[i] >= 1 && a[dpl_Max[i]] < a[i]) dpl_Max[i] = dpl_Max[dpl_Max[i]]; while(dpl_Min[i] >= 1 && a[dpl_Min[i]] > a[i]) dpl_Min[i] = dpl_Min[dpl_Min[i]]; } dpr_Max[n] = n + 1 , dpr_Min[n] = n + 1; for(int i = n - 1 ; i >= 1 ; i--) { dpr_Max[i] = dpr_Min[i] = i + 1; while(dpr_Max[i] <= n && a[dpr_Max[i]] <= a[i]) dpr_Max[i] = dpr_Max[dpr_Max[i]]; while(dpr_Min[i] <= n && a[dpr_Min[i]] >= a[i]) dpr_Min[i] = dpr_Min[dpr_Min[i]]; } ll Sum_Max = 0 , Sum_Min = 0; for(int i = 1 ; i <= n ; i++) { Sum_Max += a[i] * (i - dpl_Max[i]) * (dpr_Max[i] - i); Sum_Min += a[i] * (i - dpl_Min[i]) * (dpr_Min[i] - i); } printf("%lld " , Sum_Max - Sum_Min); return 0; }