[学习笔记]主席树

权值线段树

线段树上每个区间记录的是区间内所有数出现次数的总和.

然后就可以求出整棵线段树的第k大的数了(类似于二叉查找树?)

主席树

建立$n$棵上述的权值线段树,第$i$棵表示$a_1-a_i$的所有数组成的权值线段树。

用可持久化线段树的思想会发现,第$i$棵线段树与第$(i-1)$棵线段树之间只有$logn$个区间值是不同的,所以每次只要新建$logn$个区间,总复杂度是$O(nlogn)$.

区间查询类似于前缀和.

例题

bzoj4408

时间: 2024-08-25 23:47:01

[学习笔记]主席树的相关文章

数据结构学习笔记(树、二叉树)

树(一对多的数据结构) 树(Tree)是n(n>=0)个结点的有限集.n=0时称为空树.在任意一颗非空树种: (1)有且仅有一个特定的称为根(Root)的结点: (2)当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1.T2........Tn,其中每一个集合本身又是一棵树,并且称为根的子树. 对于树的定义还需要强调两点:1.n>0时根结点是唯一的,不可能存在多个根结点,数据结构中的树只能有一个根结点.2.m>0时,子树的个数没有限制,但它们一定是互不相交的. 结点

学习笔记:树分治

树分治用于解决有关路径的问题.树分治分为点分治和边分治(其实还有一种叫“链分治”,是树的路径剖分思想的更高级的体现,一般链分治的题目都可以用路径剖分解决).点分治就是每次找到重心,然后把重心去掉,对分成的每两棵树之间分别统计路径信息(以重心的每个相邻点为根,遍历整棵子树即可得到这个根到每个结点的统计信息),就可以知道包含这个重心的所有路径的信息,然后对于剩下的路径就是在子树里面进行同样的操作了,直到只剩一个点为止(注意这一个点所构成的路径有时也要处理一下).边分治就是每次找到一条边,使得删掉这条

二叉树学习笔记之树的旋转

树旋转(Tree rotation)是二叉树中的一种子树调整操作,每一次旋转并不影响对该二叉树进行中序遍历的结果.树旋转通常应用于需要调整树的局部平衡性的场合. >>左旋和右旋 树的旋转有两种基本的操作,即左旋(逆时针方向旋转)和右旋(顺时针方向旋转). 树旋转包括两个不同的方式,分别是左旋转(以P为转轴)和右旋转(以Q为转轴).两种旋转呈镜像,而且互为逆操作. 下图示意了两种树旋转过程中, 子树的初态和终态 +---+ +---+ | Q | | P | +---+ +---+ / \ ri

数据结构学习笔记04树(二叉树、二叉搜索树、平衡二叉树)

一.树 树的基本术语 ①结点的度(Degree):结点的子树个数 ②树的度:树的所有结点中最大的度数 ③叶结点(Leaf):度为0的结点 ④父结点(Parent):有子树的结点是其子树的根结点的父结点 ⑤子结点(Child):若A结点是B结点的父结点,则称B结点是A结点的子结点:子结点也称孩子结点. ⑥兄弟结点(Sibling):具有同一父结点的各结点彼此是兄弟结点. ⑦路径和路径长度:从结点n1到nk的路径为一个结点序列n1 , n2 ,… , nk , ni是 ni+1的父结点.路径所包含边

数据结构学习笔记04树(堆 哈夫曼树 并查集)

一.堆(heap) 优先队列(Priority Queue):特殊的“队列”,取出元素的顺序是依照元素的优先权(关键字)大小,而不是元素进入队列的先后顺序. 数组 : 插入 — 元素总是插入尾部 ~ O ( 1 ) 删除 — 查找最大(或最小)关键字 ~ O ( n ) 从数组中删去需要移动元素 ~ O( n ) 链表: 插入 — 元素总是插入链表的头部 ~ O ( 1 ) 删除 — 查找最大(或最小)关键字 ~ O ( n ) 删去结点 ~ O( 1 ) 有序数组: 插入 — 找到合适的位置

学习笔记::矩阵树定理

我很懒惰,没有理解 是这样做的 先计算每个点的度数 a[i][j]=i到j边数*-1 进行高斯消元 最后把对角线乘起来就是答案 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; #define eps 1e-9 #define N 20 int n,m; int d[N][N],c[N][N]; double a[N][N];

[知识学习] 主席树

这两天学习了主席树,基本上搞懂了主席树是怎么操作的 主席树,是一种可持久化线段树.最简单的操作就是维护静态区间第 \(k\) 小 主席树通过维护历史版本,实现查询区间的有关操作 主席树的原理 假设现在有这么一个序列:\(4,1,3,5,2\) 问如何求出区间[1,3]内大小为第二的数? 利用大眼观察法,很显然是3 那么让计算机去怎么实现呢?它又没有眼睛 对于这个序列,我们可以先建一颗空的权值线段树,命名为"树0"(方便后面的使用),如图: 别告诉我你不知道什么是权值线段树,自己去百度:

BZOJ_3207_花神的嘲讽计划1_(Hash+主席树)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=3207 给出一个长度为\(n\)的串,以及\(m\)个长度为\(k\)的串,求每个长度为\(k\)的串在原串\([x,y]\)区间是否出现过. 分析 这道题要求对比长度为\(k\)的串,于是我们把这些串的Hash值都算出来,问题就转化成了求\([x,y]\)的区间中是否出现过某Hash值. 求区间中某一个值出现了多少次,可以用主席树. p.s. 1.学习了主席树指针的写法,比数组慢好多啊...

[主席树]HDOJ2665 &amp;&amp; POJ2104 &amp;&amp; POJ2761

主席树真是神奇的物种! 题意:给n.m   下面有n个数 (编号1到n) 有m个询问,询问的是上面的数的编号在[l,r]之间第k小的数 n.m的范围都是1e5 是主席树的入门题 借此来学习一下主席树 1 const int N=1e5+5; 2 int L[N<<5], R[N<<5], sum[N<<5]; 3 int tot; 4 int a[N], T[N], Hash[N]; 5 int build(int l, int r) 6 { 7 int rt=(++t