1

假设我们连续有n 个空框。我们将把m组硬币放入预先知道的一些连续的盒子中。我们将第一组硬币放入从i_1j_1的盒子中,将第二组硬币放入从i_2j_2的盒子中,依此类推。

在将所有硬币放入盒子后,让c_i盒子i中的硬币数量。我们希望能够快速确定索引为 i = s, s + 1, ... e - 1, e的框中有多少硬币 ,即我们要计算总和

c_s +c_(s+1) + ... + c_e

有效率的。这可以通过使用Fenwick 树来完成。在没有任何改进的情况下,Fenwick 树需要O(n)空间来存储c_i(在表中;实际上,tree[i] != c_i,值存储得更智能)和 O(log n) 时间来计算上和。

如果我们有这样的情况

  • n太大了,我们无法制作长度为n的表格(比如说 ~ 10 000 000 000)
  • m足够小(比如说 ~ 500 000)

有一种方法可以以某种方式压缩框的坐标(索引),即只存储索引为i_1i_2、 ... 、i_m的框就足够了。由于存储在tree[i]中的值取决于 i 的二进制表示我的想法是对索引i_1j_1i_2j_2、 ... 、i_mj_m进行排序,并制作一棵长度为O(m)的树。然后向树中添加新值将是直截了当的。此外,为了计算总和,我们只需要找到不大于e的第一个索引最后一个不小于s。两者都可以通过二分搜索来完成。之后,可以很容易地计算总和。

问题发生在二维情况下。现在,我们在平面上有一个点(x,y)区域, 0 < x,y < n。该区域有m个矩形。我们知道它们的左下角和右上角的坐标,我们想计算有多少个矩形包含一个点(a,b)。最简单(也是我唯一)的想法是遵循一维情况的方式:对于角的每个坐标x_i存储角的所有坐标y_i。这个想法不是那么聪明,因为它需要O(m^2) =太多的空间。我的问题是

How to store coordinates in the tree in a more efficient way?

使用 Fenwick 树的问题的解决方案是首选,但每个解决方案都是受欢迎的!

4

1 回答 1

3
  1. 最简单的方法是使用 map/unordered_map 而不是二维数组。在这种情况下,您甚至不需要坐标压缩。Map 只会在需要时创建键值对,因此它会为输入的每个点创建 log^2(n) 键值对。
  2. 您也可以使用延迟初始化基于指针(而不是数组)分割树(您应该只在需要时创建节点)。
  3. 使用二维分段树。可以注意到,对于每个 y 坐标的规范段,您可以仅为位于 y_min <= y < y_max 区域中的点构建 x 坐标的段树 (1d),其中 y_min 和 y_max 是 y 的规范段的边界. 这意味着每个输入点将仅在 x 坐标的 log(n) 段树中,这使得总共 O(n log n) 内存。
于 2014-05-08T12:01:44.573 回答