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;
}
posted @ 2020-06-01 17:53  GsjzTle  阅读(291)  评论(0编辑  收藏  举报