0% completed
You are given an array arr
containing integers greater than 0
. Additionally, you are given the array of queries where queries[i] = [left<sub>i</sub>, right<sub>i</sub>].
For each query, compute the XOR of the elements in arr
from index left<sub>i</sub> to right<sub>i</sub> (inclusive)
Return an array answer
where answer[i]
represents the result of the i<sup>th</sup> query.
[2, 4, 7, 3]
, queries = [[0, 1], [1, 3], [0, 2]]
[6, 0, 1]
[5, 9, 12, 6]
, queries = [[2, 3], [0, 2], [1, 2]]
[10, 0, 5]
[1, 3, 5, 7, 9]
, queries = [[1, 4], [0, 3], [2, 4]]
[8, 0, 11]
Constraints:
To solve this problem, we can use Mo's Algorithm, which is a powerful technique used to answer multiple queries on an array in an efficient manner. The core idea is to sort the queries in a way that minimizes the amount of work needed to process them. We can do this by sorting based on the blocks of the query ranges and then processing each block while keeping track of the current XOR value. By moving the pointers to include or exclude elements in the current range, we can quickly compute the XOR for each query without recalculating from scratch.
This approach is effective because it reduces the time complexity compared to a naive approach where we would recompute the XOR for every query from scratch. By reusing the results from previous computations, we can answer each query in sub-linear time relative to the size of the array, making the algorithm scalable even for large inputs.
Initialization:
Query
that stores each query's left
, right
indices and its original index in the queries
array. This is essential for keeping track of the order of queries after sorting.blockSize
as the square root of the length of arr
.qs[]
to store the queries as Query
objects, with each query’s left
, right
, and original index.Sort Queries:
qs[]
based on:
left / blockSize
.right
index.currentLeft
and currentRight
pointers during query processing.Initialize Pointers:
currentLeft
to 0, currentRight
to -1, and currentXor
to 0.arr[]
being processed, and currentXor
stores the XOR of this segment.Process Each Query:
qs[]
:
currentRight
: While currentRight
is less than query.right
, move currentRight
to the right, including new elements in the XOR calculation.currentRight
: While currentRight
is greater than query.right
, move currentRight
to the left, excluding elements from the XOR calculation.currentLeft
: While currentLeft
is less than query.left
, move currentLeft
to the right, excluding elements from the XOR calculation.currentLeft
: While currentLeft
is greater than query.left
, move currentLeft
to the left, including new elements in the XOR calculation.currentLeft
and currentRight
, store the computed currentXor
in answer[query.index]
.Return the Results:
answer[]
array containing the results for each query.Let’s walk through the algorithm with arr = [2, 4, 7, 3]
and queries = [[0, 1], [1, 3], [0, 2]]
.
Step 1: Initialization
queries = [[0, 1], [1, 3], [0, 2]]
blockSize = 2
(since sqrt(4) = 2
)answer[] = [0, 0, 0]
Step 2: Create Query
objects
qs[0] = Query(0, 1, 0)
→ corresponds to the first query.qs[1] = Query(1, 3, 1)
→ corresponds to the second query.qs[2] = Query(0, 2, 2)
→ corresponds to the third query.Step 3: Sort the queries (qs[]
array)
blockSize = 2
. All queries belong to the first block. The sorted Queries are:
qs[0] = Query(0, 1, 0)
qs[1] = Query(0, 2, 2)
qs[2] = Query(1, 3, 1)
Step 4: Initialize pointers and currentXor
currentLeft = 0
currentRight = -1
currentXor = 0
Step 5: Process the first query (Query(0, 1, 0))
currentRight
to 1:
currentRight = 0
, currentXor = 0 XOR arr[0] = 0 XOR 2 = 2
currentRight = 1
, currentXor = 2 XOR arr[1] = 2 XOR 4 = 6
currentLeft
as it's already 0.answer[0] = 6
Step 6: Process the second query (Query(0, 2, 2))
currentRight
to 2:
currentRight = 2
, currentXor = 6 XOR arr[2] = 6 XOR 7 = 1
currentLeft
as it's already 0.answer[2] = 1
Step 7: Process the third query (Query(1, 3, 1))
currentRight
to 3:
currentRight = 3
, currentXor = 1 XOR arr[3] = 1 XOR 3 = 2
currentLeft
to 1:
currentXor = 2 XOR arr[0] = 2 XOR 2 = 0
answer[1] = 0
Final Output:
answer[] = [6, 0, 1]
The overall time complexity is O(Q \log Q + (N + Q) \times \sqrt{N}) \approx ((N + Q) \times \sqrt{N})), according to Mo's algorithm.
Overall Space Complexity: O(N + Q)
.....
.....
.....