不进行修改操作的主席树

不进行修改操作的主席树说是多个树,不如说是多个相互交叉的树,

建立n个树每个树都含有kk代表n中有k个不同数)个叶节点,第i个树代表以1n所有元素 按从小到大排列建立的线段树,节点的权值是指这个节点下有多少个点(对应于这i个叶节点的值,如果第i个数(从小到大排列的第i个数)出现则值为1,不出现值为0,节点维护的是左右儿子节点的和),查询1i这些数中的第k个数时,只需要从第一个节点往下查找,如果左节点的值是大于等于k的,那么查询左儿子,否则查询右儿子,递归直到查到某个节点。

上面是原理,但如果直接开n个树的内存是(4*n^2肯定会爆掉,下面是如何把它们变成相互交叉的树。

对于一个目标数组a[n],现将a[n],按从小到大的顺序排列,目的的为了在建树过程中知道某个点应该放在线段树的哪个位置。

 

比如 22)  44)  3311{前面是数值,括号里是应该放的位置},这样线段树的结构是提前确定的,易于插入,用root[i]表示1i个数形成的线段树的跟节点;ii+1这两个数相比较,他们的树只有一个叶子节点和这个叶节点到跟节点上的节点是不同的,对于数组第i+1个值,它肯定要插入到第i个树;相比较第i个树,第i+1个数在排列时对应的位置从0变成1,然后这个叶子节点到跟节点都需要更新,但其他的节点都一样,

下面用图表示:

struct Node

{

Int L,int R,sum;

}node[N logN+4),root[N]];

  root[i]               

L1           R1       

L2 R2  L3      R3   

root[i+i]

 l1             r1

 l2 r2    l3       r3   

假设n4,插入的位置在l3,那么l1L1是完全相同的,直接让root[i+1]节点的L值等于root[i]L值,然后新建一个节点保存r1节点的信息。因为r3R3完全相同,那么直接让r1R等于R1R;然后新建一个节点保存l3

.......root[i]                 

L1 ........... R1       

L2...R2..L3....R3    

 ......root[i+i]

 L1............. l1

............... l3....R3

空间结构如上图所示。

所以时间复杂度为nlogn),空间复杂度为nlogn;

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值