区间K大——树套树

@

定义

  • 这里的树套树是用线段树套平衡树
  • 线段树用来维护区间位置信息,把这个区间中的所有数插进一颗平衡树中
  • 利用线段树信息可加的性质来维护区间k大

实现方法

问题

区间k大问题需要进行几个操作:

  1. 查询k在区间内的排名

  2. 查询区间内排名为k的值

  3. 修改某一位值上的数值

  4. 查询k在区间内的前驱 (前驱定义为严格小于x,且最大的数)

  5. 查询k在区间内的后继 (后继定义为严格大于x,且最小的数)

实现

  1. 查询区间内一个数的排名:在线段树上找到区间对应的节点,然后每个节点的平衡树内查询对应数的排名并求和。时间复杂度 \(O(\log^2N)\)
  2. 查询区间内排名为k的数是几:由于这项操作在线段树上不可加。所以我们考虑转换为判定一个数是不是区间内排名为k的。这个可以在 \(O(\log^2N)\)的时间内通过操作1完成。那么我们考虑二分答案,就可以解决这个问题。时间复杂度 \(O(\log^3N)\)
  3. 单点修改:我们在线段树上找到所有覆盖这个点的区间,然后在所有区间对应的平衡树中删除原数,加入新数即可。时间复杂度 \(O(log^2N)\)
  4. 对于4和5、 查询区间内一个数前驱、后继:这是平衡树上的经典问题。我们只需要对于所有区间分别查询,然后答案相应的取\(\max\min\)即可。时间复杂度 \(O(\log^2N)\)
    当然,由于序列中的一个数最多被插入 \(O(\log N)\)个平衡树内,考虑到每次修改操作最多增加并删除一个节点,所以空间复杂度为 \(O(N\log N)\) 。经过我们的分析,时间复杂度为 O\((N\log^3N)\)。当然这是一个较松的上界。

代码

include<iostream>

(肥肠抱歉,咕咕咕

posted @ 2019-07-27 23:07  lcyfrog  阅读(144)  评论(0编辑  收藏  举报