花了一整天做这题,总结一下.
http://poj.org/problem?id=2104
求 : 区间 [ b,e ] 的第K大数
思路 :
建立划分树和划分表
对划分表折半查找, 同时不断缩小要求查找的区间 [ b, e ], 直至b=e时结束.
概念 :
划分树 : 对一个无序序列,通过建立划分树对其排序。用二维数组segTree[18][100001]表示划分树对象,数组第一维表示树高,第二维表示每层的节点。
划分表 : 用来记录划分树中某节点被划分到左子树还是右子树。节点i记录i之前节点中{包 括i}被划分到左子树的数目。用toLeft[18][100001]表示划分表,两维分别与划分树的每层,每个节点相对应。
建树 :
对于树中每一个节点,如果它小于等于该树的中位数,该节点进左子树;否则,该节点进右子树。与此同时,在划分表中记录该节点被划分进了哪个子树。
语言描述:
procedure Build
获得中位数;
For 对树中每一个节点
If 该节点值小于等于中位数
划分进左子树;
划分表记录该节点被划分到了左子树
Else
划分进右子树;
划分表记录该节点被划分到了右子树
Build 左子树;
Build 右子树;
查找第K大数:
与折半查找很类似,直接给出描述。
Procedure Search
假设某次划分到左子树n个节点
用k与n比较
If k <= n
那么第k大数一定在该树的左子树中,问题转化成进入左子树,求左子树的第k大数
Else k > n
问题转化成进入右子树,求右子树的第k-n大数
以下是这题AC代码