牛客 区区区间间间 (单调栈)

按照习惯一开始是要把题目复制一遍的,但是我想了一下,这个题目的符号复制过来会出现乱码,你说截图吧,又不想截图,那该怎么办,一时间不知道如何开始,所以就出现了上述的文字~~

绝对的好题目!!!

首先对于题目给出的公式,我们需要转化一下,我们把原式拆开就等到下面的公式在这里插入图片描述
转化之后我们就求所有区间长度大于1的子区间的最大值和最小值之和。

  • 首先我们用单调栈去维护以a[i]为区间的最大值,然后往左右两边去拓展,然后我们正反跑一次单调栈就能维护出l和r数组
  • 其中l[i]表示以a[i]为最大值,左边最多延伸到l[i],r[i]表示以a[i]为最大值,右边最多延伸到r[i],那么如何计算呢
  • ① a[i]作为一个区间的端点,那么可以选择的区间另一个端点就是r[i]-l[i]。
    ② a[i]作为区间中的一点,也就是区间的端点都没选。那么就是在l[i]到i之间选一个作为左端点,r[i]-i之间选一个作为右端点,乘法原理可得区间的个数为 (r[i]-i) * (i-l[i])
    这样就处理出来拆分出来的和式的第一部分了。

下面我来解答一下大部分同学都会遇到的问题

  1. 第一个就是很多人不明白代码里面为什么只在一边取等号,而另一边不取等号,因为如果存在最大值有多个那么如果两边同时取就是出现重复取的情况,所以我们只要把数字放在任意一边取得就行
  2. 第二个就是如何获得最小值,因为我们知道我们跑一次单调栈求得的就是每个子区间最大值之和,所以我们就对数组每个元素取反,然后再跑一遍单调栈,得出的数中,我们取一个最大值,那么加起来就是最大值了,如果取反之后并且跑完单调栈之后最大数是负数,负数是数字越小负数越大,并且负号已经包含在里面了,直接相加就是最大值了,如果最大值是正数那么直接相加就行

AC代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
ll a[maxn], l[maxn], r[
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值