主席树
可持久化线段树,就是每次新建一个版本的线段树,但是因为是单点修改所以每次只有\(\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);
}
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就好。

浙公网安备 33010602011771号