基于此paper,我发现使用两个BIT在O(lg N)
中执行RMQ非常棒,因为它比分段树更容易编码,并且该文件声称它表现更好也比其他数据结构。
我理解如何构建树以及如何进行查询操作,但我对更新操作感到困惑。这是引用:
我们进行以下观察:当我们生成相关的间隔时 我们经过的节点,我们可以从节点开始覆盖整个区间 [p + 1,y] p + 1和攀爬第一棵树(图2.1)。因此,我们不是对每个节点进行查询 更新,我们通过爬树一次计算查询结果。
类似地,我们可以通过以下方式更新 [x,p - 1] 形式的所有间隔 节点p - 1和攀爬第二棵树(图2.2)。应用相同的算法 更新两棵树。
我怀疑它应该是相反的:为了找到最小间隔 [p + 1,y] ,我们应该使用第二棵树而不是第一棵树一;为了找到最小间隔 [x,p-1] ,我们应该使用第一棵树。
我的问题是:我说错了吗?如果不是,有人可以给出一个简单的例子来演示更新操作的工作原理吗?
答案 0 :(得分:1)
解释有点含糊不清。我猜他们的意思是[p+1,y]
你从p+1
开始攀登前三个,但是使用第二个树进行查询。
让我们假设您更新第10个索引的值(来自论文)。您必须回答[x, 10 - 1]
&的查询更新树时[10 + 1, y]
。为了有效地做到这一点,你需要建立两个“攀爬”列表:
CLB1
攀爬p+1
:{11, 12}
中的第一棵树,该树对应于下一个时间间隔:[11..11]
,第二棵树的[12..15]
CLB2
攀爬p-1
:{9, 8}
中的第二个树,该树对应于下一个时间间隔:[9..9]
,[1..8]
第一棵树
现在,您可以通过爬上从10开始的第一棵树来开始更新第一棵树。
10 - 微不足道的更新
12 - 您需要查询[9..9]
,{10}
,[11..11]
,{12}
。您可以通过[9..9]
的第一个成员从BIT1
获得CLB2
的答案。您可以通过[11..11]
的第一个成员从BIT2
获得CLB1
的答案。 {10}
和{12}
是微不足道的。
16 - 您需要查询[1..9]
。 {10}
,[11..15]
(没有{16}
,因为它是虚构的)。通过前两项[1..9]
,您从BIT1
开始CLB2
。通过前两项[11..15]
,您从BIT2
开始CLB1
。 {10}
是微不足道的。
正如您在左侧查询中看到的那样,您可以使用第二棵树的p-1
中的攀爬历史从第一棵树中获取答案。对于正确的查询,您可以使用第一棵树的p+1
的攀爬历史从第二棵树中获取答案。
类似的过程用于更新正确的树。
更新:第9个节点的流程
如果要更新第9个索引,我们有下一个CLB
s:
CLB1
:{10, 12}
,[10..11]
的间隔:[12..15]
,BIT2
。
CLB2
:{8}
,间隔时间[1..8]
BIT1
更新BIT1
:
9 - 琐碎
10 - 琐碎(我们只需要{9}
和{10}
)
12 - 我们需要先从CLB1
- [10..11]
进入,{12}
进入{9}
16 - 我们需要来自CLB1
- [10..11] U [12..15]
的两个第一个条目,CLB2
的第一个条目 - [1..8]
和{9}
更新BIT2
:
9 - 琐碎
8 - 我们需要前两个来自CLB1
- [10..11] U [12..15]
和{9}
{8}
0 - 我们需要前两个来自CLB1
- [10..11] U [12..15]
的条目和来自CLB2
的第一个条目 - [1..8]
和{9}