codeforces 817 D. Imbalanced Array(单调栈+思维)

题目链接: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;
}
原文地址:https://www.cnblogs.com/TnT2333333/p/7071630.html