Imagine you're exploring a magical tree where each node holds a special value, and traveling from the root to any node creates a unique XOR signature by combining all values along the path!
You are given an undirected tree rooted at node 0 with n nodes numbered from 0 to n - 1. Each node i has an integer value vals[i], and its parent is given by par[i].
The path XOR sum from the root to a node u is defined as the bitwise XOR of all vals[i] for nodes i on the path from the root node to node u, inclusive.
You are given a 2D integer array queries, where queries[j] = [u_j, k_j]. For each query, you need to:
Find all nodes in the subtree rooted at u_j
Calculate the path XOR sum for each of these nodes
Find the k_j-th smallest distinct path XOR sum
Return -1 if there are fewer than k_j distinct values
Remember: In a rooted tree, the subtree of a node v includes v and all nodes whose path to the root passes through v.
💡 Note:Tree structure: 0->1,2 and 1->3,4. XOR sums from root to each node: 0:5, 1:5⊕3=6, 2:5⊕7=2, 3:5⊕3⊕2=4, 4:5⊕3⊕1=7. For query [0,2]: all nodes in subtree have XOR sums [5,6,2,4,7], sorted distinct: [2,4,5,6,7], 2nd smallest is 4. For query [1,1]: subtree of 1 has nodes 1,3,4 with XORs [6,4,7], sorted distinct [4,6,7], 1st smallest is 4.
💡 Note:Tree: 0->1,2 and 1->2. XOR sums: 0:1, 1:1⊕1=0, 2:1⊕1⊕1=1. For query [2,2]: subtree of 2 contains only node 2 with XOR sum [1]. There's only 1 distinct value, but we need the 2nd smallest, so return -1.
Constraints
1 ≤ n ≤ 104
0 ≤ vals[i] ≤ 109
par[0] = 0 (root points to itself)
For i > 0: 0 ≤ par[i] < i
1 ≤ queries.length ≤ 104
0 ≤ uj < n
1 ≤ kj ≤ n
The parent array represents a valid tree structure
The optimal approach uses DFS pre-computation to calculate all XOR sums in O(n) time by leveraging the property that child XOR = parent XOR ⊕ child value. For each query, we collect the pre-computed XOR sums from the subtree, find distinct values, sort them, and return the kth smallest. This reduces the time complexity from O(q×n×h) to O(n + q×s×log s) where s is the average subtree size.
Common Approaches
✓
Brute Force (Naive DFS)
⏱️ Time: O(q * n * h)
Space: O(n)
For each query, perform DFS from the query node to find all nodes in its subtree. For each node found, calculate the path XOR sum by traversing from root to that node. Sort all distinct XOR sums and return the kth smallest.
Optimized DFS with Efficient Sorting
⏱️ Time: O(n + q * s * log s)
Space: O(n)
Use DFS to calculate XOR sums for all nodes in one pass, leveraging the property that child XOR = parent XOR ^ child value. Store results and use efficient data structures to answer queries.
Brute Force (Naive DFS) — Algorithm Steps
For each query [u, k], start DFS from node u
For each node in subtree, calculate XOR sum from root by traversing path
Collect all distinct XOR sums in a list
Sort the list and return the kth element (or -1 if not enough)
Repeat for all queries
Visualization
Tap to expand
Step-by-Step Walkthrough
1
Query Processing
For each query, start DFS from the specified node
2
Subtree Collection
Collect all nodes in the subtree using DFS
3
XOR Calculation
For each node, traverse back to root to calculate XOR sum
4
Sorting & Selection
Sort distinct XOR values and pick the kth smallest
Code -
solution.c — C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int children[1000][1000];
static int child_count[1000];
static int vals[1000];
static int par[1000];
int compare_ints(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
void parse_int_array(const char* s, int* arr, int* size) {
*size = 0;
const char* ptr = s;
while (*ptr) {
// Skip non-digit characters except minus
while (*ptr && (*ptr < '0' || *ptr > '9') && *ptr != '-') {
ptr++;
}
if (*ptr == '\0') break;
// Parse number
char* endptr;
arr[(*size)++] = (int)strtol(ptr, &endptr, 10);
ptr = endptr;
}
}
void parse_queries(const char* s, int queries[][2], int* query_count) {
*query_count = 0;
const char* ptr = s;
// Skip to first number
while (*ptr && (*ptr < '0' || *ptr > '9') && *ptr != '-') {
ptr++;
}
while (*ptr) {
// Parse first number of pair
char* endptr;
int first = (int)strtol(ptr, &endptr, 10);
ptr = endptr;
// Skip to second number
while (*ptr && (*ptr < '0' || *ptr > '9') && *ptr != '-') {
ptr++;
}
if (*ptr == '\0') break;
// Parse second number of pair
int second = (int)strtol(ptr, &endptr, 10);
ptr = endptr;
// Store the pair
queries[*query_count][0] = first;
queries[*query_count][1] = second;
(*query_count)++;
// Skip to next number
while (*ptr && (*ptr < '0' || *ptr > '9') && *ptr != '-') {
ptr++;
}
}
}
int get_path_xor(int node, int n) {
int path_xor = 0;
int current = node;
int path[1000];
int path_len = 0;
// Build path from node to root
while (current != -1) {
path[path_len++] = current;
if (current == 0) {
current = -1;
} else {
current = par[current];
}
}
// Calculate XOR along path (from root to node)
for (int i = path_len - 1; i >= 0; i--) {
path_xor ^= vals[path[i]];
}
return path_xor;
}
void get_subtree_nodes(int root, int* subtree, int* subtree_size) {
int stack[1000];
int stack_top = 0;
stack[stack_top++] = root;
*subtree_size = 0;
while (stack_top > 0) {
int node = stack[--stack_top];
subtree[(*subtree_size)++] = node;
for (int i = 0; i < child_count[node]; i++) {
stack[stack_top++] = children[node][i];
}
}
}
int main() {
char line[10000];
// Read n
fgets(line, sizeof(line), stdin);
int n = atoi(line);
// Read vals
fgets(line, sizeof(line), stdin);
int vals_size;
parse_int_array(line, vals, &vals_size);
// Read par
fgets(line, sizeof(line), stdin);
int par_size;
parse_int_array(line, par, &par_size);
// Build adjacency list
memset(child_count, 0, sizeof(child_count));
for (int i = 1; i < n; i++) {
children[par[i]][child_count[par[i]]++] = i;
}
// Read queries
fgets(line, sizeof(line), stdin);
int queries[100][2];
int query_count;
parse_queries(line, queries, &query_count);
// Process queries
for (int q = 0; q < query_count; q++) {
int u = queries[q][0];
int k = queries[q][1];
// Get all nodes in subtree
int subtree_nodes[1000];
int subtree_size;
get_subtree_nodes(u, subtree_nodes, &subtree_size);
// Calculate XOR sums
int xor_sums[1000];
for (int i = 0; i < subtree_size; i++) {
xor_sums[i] = get_path_xor(subtree_nodes[i], n);
}
// Sort and remove duplicates
qsort(xor_sums, subtree_size, sizeof(int), compare_ints);
int unique_count = 0;
if (subtree_size > 0) {
unique_count = 1;
for (int i = 1; i < subtree_size; i++) {
if (xor_sums[i] != xor_sums[unique_count-1]) {
xor_sums[unique_count++] = xor_sums[i];
}
}
}
// Get kth element
int result = (k <= unique_count) ? xor_sums[k-1] : -1;
if (q > 0) printf(",");
printf("%d", result);
}
printf("\n");
return 0;
}
Time & Space Complexity
Time Complexity
⏱️
O(q * n * h)
q queries, each processes up to n nodes, each XOR calculation takes O(h) time where h is tree height
n
2n
✓ Linear Growth
Space Complexity
O(n)
Space for storing subtree nodes and XOR sums
n
2n
⚡ Linearithmic Space
23.4K Views
Medium-HighFrequency
~25 minAvg. Time
892 Likes
Ln 1, Col 1
Smart Actions
💡Explanation
AI Ready
💡 SuggestionTabto acceptEscto dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen
Algorithm Visualization
Pinch to zoom • Tap outside to close
Test Cases
0 passed
0 failed
3 pending
Select Compiler
Choose a programming language
Compiler list would appear here...
AI Editor Features
Header Buttons
💡
Explain
Get a detailed explanation of your code. Select specific code or analyze the entire file. Understand algorithms, logic flow, and complexity.
🔧
Fix
Automatically detect and fix issues in your code. Finds bugs, syntax errors, and common mistakes. Shows you what was fixed.
💡
Suggest
Get improvement suggestions for your code. Best practices, performance tips, and code quality recommendations.
💬
Ask AI
Open an AI chat assistant to ask any coding questions. Have a conversation about your code, get help with debugging, or learn new concepts.
Smart Actions (Slash Commands)
🔧
/fix Enter
Find and fix issues in your code. Detects common problems and applies automatic fixes.
💡
/explain Enter
Get a detailed explanation of what your code does, including time/space complexity analysis.
🧪
/tests Enter
Automatically generate unit tests for your code. Creates comprehensive test cases.
📝
/docs Enter
Generate documentation for your code. Creates docstrings, JSDoc comments, and type hints.
⚡
/optimize Enter
Get performance optimization suggestions. Improve speed and reduce memory usage.
AI Code Completion (Copilot-style)
👻
Ghost Text Suggestions
As you type, AI suggests code completions shown in gray text. Works with keywords like def, for, if, etc.
Tabto acceptEscto dismiss
💬
Comment-to-Code
Write a comment describing what you want, and AI generates the code. Try: # two sum, # binary search, # fibonacci
💡
Pro Tip: Select specific code before using Explain, Fix, or Smart Actions to analyze only that portion. Otherwise, the entire file will be analyzed.