维护一个有两个键值的序列, 对于每个 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
这竟然不是线段树,,,哭了。