在网上找了一些资料,发现讲述得都不大清晰,所以在这里总结一下。
问题描述
假设我们希望记录一个区间集合的最大重叠点,即被最多数目区间所覆盖的那个点。
a. 证明:最大重叠点一定是其中一个区间的端点
b. 设计一个数据结构,使得它能够有效地支持 INTERVAL-INSERT、INTERVAL-DELETE, 以及
返回最大重叠点的 FIND-POM 操作。
求解过程
a.证明
假设取得一最大重叠点,如果其不是某个区间端点,那么让这个点逐渐右移,直到遇到一个区间端点为止。此时,新得到的端点所在区间数目要么增加要么不变,所以最大重叠点一定是一个区间的端点。
b.设计
思路: 使用红黑树,节点的值是每个端点的值。使用分治算法,最大重叠点要么在左子树,要么在右子树,要么是自己。
数据结构扩增
每个节点的附加信息:
p
(
x
)
p(x)
p(x):左端点为+1,右端点为-1;
v
(
x
)
v(x)
v(x):以x为根的所有结点的p值之和。
INTERVAL-INSERT操作:
使用红黑树的插入方式,特殊操作为:将插入时经过的每个节点的v值加上插入节点的p值。
INTERVAL-DELETE操作:
使用红黑树的删除方式,特殊操作为:将删除时经过的每个节点的v值减去删除节点的p值。
FIND-POM算法:
记
s
(
i
,
j
)
=
p
(
v
i
)
+
p
(
v
i
+
1
)
+
.
.
.
+
p
(
v
j
)
s(i,j)=p(v_{i}) + p(v_{i+1})+...+p(v_{j})
s(i,j)=p(vi)+p(vi+1)+...+p(vj),即
v
i
v_{i}
vi到
v
j
v_{j}
vj的p值之和。那么
s
(
i
,
j
)
s(i,j)
s(i,j)就代表了重叠的区间数。
设一节点为x,记以x为根节点的子树的最小元素为
l
(
x
)
l(x)
l(x),最大元素为
r
(
x
)
r(x)
r(x)。
则记
m
(
x
)
=
m
a
x
{
s
(
l
(
x
)
,
i
)
}
,
f
o
r
i
i
n
{
l
(
x
)
,
.
.
.
,
r
(
x
)
}
m(x)=max\left \{ s(l(x), i) \right \},\ for \ i \ in \ \left \{ l(x),...,r(x) \right \}
m(x)=max{s(l(x),i)}, for i in {l(x),...,r(x)}。则
m
(
x
)
m(x)
m(x)就是以x为根节点的树的最大重叠点的重叠数。
因此,一颗红黑树的最大重叠点就很容易用分治算法求解出来了:重叠点分为三种情况(在左子树中、根节点、在右子树中),要分别算出左右子树的
m
(
x
)
m(x)
m(x),最后进行比较。而左右子树的
m
(
x
)
m(x)
m(x)又可递归调用该算法求出。每个
m
(
x
)
m(x)
m(x)还应该附带位置信息,以指示最大重叠点的位置。
下面是
v
(
x
)
v(x)
v(x)与
m
(
x
)
m(x)
m(x)的求法: