Given an n-ary tree and Q queries where each query consists of an integer u which denotes a node. The task is to print the xor of all the values of nodes in the sub-tree of the given node.
Examples:
Input:
q[] = {0, 1, 4, 5}
Output:
0
3
5
6
Query 1: (1 ^ 2 ^ 3 ^ 4 ^ 5 ^ 6 ^ 7) = 0
Query 2: (2 ^ 4 ^ 5) = 3
Query 3: (5) = 5
Query 4: (6) = 6
Naive approach: For each node we have to traverse the tree for every query find the xor of all the nodes of the sub-tree. So the complexity of the code will be O(N * Q).
Efficient approach: If we pre-compute the xor of all the nodes of the sub-tree by traversing the total tree once and first computing the xor of all the nodes of the sub-tree of the child node first and then using the value of the child node for computing the xor of all the nodes of the sub-tree of the parent node. In this way we can compute the xor in O(N) time and store them for queries. When a query is asked we will print the pre-computed value in O(1) time.
Below is the implementation of the above approach:
C++
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std; // Adjacency list of the graph vector<vector< int > > graph; // Value of the node vector< int > values, xor_values; // Function to pre-compute the xor values int pre_compute_xor( int i, int prev) { // xor of the sub-tree int x = values[i]; for ( int j = 0; j < graph[i].size(); j++) if (graph[i][j] != prev) { // xor x with xor of the sub-tree // of it child nodes x ^= pre_compute_xor(graph[i][j], i); } xor_values[i] = x; // Return the xor return x; } // Function to return the xor of // the nodes of the sub-tree // rooted at node u int query( int u) { return xor_values[u]; } // Driver code int main() { int n = 7; graph.resize(n); xor_values.resize(n); // Create the graph graph[0].push_back(1); graph[0].push_back(2); graph[1].push_back(3); graph[1].push_back(4); graph[2].push_back(5); graph[2].push_back(6); // Set the values of the nodes values.push_back(1); values.push_back(2); values.push_back(3); values.push_back(4); values.push_back(5); values.push_back(6); values.push_back(7); // Pre-computation pre_compute_xor(0, -1); // Perform queries int queries[] = { 0, 1, 4, 5 }; int q = sizeof (queries) / sizeof (queries[0]); for ( int i = 0; i < q; i++) cout << query(queries[i]) << endl; return 0; } |
Java
// Java implementation of the approach import java.util.*; class GFG { static int n = 7 ; // Adjacency list of the graph static Vector<Integer> []graph = new Vector[n]; // Value of the node static Vector<Integer> values = new Vector<Integer>(), xor_values = new Vector<Integer>(n); // Function to pre-compute the xor values static int pre_compute_xor( int i, int prev) { // xor of the sub-tree int x = values.get(i); for ( int j = 0 ; j < graph[i].size(); j++) if (graph[i].get(j)!= prev) { // xor x with xor of the sub-tree // of it child nodes x ^= pre_compute_xor(graph[i].get(j), i); } xor_values.remove(i); xor_values.add(i, x); // Return the xor return x; } // Function to return the xor of // the nodes of the sub-tree // rooted at node u static int query( int u) { return xor_values.get(u); } // Driver code public static void main(String[] args) { for ( int i = 0 ; i < n; i++) { graph[i] = new Vector<Integer>(); xor_values.add( 0 ); } // Create the graph graph[ 0 ].add( 1 ); graph[ 0 ].add( 2 ); graph[ 1 ].add( 3 ); graph[ 1 ].add( 4 ); graph[ 2 ].add( 5 ); graph[ 2 ].add( 6 ); // Set the values of the nodes values.add( 1 ); values.add( 2 ); values.add( 3 ); values.add( 4 ); values.add( 5 ); values.add( 6 ); values.add( 7 ); // Pre-computation pre_compute_xor( 0 , - 1 ); // Perform queries int queries[] = { 0 , 1 , 4 , 5 }; int q = queries.length; for ( int i = 0 ; i < q; i++) System.out.print(query(queries[i]) + "\n" ); } } // This code is contributed by Rajput-Ji |
Python3
# Python3 implementation of the approach # Adjacency list of the graph graph = [] # Value of the node values = [] xor_values = [] # Function to pre-compute the xor values def pre_compute_xor(i, prev): # xor of the sub-tree x = values[i] for j in range ( len (graph[i])): if graph[i][j] ! = prev: # xor x with xor of the sub-tree # of it child nodes x ^ = pre_compute_xor(graph[i][j], i) xor_values[i] = x # Return the xor return x # Function to return the xor of # the nodes of the sub-tree # rooted at node u def query(u): return xor_values[u] # Driver code n = 7 for i in range (n): graph.append([]) xor_values.append( 0 ) # Create the graph graph[ 0 ].append( 1 ) graph[ 0 ].append( 2 ) graph[ 1 ].append( 3 ) graph[ 1 ].append( 4 ) graph[ 2 ].append( 5 ) graph[ 2 ].append( 6 ) # Set the values of the nodes values.append( 1 ) values.append( 2 ) values.append( 3 ) values.append( 4 ) values.append( 5 ) values.append( 6 ) values.append( 7 ) # Pre-computation pre_compute_xor( 0 , - 1 ) # Perform queries queries = [ 0 , 1 , 4 , 5 ] q = len (queries) for i in range (q): print (query(queries[i])) # This code is contributed by divyamohan123 |
C#
// C# implementation of the approach using System; using System.Collections.Generic; class GFG { static int n = 7; // Adjacency list of the graph static List< int > []graph = new List< int >[n]; // Value of the node static List< int > values = new List< int >(), xor_values = new List< int >(n); // Function to pre-compute the xor values static int pre_compute_xor( int i, int prev) { // xor of the sub-tree int x = values[i]; for ( int j = 0; j < graph[i].Count; j++) if (graph[i][j] != prev) { // xor x with xor of the sub-tree // of it child nodes x ^= pre_compute_xor(graph[i][j], i); } xor_values.RemoveAt(i); xor_values.Insert(i, x); // Return the xor return x; } // Function to return the xor of // the nodes of the sub-tree // rooted at node u static int query( int u) { return xor_values[u]; } // Driver code public static void Main(String[] args) { for ( int i = 0; i < n; i++) { graph[i] = new List< int >(); xor_values.Add(0); } // Create the graph graph[0].Add(1); graph[0].Add(2); graph[1].Add(3); graph[1].Add(4); graph[2].Add(5); graph[2].Add(6); // Set the values of the nodes values.Add(1); values.Add(2); values.Add(3); values.Add(4); values.Add(5); values.Add(6); values.Add(7); // Pre-computation pre_compute_xor(0, -1); // Perform queries int []queries = { 0, 1, 4, 5 }; int q = queries.Length; for ( int i = 0; i < q; i++) Console.Write(query(queries[i]) + "\n" ); } } // This code is contributed by PrinciRaj1992 |
0 3 5 6
Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.