给定一个大小为N的数组,以及一个大小为N的区间数组,每个区间都是第一个数组的连续段,我需要处理更新数组元素并要求总和的Q查询第二个数组中的段(iTH间隔中的元素与jTH间隔的总和)。
现在,可以轻松处理第一个查询。我可以从数组中构建一个分段树。我可以用它来计算第一个数组中间隔的总和(第二个数组中的一个元素)。但是如何处理O(log n)中的第二个查询?在最坏的情况下,我更新的元素将在第二个数组的所有间隔中。
我需要一个O(Q log N)或O(Q (logN)^ 2)解决方案。
答案 0 :(得分:0)
这是一个O((Q + N) * sqrt(Q))
解决方案(它基于一个非常标准的sqrt分解思路):
1.让我们假设数组永远不会更新。然后问题变得非常简单:使用前缀和,可以在O(N)
时间进行预计算和每个查询O(1)
解决此问题(这里我们需要2个前缀和数组:一个用于原始数组和另一个用于间隔数组。)
2.现在让我们将查询分成大小为sqrt(Q)
的块。在每个块的开头,我们可以执行与1中相同的操作。仅考虑在此块开始之前发生的那些更新。它可以在线性时间内完成(使用前缀和两次)。此类计算的总数为Q / sqrt(Q) = sqrt(Q)
次(因为它是我们拥有的块数)。到目前为止,它总共给我们O((N + Q) * sqrt(Q))
个时间
3.当我们得到类型2的查询时,已经考虑了当前块之外的所有更新。因此,最多sqrt(Q)
次更新可能会影响答案。因此,让我们几乎天真地处理它们:迭代在此查询之前发生的当前块内的所有更新并更新答案。为此,我们需要知道从i
到j
的间隔中数组中给定位置的出现次数。使用O(Q * sqrt(N + Q))
时间和空间的扫描线算法可以离线解决此部分(由于可以使用基数排序,因此不会出现额外的对数因子)。
所以我们在最坏的情况下得到O((N + Q) * sqrt(Q))
时间和空间。当然,它比O(Q * log N)
更糟糕,但对于约10^5
个查询和数组元素应该可以正常工作。