主席树

可持久化线段树,就是每次新建一个版本的线段树,但是因为是单点修改所以每次只有\(\log n\)的变化量。
主席树,指的是可持久化权值线段树

我们先学习一下最基础的可持久化线段树,就是查询一个历史版本的值,单点修改并新建版本。
最核心的修改操作是这样的:

点击查看代码
void modify(int pre, int &id, int pos, int val)
{
	id = ++cnt, tr[id] = tr[pre];
	if(tr[id].l == tr[id].r){tr[id].val = val; return;}
	int mid = (tr[id].l + tr[id].r) >> 1;
	if(pos <= mid)modify(lpre, lid, pos, val);
	else modify(rpre, rid, pos, val);
}
手膜一下就知道它是先把节点的信息搞成前面的,再在往下修改的过程中更改这个信息。所以id传的是引用。

1.单点修改,历史版本区间最大值

板子,修改没区别,查询就按照普通线段树写法查。

2.区间第k小值查询

我们考虑对权值线段树从1到n进行可持久化。
然后需要一个作差的思想,就是我query的时候同时去搜L-1和R两棵线段树,然后把对应的左儿子的值相减就知道左边有几个值了,然后正常查即可。

注意每次开的实际上是log + 1个点,所以空间要开够。

3.二维数点(强制在线)

其实是比较容易的。考虑左下角是(x1,y1),右上角是(x2,y2)的一个矩形。
我们如果把x1到x2当作版本,就对这些版本做前缀和,然后查询的时候就是x2和x1-1的版本的y1到y2的区间和相减就行。
时间复杂度应该是单log的。

4.区间数颜色(强制在线)

这个不是很容易,考虑转化。
我们对每个点i找到前面最右边的与它颜色相同的点\(last_i\),然后就能转化成二维数点问题直接做了。

5.花神的嘲讽计划(主席树维护哈希)

这个题哈希是用来判子串的,主席树统计哈希值的个数,注意一下写的时候不要爆ull就好。

posted @ 2025-09-06 08:41  The_Wandering_Earth  阅读(11)  评论(0)    收藏  举报
/