我有一个很大的间隔[0 ... 2^32 - 1]
。大约有2 ^ 20个点具有一些坐标和值,例如:
1; 435
5; 5454
345345; 5485;
9999999; 43435
4294967294; 35353
我也有一组间隔。间隔数小于2^22
。例如,
1 3; // sum is 435
1 3535; // sum is 435 + 5454
99994 4294967294; // sum is 5485 + 43435 + 35353
对于每个间隔,我必须计算总和模2^32
。
有天真的算法。我可以迭代每个间隔的所有点。它需要O(查询数量*点数)。这太慢了。
是否有更快的算法?
答案 0 :(得分:2)
对点进行排序。迭代点并计算到每个点的值的运行总和。将总和存储在一个数组中。如果要计算间隔的总和,请通过二分搜索找到下限和上限,然后查找较低的总和和较高的总和。这些总和的差异是间隔的总和。
对于您提供的示例,这些点的索引如下:
{0: 1, 1: 5, 2: 345345, 3: 9999999, 4: 4294967294}
总和如下:
{0: 0, 1: 435, 2: 5889, 3: 11374, 4: 54809, 5: 90162}
要计算区间[a..b]
中的总和,请找到不小于p(a)
和p(b)
的最小点的索引a
和b
,并返回sums[p(b)+1] - sums[p(a)]
。
对于1和3,我们找到索引0和0.结果是sums[1] - sums[0]
。
对于1和3535,我们找到索引0和1.结果是sums[2] - sums[0]
。
对于99994和4294967294,我们找到索引2和4.结果为sums[5] - sums[2]
。
准备总和数组需要O(点数)。每个查询都需要O(log(点数))。