CF1290E Cartesian Tree

考虑笛卡尔树的意义:

一个点在笛卡尔树中的子树,代表以他为最小/最大值的区间。
所以一个点的子树大小,一定是类似到达序列边界或者被一个比他更大的数隔离。

考虑记录 \(l_i,r_i\) 为第 \(i\) 个数往前的第一个比他大数位置,以及往后第一个比他大的数位置。

则该的子树大小为为 \(r_i - l_i + 1\)

所以所有的点答案为 \(\sum r_i - l_i + 1\)

考虑这个数据范围,我们应该要实现一个可以支持插值,并且一次操作为 \(log\) 就能维护 \(l,r\)的数据结构。

我们思考到,这题的一个关键性质:每次都加入一个最大的数。

那么我们可以考虑这个数位于 \(x\),那么他对左右两边都有贡献。

具体来说即对右边的位置 \(l_i\)\(min\),左边的位置 \(r_i\)\(max\)

那么可以联想到吉司机线段树。

我们拆成两颗线段树来做,一颗维护 \(l\),一颗维护\(r\)即可。

同时注意到,每次插入,都会让右侧的 \((l,r) \to (l+1,r + 1)\)

我们需要做的操作有:区间取 \(min/max\),区间加,查全局和单点加。

复杂度\(O(nlog^2n)\)

原文地址:https://www.cnblogs.com/dixiao/p/15103884.html