[Dr.Lib]Note:Data Structures – 主席树 via 函数式线段树

偶然间翻PDF时看到了FHQ神犇的WC论文……看了一遍没记住什么……除了函数式编程其他也……就那样吧……顺手把CLJ的论文也看了一遍……//可持久化做法很多,函数式是种比较科学的实现……暴力复制、wzk树什么的就不说了……

然后函数式编程早就接触过但从来没有研究过TAT显然函数式线段树最成功的应用(之一?)就是主席树了……

函数式编程

修改元素是数据结构的一个基本操作,平常的实践中我们比较常见的就是直接改储存的值,而函数式编程中,我们从不去修改值,而是再定义一个。

对应在线段树操作中,我们每次修改值,都不会去修改任何节点,而是返回一棵新的树。

函数式Treap假想图 函数式线段树

图片来自范_wc2012

因为保证所有节点都不会被修改,所以我们可以重用未受影响的节点。显然,函数式线段树中,插入操作的时间、空间复杂度都是O(log n),其他操作与正常线段树无异。

主席树

主席树是一种利用函数式线段树维护数列的数据结构,一般用来解决区间第K大数问题。设数列长度为NN,数据范围为n,已离散化。

不支持修改的主席树(前缀和主席树)

……不支持修改的主席树在我的笔记中记为前缀和主席树…自己取的名字。。。

前缀和主席树由N棵线段树组成,第i棵Ti是对于[1,i]建一棵以序列里的值为下标,储存区间里出现该值的次数的线段树,也可以看作是Ti-1插入a[i]后的线段树。

注意到所有的树是同构(?)的,Ts-1和Tt可以直接相减得到T[s,t],在树上进行二分就可以得到区间K大值。

当然,所有的线段树都指函数式线段树。

代码:Via http://www.cnblogs.com/Rlemon/archive/2013/05/23/3094635.html 我自己码的实现惨不忍睹…这是和我的风格最接近的一个…以下是按我的笔记格式码的…

 

支持修改的主席树(树状主席树)

还记得当年学数据结构时如何维护带修改区间[s,t]的区间和吗?

树状数组,简单高效。既然我们维护的是一个线段树的前缀和,何不用树状数组维护呢?

脑补一棵树状数组,每个节点是一棵线段树 。修改时,我们仅需修改log n棵线段树即可。

//貌似只有我叫它树状主席树……正解是树状数组套主席树。

代码

 

临时建立节点的主席树

//待补完
参见clj的wc论文

[Dream YOLO]NOIP2013提高组酱油报告

370/600。
还不错的成绩。
但。。。怨念的是。。D1T2的10分。。
D1
T1
显然是快速幂。。
T2
显然当上下两序列同序(对应数字排名相同时和最小。
由于要求同序所以说序列一的顺序是无关紧要的,按序列一排序后我们只需再把序列二排序即可。由于交换一次至多消除一个逆序对,答案就是按序列一排序后的逆序对数。
至今不知哪写傻了,10分。
T3
当时写了一个裸并查集。。60。。
和YY聊了聊才发现应该先跑一个最大生成树的。。
D2
T1&T2都是喜闻乐见的题型。
n^2可以做,nlogn可以做,线性也可以做。。
我们那考场一位大神两题写了五个线段树(T1真的很像线段树操作喂。。
T1推了15分钟差分,5分钟码代码,10分钟对拍。
T2第一眼看过去是DP,看了下数据范围不大对了。
思考了五分钟,发现可以用数据结构优化。
先码了一个裸DP,试了一下貌似还可以,于是又推了一会题目,没看出什么东西来。
然后看了看第三题,我估计只会爆搜了,于是发呆5分钟开始重新码T2。
稳妥起见先码了一个离散化,把h搞到1~n(还有一个原因是h=0的话zkw线段树会囧。。。这是我后来才发现的。)
写了俩zkw分别记录当前处理到的这一棵是目标序列中奇数位和偶数位的情况。然后两种情况分别算一次。
然后写树的时候开闭区间没注意。。调了20分钟。。七弄八弄就交卷了囧。D2倒是A了两题……

发自 WordPress for Android