神仙题。
首先只有楼房顶有用,然后要斜率递增。
没事干了,上线段树。
肯定要记录区间单调队列的长度 \(len\)。当然把整个能看到的位置都记下来会更方便,然而复杂度就爆了。
顺便再来个区间最大值 \(mx\)。
修改是单点,叶子很好搞。询问就是根节点的 \(len\)。
难点就在 pushup。
\(mx\) 不管,只看 \(len\)。
首先发现,最左边的和最大值都能看到。
pushup 时,首先左边的所有数都仍然能被看到,右边能看到的数的个数和左边的最大值有关,右边留下的只有大于左边最大值的数。
所以我们递归 pushup:
参数有:线段树节点编号 \(o\) 和能看到的数的下界 \(lwr\)(也就是只保留 \(>lwr\) 的数,然后再求看不看得到)
如果 \(mx_o\le lwr\),整个区间都不能看到。
如果 \(a_l>lwr\),那么答案就是 \(len_o\)(能看到的数和没有这个下界没区别)。
如果 \(mx_{lson}\le lwr\),那么左儿子全都没有,递归到右儿子 \(pushup(rson,lwr)\)。
否则左儿子的最大值肯定保留了下来,那么右儿子能看到的数与没有下界没有区别,个数是 \(len_o-len_{lson}\)。递归到左儿子 \(pushup(lson,lwr)+len_o-len_{lson}\)。
这样 pushup 一次是 \(O(\log n)\)。
时间复杂度 \(O(m\log^2n)\)。