codeforce 871D Imbalanced Array

本文介绍了一种利用单调栈求解子区间最大值与最小值之差的和的高效算法。通过计算每个值作为最大值和最小值时能覆盖的区间范围,进而求得所有子区间的目标差值总和。

题目大意:

然后就i是输入一个整数n,然后输入n个整数,然后求这个区间的子区间的最大值最小值的差值的和;

基本思路:

转化为用单调栈求每一个值作为最大值和最小值能管到的区间范围,然后求每一个以该值为最大值的区间的个数然后乘以这个最大值加到res上,在求出以该值为最小值的区间个数乘以这个值,然后res减去这个值,最终就等效于求出了所有子区间最大值与最小值的差值的和;

代码如下:

#include<iostream>
#include<iomanip>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<list>
#include<stack>
#include<map>
#include<set>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>


using namespace std;


const int inf = 0x3f3f3f3f;
const int maxn = 1000000+10;
typedef long long ll;
int ans[maxn],lmax[maxn],rmax[maxn],lmin[maxn],rmin[maxn];




int main()
{
    stack<int>s1,s2,s3,s4;
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&ans[i]);
    for(int i=1;i<=n;i++)
    {
        while(!s1.empty()&&ans[s1.top()]>=ans[i]) s1.pop();
        if(s1.empty()) lmin[i]=1;
        else lmin[i]=s1.top()+1;
        s1.push(i);
    }
    for(int i=n;i>=1;i--)
    {
        while(!s2.empty()&&ans[s2.top()]>ans[i]) s2.pop();//注意这里是大于而不是大于等于,你想,如果是等于的话,就会求出许多重复的区间,因为有最大值可能相等的情况

//然后这样的话分别对这两个相同的值求左右能管到的范围是一样的,即求出了相同的区间,然后就有了重复;
        if(s2.empty()) rmin[i]=n;
        else rmin[i]=s2.top()-1;
        s2.push(i);
    }
    for(int i=1;i<=n;i++)
    {
        while(!s3.empty()&&ans[s3.top()]<=ans[i]) s3.pop();
        if(s3.empty()) lmax[i]=1;
        else lmax[i]=s3.top()+1;
        s3.push(i);
    }
    for(int i=n;i>=1;i--)
    {
        while(!s4.empty()&&ans[s4.top()]<ans[i]) s4.pop();
        if(s4.empty()) rmax[i]=n;
        else rmax[i]=s4.top()-1;
        s4.push(i);
    }
    ll res=0,t;
    for(int i=1;i<=n;i++)
    {
        t=(ll)(rmax[i]-i+1)*(i-lmax[i]+1)-(ll)(rmin[i]-i+1)*(i-lmin[i]+1);
        res+=(t*(ll)ans[i]);
    }
    printf("%I64d\n",res);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值