【问题标题】:How to compute bitwise-or on the segment fast? [closed]如何快速计算分段或分段? [关闭]
【发布时间】:2023-03-28 08:05:01
【问题描述】:

给定一个整数列表。

我想知道是否可以在每个查询的 O(1) 和前提的 O(n) 的段上计算按位或? (一些前缀和)(对于每个查询 O(log n) 和 O(n log n) 的前提,这样做很容易,例如,使用段树,但什么更快?)

【问题讨论】:

  • 什么意思?给定一个整数或布尔值列表,您需要特定子段的or(逻辑或按位),例如a[3] | a[4] | a[5]?可以举个例子吗?
  • 整数列表。按位或
  • 我还可以想出一种方法,每个查询 O(logn) 和 O(nlogn) 预处理,通过累积为列表中的所有值设置每个位的频率,然后检查哪个上限数字中的值高于下限。不要认为每个查询都有 O(1) + O(n) 预处理的方法。

标签: algorithm data-structures prefix-sum


【解决方案1】:

是的,这是可能的。只需为每个位位置构建一个类似前缀和的数组,并用从数据开头设置的运行总位填充它。每个计数器的初始值为零:counter[0][b]=0,而n-th 计数器将存储在数据项 0 到 n-1 中设置的多个位。

然后,您可以通过测试范围两端的b-th 计数器是否不同 (counter[n+1][b] not.eq. counter[m][b]) 来测试位号 b 是否设置在给定范围 [m,n] 中的任何位置。

最后从所有 (8, 16, 32...) 位位置的结果中一点一点地组成一个答案。

请注意,此解决方案需要为原始数据的每一位添加一个额外的整数,这意味着您需要例如如果您的 int 是 32 位宽,则内存增加 32 倍。

【讨论】:

  • 这基本上就是我在cmets中描述的。不过,我不会将其归类为 O(1),而是 O(logn)。两者都有些争议。您可以说 O(1) 因为例如位数int64 是常数,我会说它是 logn 假设列表中值的位数与列表中元素的总数有些相关。当然,对于任意大小的数字都不正确,它应该只是 O(b),其中 b 是最大位数。
  • 这有点吹毛求疵,不是吗?那样的话,你也可以说加法 'n+1' 是 O(log n),因为在最坏的情况下,我们需要通过左侧操作数的所有位进行位溢出。然而,在实践中,我们在任意但恒定的技术约束下工作,这使得整数的宽度为常数;加法、比较和其他基本操作也被认为是常数时间。
  • 当你编写这样的问题时,你通常知道或者你可以选择你处理的整数大小。这变得恒定。您通常将列表的长度视为 O() 估计所引用的可变参数。
  • 为了使前缀和方法有效,我们需要快速随机访问。这需要一个数组。数组通常使用某种整数类型进行索引,有时与平台相关。然后我们预先知道最大位数,因此每个计数器所需的大小。
  • @tobias_k Pinging(之前忘记了)。
猜你喜欢
  • 2011-10-10
  • 1970-01-01
  • 1970-01-01
  • 2021-12-15
  • 2013-03-31
  • 1970-01-01
  • 2016-01-26
  • 1970-01-01
  • 2017-11-04
相关资源
最近更新 更多