单调栈

维护一个有两个键值的序列, 对于每个 i, 询问一个 最小的 j , 使得h[j] >= h[i] 且 j < i。

直观的想法: 用set水。 或者rmp套一个二分。  但都慢而不优美。

更好的做法?  单调栈

单调性在哪里?

—— t > 0 则, h[i + t] < h[i]  当且仅当 j[ i + t ] >= i; h[i + t] >= h[i] 当且仅当 h[ j [ i + t ] ]  >= h[i] (像是一句废话,,)

有什么用?

考虑 有一个 沿 序号 单调递增 且 沿 h 单调递减的序列, 从序号最小到最大扫一遍, 每扫到一个点 i, 它的 j 即为从序列尾端 开始扫遇到的第一个 h >= h[i] 的数, 嗯然后把 i 加入这个 序列 (加到i 的后面), 这时候序列中在 j 之后的数 显然不会再被用到了, 都弹出即可。

哦——这就是一个栈么。时间复杂度是 O(n) 的


写起来也很容易,,


练习题

【bzoj1657】[Usaco2006 Mar]Mooo 奶牛的歌声

【bzoj1660】[Usaco2006 Nov]Bad Hair Day 乱发节

这两题 一样, 都可以用set 或者 rmq + 二分来水。


【bzoj1683】[Usaco2005 Nov]City skyline 城市地平线

【bzoj1628】[Usaco2007 Demo]City skyline

【bzoj1113】[Poi2008]海报PLA

一道题出三次也真是蛮拼的呢, 的确很巧妙, 我的题解


【bzoj1012】[JSOI2008]最大数maxnumber

这竟然不是线段树,,,哭了。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值