zoukankan      html  css  js  c++  java
  • 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)\)

  • 相关阅读:
    二分图的判定 (图)
    并查集(模板)
    数独 (dfs)
    Map <STL>
    Set <STL>
    二叉搜索树的实现
    Find a way (BFS)
    根据输入的变量,执行相应的计算公式并返回结果
    检测字符串当中x与o的数目是否相等
    根据给定的数字和字符串,生成循环指定次数的字符串
  • 原文地址:https://www.cnblogs.com/dixiao/p/15103884.html
Copyright © 2011-2022 走看看