主席树学习笔记
简介
时间复杂度\(\ logN\) ,空间复杂度\(\ nlogn\),的一种持久化数据结构
访问历史版本的线段树,限定于修改操作为\(\ log\) 级别
常用操作
通常为权值线段树
1、处理区间问题,利用前缀和思想,将数组依次插入建历史版本。
2、处理大小问题,将数组按大小插入原始下标建 n 个版本。
3、树上问题,dfn 序拍平,并且将当前版本基于父亲版本上
...
常有 $build,insert,query\ $函数
例题
1、板子
为上述第一种类型,权值线段树差分出出现次数
2、P3567
与板子一样的线段树设置,解决要点在于 如果存在一个“众数”的话,左右区间肯定有一个的数字数量大于区间长度的二分之一 ,那就往那边递归,如果两边都没有,就说明没有
3、P2633
主席树结合树剖结构
首先排除强制在线的干扰,实际求 u 到 v 的第 k 小数。
显然在序列上是板子,那就需要树转序列,直接由上述 3
同时我们发现还需要 lca ,所以接着写一个树剖的东西求。
然后我们确定一段区间的值\(\ =val[u]+val[v]-val[lca]-val[father_{lca}]\)
套板子即可
4、P4587
一dao需要一些思考的题
首先并不能直接看出是主席树,先想 \(n^2\) 做法
基于动态规划思想,在一个区间里,我们把区间内的数字从小到大看,已经考虑了前 \(i-1\) 个数,能表示出 \([1,x]\) ,即神秘数为 \(x+1\) ,如果 \(a_i\le x+1\) 那我们可以现在表示 \([1,x+a_i]\) ;否则 就再也不能表示更多,答案为 \(x+1\) ,退出
有了代码:
while(m--){
int l,r;
cin>>l>>r;
sort(a+l,a+r+1);
int x=1;
for(int i=l;i<=r;i++){
if(a[i]<=x)x+=a[i];
a[i]=b[i];
}
cout<<x<<"\n";
}
发现本质上是区间前缀和,就有了一些主席树的影子(区间和)。
这个时候主播就不会了,怎么判断前缀和是否小于 a[i] 呢,想了二分发现并没有单调性?
使用 观看题解法 恍然大悟,逆向思维,现在假设答案就是 \(ans\),设 a 数组中小于 ans 的数的和为 \(res\) ,若\(res\ge ans\) 则说明 ans 还可以更新到 \(res+1\) ,就可以用主席树维护和了。
Code:
for(int i=1;i<=n;i++){
cin>>a[i];
root[i]=insert(root[i-1],1,inf,a[i]);
}
cin>>m;
while(m--){
int l,r;
cin>>l>>r;
int ans=1;
while(1){
int sum=que(root[l-1],root[r],1,inf,1,ans);
if(sum>=ans)ans=sum+1;
else break;
}
cout<<ans<<"\n";
}
5、Middle
这题主播怎么都调不出来(现在还没调出来)
首先有二分变为判定 x 是否可以为中位数,然后套路把 小于 x 的 设为 -1 ,大于 x 的设为 1 ,求 最大的和是否大于等于 0
怎么用上主席树的?
发现题目还是区间问题,且假如我现在假设 \(a_i\)为中位数,设置了一堆 -1 和 1 ,再假设 \(a_{i+1}\) 的时候实际上只有一个 1 变成了 -1 ,直接满足了主席树的两个使用特点
所以有了建每个版本的思路: 这道题属于常用操作2 : 按大小排序建立版本 ;插入位置为上一个数的原下标 ; 把值改成 -1。(初始一个 build 函数所有置为 1)
维护什么?
要求最大的和,我们考虑维护最大前缀和,最大后缀和,和
对于 \([a,b],[c,d]\) ,答案是 \([c,d-1]\) 的最大后缀和 + \([b,c]\) 的和 + \([c+1,d]\) 的最大前缀和
tips:query 函数返回值设为结构体,写 merge函数,就只用写一个 query;
但是,主播为啥调不出来。。。。。。
6、美味
异或,考虑按位考虑,常见贪心从高到低先满足能满足的。
假设现在考虑到第 \(i\) 位,更高位能满足的和为 \(ans\)
分类讨论:
如果 \(b\) 在这一为为 \(1\) : 那么我们希望有某个 \(a_i\) 在这一位为 \(0\) ,同时他还得满足更高位的 ans ,得出这一位有贡献当且仅当区间 \([ans-x,ans-x+2^i-1]\) 没有数
同理如果 \(b\) 在这一位为 \(0\) :有贡献当且仅当区间 \([ans-x+2^i,ans-x+2^{i+1}-1]\) 有数
发现是一段区间的某段值的数字个数,完全符合主席树,套模板

浙公网安备 33010602011771号