【算法】主席树

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

主席树是什么?

对于原序列的每一个前缀[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

原文地址:https://www.cnblogs.com/hongyj/p/8635456.html

时间: 2024-10-08 23:36:01

【算法】主席树的相关文章

BZOJ 1878 [SDOI2009]HH的项链 (主席树 或 莫队算法)

题目链接  HH的项链 这道题可以直接上主席树的模板 #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) typedef long long LL; const int N = 5e4 + 10; const int M = 3e6 + 10

算法总结——主席树(poj2104)

题目: Description You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the a

POJ2104主席树模板题

完成新成就——B站上看了算法https://www.bilibili.com/video/av4619406/?from=search&seid=17909472848554781180#page=2 K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 60158   Accepted: 21054 Case Time Limit: 2000MS Description You are working

poj_2104: K-th Number 【主席树】

题目链接 学习了一下主席树,感觉具体算法思路不大好讲.. 大概是先建个空线段树,然后类似于递推,每一个都在前一个"历史版本"的基础上建立一个新的"历史版本",每个历史版本只需占用树高个空间(好神奇!) 查询时这道题是通过"历史版本"间作差解决 *另外提一下,在建立"历史版本"的过程中,是"新建",而不是"更新",是先copy过来原有的,再按个人需求改成自己的,所产生的一个新的"

【BZOJ-1926】粟粟的书架 二分 + 前缀和 + 主席树

1926: [Sdoi2010]粟粟的书架 Time Limit: 30 Sec  Memory Limit: 552 MBSubmit: 616  Solved: 238[Submit][Status][Discuss] Description 幸福幼儿园 B29 班的粟粟是一个聪明机灵.乖巧可爱的小朋友,她的爱好是画画和读书,尤其喜欢 Thomas H. Cormen 的文章.粟粟家中有一个 R行C 列的巨型书架,书架的每一个位置都摆有一本书,上数第i 行.左数第j 列摆放的书有Pi,j页厚

SPOJ - DQUERY 主席树

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=32356 Given a sequence of n numbers a1, a2, ..., an and a number of d-queries. A d-query is a pair (i, j) (1 ≤ i ≤ j ≤ n). For each d-query (i, j), you have to return the number of dist

归并树 划分树 可持久化线段树(主席树) 入门题 hdu 2665

如果题目给出1e5的数据范围,,以前只会用n*log(n)的方法去想 今天学了一下两三种n*n*log(n)的数据结构 他们就是大名鼎鼎的 归并树 划分树 主席树,,,, 首先来说两个问题,,区间第k大 ,,,, 这个问题的通用算法是 划分树,, 说白一点就是把快速排序的中间结果存起来, 举个栗子 原数列 4 1 8 2 6 9 5 3 7 sorted 1 2 3 4 5 6 7 8 9 ........................... qs[0] 4 1 8 2 6 9 5 3 7 q

可持久化数据结构之主席树

转自:http://finaltheory.info/?p=249 HomeACM可持久化数据结构之主席树 06十2013 可持久化数据结构之主席树 Written by FinalTheory on. Posted in ACM 引言 首先引入CLJ论文中的定义: 所谓的“持久化数据结构”,就是保存这个数据结构的所有历史版本,同时利用它们之间的共用数据减少时间和空间的消耗. 本文主要讨论两种可持久化线段树的算法思想.具体实现以及编码技巧. 核心思想 可持久化线段树是利用函数式编程的思想,对记录

主席树初探 &amp; bzoj 3295: [Cqoi2011] 动态逆序对 题解

[原题] 3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 778  Solved: 263 [Submit][Status] Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数. Input 输入第一行包含两个整数n和m,即初始元素的个数和删除的元