单调栈

单调栈


前置技能点:

闲话:

其实并不知道单调队列和单调栈的先后顺序,但既然我是先写单调队列的,那就把单调队列作为单调栈的前置技能点吧。

问题:

给定序列长度 n ,求每个点作为最大/最小值的最长区间。

思路:

对于每个点,可以直接向左向右枚举直到遇到比它小的数,复杂度为O(n2)

对于每个点,可以二分以它作为左端点的区间的长度,然后用线段树得到它是不是该长度的区间的最小值,同理向右处理。复杂度建树 O(nlogn) ,对每个点的询问 O((logn)2)

对于每个点,用倍增的方法得到它右边第一个比它小的元素,同理向右处理。敲起来比线段树快,还能加个小优化。复杂度同线段树。

概念引入:

对于单调队列中循环删除队尾的情况,有这么一种性质(假设该单调队列单调递增):

下面说的左边和右边指的是原序列中的位置,左边表示从该元素开始向 id 较小的元素看,右边这是向 id 较大的元素看。

  • 某个元素作为队尾被删除的条件:
    它右边的第一个比它小的数字即将进入队列时。

  • 循环队尾删除操作的终止条件:
    队列为空,或者队列中的队尾元素是即将压入元素左边的第一个比它小的元素。

所以可以取消掉单调队列的弹出队首操作,这样单调队列就是一个栈(其实觉得单调队列不算队列)了。

当有一个元素即将进栈时,需要先将栈内值大于它的函数全部弹栈,这个元素是被弹栈的元素右边第一个比它们小的元素,弹栈操作结束后,栈顶元素是该元素左边第一个比它小的元素。

若栈为空,则表示该元素是目前的最小值。

若整个序列进栈完毕,栈内剩余的每一个元素右边都没有比它小的元素。

复杂度:

预处理 O(n) ,询问 O(1) ,空间复杂度 O(n)

拓展

同单调队列

例题

  • poj 2796
    给定一个长度为 n(n<105) 的非负整数序列 a ,定义函数f(l,r)=(minri=la[i])(ri=la[i]),求 f(l,r) 的最大值及其对应的 l r
    解题报告
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值