XOR Queries of a Subarray
Build prefix, where prefix[i] is the XOR of everything before index i, with prefix[0] = 0. Then the XOR of arr[l..r] is prefix[r + 1] ^ prefix[l]. The part before l is in both prefixes, and XOR-ing it twice cancels it out. Each query is then a single XOR.
prefix[i] always means the XOR of everything strictly before index i. Then arr[l..r] is prefix[r + 1] ^ prefix[l], because the part before l appears in both and cancels.
Problem
You get an array arr of positive integers and a list of queries. Each query is a pair [left, right]. The answer to a query is the XOR of the numbers from arr[left] to arr[right], both ends included: arr[left] ^ arr[left + 1] ^ … ^ arr[right].
Return one answer for each query, in the same order as the queries.
An array arr of positive integers, and a list queries of [left, right] pairs.
An array with one answer per query, in the same order.
1 ^ 3 = 2 (0001 ^ 0011 = 0010). 3 ^ 4 = 7. 1 ^ 3 ^ 4 ^ 8 = 14. A range of one number is that number, so the last answer is 8.
2 ^ 10 = 8. 8 ^ 2 ^ 10 = 0. A single 4 is 4. 4 ^ 8 ^ 2 ^ 10 = 4.
- • 1 ≤ arr.length ≤ 3 · 10^4 and 1 ≤ queries.length ≤ 3 · 10^4
- • 1 ≤ arr[i] ≤ 10^9
- • queries[i] has exactly 2 numbers: [left, right]
- • 0 ≤ left ≤ right < arr.length
First, think yourself
Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.
- 1.
Range Sum Query asked for sums. What should replace the adding here, and what happens when a value is XOR-ed with itself?
- 2.
If three queries all cover index 1, how many times does the brute force XOR
arr[1]in total? - 3.
Can I store one value per position that says "everything up to here"? How many of those values would I need?
- 4.
If I know the XOR of everything up to
rand the XOR of everything beforel, how do I get the middle part? - 5.
Is XOR's inverse the same operation as subtraction? What does
x ^ xequal?
Brute force approach
Optimized approach
Why does this algorithm work?
Dry run
All approaches compared
| Approach | Idea | Time | Space |
|---|---|---|---|
| Brute Force | For each query, XOR arr[left..right] from scratch | O(N · Q) | O(1) |
| Optimal | Build prefix XORs once; each query is prefix[r+1] ^ prefix[l] | O(N + Q) | O(N) |
Why does this belong to this pattern?
- “XOR of arr[left] … arr[right]”A range of one array. Like a range sum, it is built from two prefix totals.
- “many queries, the array never changes”Compute the prefix XORs once. After that each query is O(1).
- “XOR, not addition”XOR is its own inverse, so the subtraction step of prefix sums becomes another XOR.
Range Sum Query - Immutable has the same shape with +: a range is the difference of two prefixes. Here XOR is its own inverse, so the "subtract" step becomes another XOR: x ^ x = 0 removes the shared part. Unlike the next question, this one has an array and many queries, so it needs a prefix array. The next question has no array at all; it asks about a range of consecutive numbers.
Don't make this mistake
This is the pattern-confusion trap. The code looks the same as Range Sum Query, so the - slips in. XOR is not subtraction. On [1, 3, 4, 8], query [1, 2]: prefix[3] − prefix[1] = 6 − 1 = 5, but the answer is 3 ^ 4 = 7. The XOR version gives 6 ^ 1 = 0110 ^ 0001 = 0111 = 7.
prefix[i] stops before index i, so prefix[r] leaves out arr[r]. On [1, 3, 4, 8], query [0, 1]: prefix[1] ^ prefix[0] = 1 ^ 0 = 1, which is just arr[0]. The answer is 1 ^ 3 = 2, and prefix[r + 1] = prefix[2] = 2 gives it.
prefix[n] is the XOR of the whole array and needs its own slot. Writing to prefix[n] on a vector of size n is undefined behaviour: it may crash, or silently overwrite memory next to the vector. The leading 0 is what makes the size n + 1.
Want to implement this?
Write it yourself on LeetCode, then come back and compare your code with the solutions above.
Open coding workspaceHow this concept connects to System Design & C++ Systems
Top engineering interviews test whether you understand how algorithms like Bit Manipulation translate into production architectures and low-level memory mechanics.
Foundations: Object-Oriented Principles in C++23
Class invariants, pure virtual interfaces, and RAII smart pointers.
Food Delivery System (Zomato Architecture)
Real-world machine coding application of algorithms and design patterns.
Pointers vs References Deep Dive
Pointer arithmetic and memory layout under the hood.
Virtual Method Table (vtable) & Memory Layout
Polymorphism, vptr overhead, and multiple inheritance in memory.