是否存在表示(64位)整数的大集合S
的数据结构,它从空开始并支持以下两个操作:
insert(s)
将号码s
插入S
; minmod(m)
会返回s
中的S
号,以使s mod m
最小化。一个例子:
insert(11) insert(15) minmod(7) -> the answer is 15 (which mod 7 = 1) insert(14) minmod(7) -> the answer is 14 (which mod 7 = 0) minmod(10) -> the answer is 11 (which mod 10 = 1)
我有兴趣尽量减少n
这类操作所花费的最长总时间。显然可以只为S
维护一个元素列表,并为每个minmod
操作迭代它们;插入为O(1)
,minmod为O(|S|)
,O(n^2)
次操作需n
次(例如,n/2
insert
操作后跟{ {1}} n/2
操作大约需要minmod
次操作。
那么:对于一系列n^2/4
操作,是否可能比O(n^2)
做得更好?可能n
或O(n sqrt(n))
?如果这是可能的,那么我也有兴趣知道是否有数据结构另外允许从O(n log(n))
中删除单个元素,或删除间隔内的所有数字。
答案 0 :(得分:7)
另一种基于平衡二叉搜索树的想法,如Keith的答案。
假设到目前为止所有插入的元素都存储在平衡的BST中,我们需要计算minmod(m)
。考虑我们的集合S
作为数字子集的并集,以[ 0,m-1],[m,2m-1],[2m,3m-1] 为间隔。答案显然是我们在每个时间间隔内的最小数字。因此,我们可以查找树以找到该间隔的最小数量。这很容易做到,例如,如果我们需要在 [a,b] 中找到最小数字,如果当前值大于 a ,我们将向左移动,并且否则,跟踪到目前为止我们遇到的 [a,b] 的最小值。
现在,如果我们假设在 [1,2 ^ 64] 中 m 均匀分布 ,那就让我们吧计算我们需要的查询数量的数学期望。
对于 [2 ^ 63,2 ^ 64-1] 中的所有 m ,我们需要 2 查询。这种可能性 1/2
对于 [2 ^ 62,2 ^ 63-1] 中的所有 m ,我们需要 4 查询。这种可能性 1/4
...
对于 [1,64] 中的 k ,数学期望将是 sum [1 /(2 ^ k)* 2 ^ k] ,这是 64 查询。
因此,总而言之, 平均 minmod(m)
查询复杂性将为 O(64 * logn)。通常,如果我们 m 的上限未知,则 O(logm logn) 。众所周知,BST更新 O(logn),因此 n 查询时的整体复杂性将为 O(n 的 10gm的* logn)时间强>
答案 1 :(得分:2)
部分答案对于评论来说太大了。
假设您将S
实现为平衡二叉搜索树。
当你寻找S.minmod(m)
时,天真地走在树上,费用是O(n ^ 2)。
然而,在步行期间的给定时间,到目前为止你有最好的(最低的)结果。您可以使用它来避免在以下情况下检查整个子树:
bestSoFar < leftChild mod m
和
rightChild - leftChild < m - leftChild mod m
如果公式间距b / w集合中的数字小于m
的公共值,这只会有很大帮助。
第二天早上更新......
格里戈尔更好,更全面地阐述了我的想法,并展示了它如何适用于“大型”m
。他还展示了“随机”m
通常是如何“大”的,所以效果很好。
Grigor的算法对于大m
非常有效,因此需要考虑更小m
的风险。
因此很明显,您需要考虑m
的分布情况,并根据需要针对不同情况进行优化。
例如,可能值得简单地跟踪非常小m
的最小模数。
但是假设m ~ 2^32
?然后搜索算法(当然也是给定的,否则)需要检查2^32
间隔,这可能相当于搜索整个集合。