主席数学习笔记
笛卡尔树太难了啊。
主席树
可持久化数据结构 总是可以保留每一个历史版本,并且支持操作的不可变特性 。
意思就是可以查询历史值,对于每一个历史版本 ,都是经过第 个版本、修改重连 个节点实现的。
如图,修改了 中对应权值为 1 的结点,红色的点即为更改的点
只更改了 个结点,形成一条链,也就是说每次更改的结点数 = 树的高度。
注意主席树不能使用堆式存储法,就是说不能用 来表示左右儿子,而是应该动态开点,并保存每个节点的左右儿子编号。
所以我们只要在记录左右儿子的基础上,保存插入每个数的时候的根节点就可以实现持久化了。
例题
例题 1:P3919 【模板】可持久化线段树 1
模板,单点修改单点查询的主席树。
#include<bits/stdc++.h> using namespace std; const int N=1e6+4; int a[N]; int root[N]; int cnt; struct PST{ struct node{ int ls,rs,val; }tr[N<<5]; #define lid tr[now].ls #define rid tr[now].rs void build(int &now,int l,int r) { now=cnt++; if(l==r) { tr[now].val=a[l];return ; } int mid=(l+r)>>1; build(lid,l,mid),build(rid,mid+1,r); } void update(int pre,int &now,int l,int r,int &x,int &y,int &val) { now=cnt++; tr[now]=tr[pre]; if(x<=l&&r<=y) { tr[now].val=val;return ; } int mid=(l+r)>>1; if(x<=mid) update(tr[pre].ls,lid,l,mid,x,y,val); if(y>mid) update(tr[pre].rs,rid,mid+1,r,x,y,val); } int query(int now,int l,int r,int x,int y) { if(x<=l&&r<=y) return tr[now].val; int mid=(l+r)>>1; if(x<=mid) return query(lid,l,mid,x,y); if(y>mid)return query(rid,mid+1,r,x,y); } }st;int n,m; signed main() { ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; st.build(root[0],1,n); for(int i=1;i<=m;i++) { int v,op,x,y;cin>>v>>op; if(op==1) { cin>>x>>y; st.update(root[v],root[i],1,n,x,x,y); } else { cin>>x; int ans=st.query(root[v],1,n,x,x); root[i]=root[v]; cout<<ans<<"\n"; } } }
例题 2:P1652 可持久化线段树
把上面的码变一下,修改的时候再新建版本,其余不要动,加上区间查询即可。
例题 3:#P467. [BZOJ3207]花神的嘲讽计划
题意是给定一个主串,有多次操作,每次给定一个值,问区间 是否存在这个值。
直接分块得了呗。
-
对于在同一块内的,直接查。
-
对于在不同块内的,先找前后小端点,再二分找中间大块。
有一个很神奇的操作,因为 是找严格大于, 是找大于等于,所以如果区间内有这个值,upper_bound()-lower_bound()>0
否则等于 。
搞定。
不知道为啥块长要设成 ,然后就是最优解。
例题 4:#P1650. [NEERC 2004] K小数
就是区间找第 小的数,先要离散化一下,然后主席树每个节点存有多少个数字,按照权值线段树找第 大的数的代码即可。
例题 5:P3834 【模板】可持久化线段树 2
和上题一模一样。
例题 6:P1533 可怜的狗狗
和上题一模一样。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!