• 【总结】主席树


    这是一篇有关主席树的总结

    主席树是什么?

    对于原序列的每一个前缀[1···i]建立出一棵线段树维护值域上每个数出现的次数,则其树是可减的

    PS:本篇随笔对于主席树的基本内容并没有深刻讲解,主要说明它的一些用法

    其实就是很多一堆大量的权值线段树

    (什么是权值线段树?就是每个节点维护不是位置,而是权值,比如 ([1,4]) 维护的就是权值等于1到权值等于4的信息)

    而且这些线段树还隐含了一个前缀和的功能

    最简单的就是一个数列,长度为 (n) ,那么就建 (n) 棵权值线段树,第 (i) 棵权值线段树对应第 (i) 个数,存的是从第一个数到第 (i) 个数的信息(建第 (i) 棵权值线段树的时候,只要先把第 (i-1) 棵权值线段树复制一份,再把 (i) 位置上的信息加入中间就可以了)

    那么我们如果要知道数列中 (l) 位置到 (r) 位置的数的信息,就只要把 (r) 上的权值线段树减去 (l-1) 的权值线段树,得到的线段树保存的就是 (l)(r) 的信息(其实就是一个差分)

    然后我们发现每次都新建整个权值线段树又耗时间又爆内存,并且相邻两棵线段树之间改变的只有一点点内容,其它的都没有变,那对于这些不变的节点就不新建了,直接共用,即多棵权值线段树在某个位置共用一个节点

    个人认为,主席树就是共用节点的权值线段树

    主席树可以用来干嘛?

    主席树的所有操作,基本上都可以说是对应一段区间,那么就都要先差分一下,以下所有功能都是差分之后的

    1. 查询区间Kth(第 (k) 大/小)

      主席树中记录的是 (num) ,即每个数字出现的次数,然后每次判断当前区间的左子树的 (num) 是否满足条件,再决定走左子树还是右子树(极其类似于Treap)

    2. 查询区间出现数字的和

      这只要把上面的 (num) 变成 (val) ,然后把差分后根节点的 (val) 输出就行了

    3. 查询区间中权值在 ([l,r]) 之间的所有数字的和

      (num) 变成了 (val) 后,不直接返回根节点的值,而是返回主席树上 ([l,r]) 区间的 (val) 值(因为主席树是权值线段树)

    暂知的作用就这几个

    几个小套路

    • 如果没有修改只有询问操作,那么可以直接静态主席树。但如果有修改操作,那么就要变成动态了。也就是说我们要有一个东西,可以维护能够修改的前缀和,那就BIT(树状数组)。所以动态主席树,一般就是树状数组套主席树的树套树

    • 如果不是一个数列,而是一棵树上要维护两个节点的信息,那么就把主席树的每个版本变成从父亲继承的就行了,最后的查询就树上差分

    这些套路要在题目之中去理解

    几道练习题

    大体上从简到难(看个人理解)

    七道题,后面的神题做得心累

    没有数论题好做啊

    从未结束

    从此,主席树的学习告一段落

    HNOI就要到了,可是HNOI最喜欢考的数据结构我还有很多没搞定

    下一步——LCT

  • 相关阅读:
    kafka基础
    springboot启动过程(3)-refresh方法
    springboot启动过程(2)-run方法
    springboot启动过程(1)-初始化
    springBoot数据库jpa+对接mybatis
    spirng boot web配置开发
    spring boot 入门
    jetty分析
    NIO/AIO
    使用jsPDF 和jspdf-autotable 导出中文表格页面
  • 原文地址:https://www.cnblogs.com/hongyj/p/8635456.html
Copyright © 2020-2023  润新知