我给出了一个长度最大为10^5
&的整数数组。我想对数组进行以下操作。
1→更新任何位置i
的数组值。 (1 <= i <= n)
2→从索引0, X, 2X, 3X, 4X....
(J * X <= n)
操作次数最多为10^5
。
是否有log n
方法来回答查询和更新值。
答案 0 :(得分:1)
(最初的想法是使用Segment Tree,但我认为不需要......)
让N = 10^5, A:= original array of size N
当我们说下面的索引时,我们使用基于0的表示法
创建一个长度最大为B
的整数数组M = NlgN
:
第一个整数等于A[0]
;
接下来N个整数是A
的索引1,2,3 ... N;我称之为第1组
接下来N / 2个整数是指数2,4,6 ......;我称之为第2组
下一个N / 3整数3,6,9 ....我称之为第3组
以下是可视化B
:
B = [A[0] | A[1], A[2], A[3], A[4] | A[2], A[4] | A[3] | A[4]]
我认为原来的想法可以使用,不用甚至使用细分树。
(当您考虑操作2时,我们总是会在B
而不是任何范围上查询特定范围,这是过度的,即我们不需要那么多的灵活性和复杂性来维护数据结构)
您可以创建上述新数组B
,同时创建另一个长度为C
,M
C[i] := products of Group i
对于操作1,只需使用O(# factors of i)
查看您需要更新的组,并更新B
和C
中的值(即C[x]/old B[y] *new B[y]
)
对于操作2,只输出相应的C[i]
不确定我是不是错了但是这应该更快并且应该通过判断,如果最初的想法是正确的但是得到了TLE
由于OP增加了一个新条件:对于操作2,我们还需要乘以A [0],因此我们可以特殊处理它。这是我的想法:
为操作1声明一个新变量z = A[0]
,如果它正在更新索引0,则更新此变量;对于操作2,使用上述相同方法进行查询,然后再乘以z
。
我已更新我的回答,所以现在我只使用B
的第一个元素来表示A[0]
示例强>
A = {1,4,6,2,8,7}
B = {1 | 4,6,2,8,7 | 6,8 | 2 | 8 | 7 } // O(N lg N)
C = {1 | 2688 | 48 | 2 | 8 | 7 } // O (Nlg N)
factorization for all possible index X (X is the index, so <= N) // O(N*sqrt(N))
opeartion 1:
update A[4] to 5: factors = 1,2,4 // Number of factors of index, ~ O(sqrt(N))
which means update Group 1,2,4 i.e. the corresponding elements in B & C
to locate the corresponding elements in B & C maybe a bit tricky,
but that should not increase the complexity
B = {1 | 4,6,2,5,7 | 6,5 | 2 | 5 | 7 } // O(sqrt(N))
C = {1 | 2688 | 48/8*5 | 2 | 8/8*5 | 7 } // O(sqrt(N))
update A[0] to 2:
B = {2 | 4,6,2,5,7 | 6,5 | 2 | 5 | 7 } // O(1)
C = {2 | 2688/8*5 | 48/8*5 | 2 | 8/8*5 | 7 } // O(1)
// Now A is actually {2,4,6,2,5,7}
operation 2:
X = 3
C[3] * C[0] = 2*2 = 4 // O(1)
X = 2
C[2] * C[0] = 30*2 = 60 // O(1)