Given an N-ary Tree consisting of N nodes valued from 1 to N, an array arr[] consisting of N positive integers, where arr[i] is the value associated with the ith node, and Q queries, each consisting of a node. The task for each query is to find the Bitwise OR of node values present in the subtree of the given node.
Examples:
Input: arr[] = {2, 3, 4, 8, 16} Queries[]: {2, 3, 1}Â
Output: 3 28 31
Explanation:Â
Query 1: Bitwise OR(subtree(Node 2)) = Bitwise OR(Node 2) = Bitwise OR(3) = 3
Query 2: Bitwise OR(subtree(Node 3)) = Bitwise OR(Node 3, Node 4, Node 5) = Bitwise OR(4, 8, 16) = 28
Query 3: Bitwise OR(subtree(Node 1)) = Bitwise OR(Node1, Node 2, Node 3, Node 4, Node 5) = Bitwise OR(2, 3, 4, 8, 16) = 31Input: arr[] = {2, 3, 4, 8, 16} Queries[]: {4, 5}Â
Output: 8 16
Explanation:Â
Query 1: Bitwise OR(subtree(Node 4)) = bitwise OR(Node 4) = 8
Query 2: Bitwise OR(subtree(Node 5)) = bitwise OR(Node 5) = 16
Naive Approach: The simplest approach to solve this problem is to traverse the subtree of the given node and for each query, calculate the Bitwise OR of every node in the subtree of that node and print that value. 
Time Complexity: O(Q * N)
Auxiliary Space: O(Q * N)
Efficient Approach: To optimize the above approach, the idea is to precompute the Bitwise OR of all subtrees present in the given tree, and for each query, find the Bitwise XOR of subtrees for every given node. Follow the steps below to solve the problem:
- Initialize a vector ans[] to store the Bitwise OR of all subtrees present in the given Tree.
- Precompute the Bitwise OR for every subtree using Depth First Search(DFS).
- If the node is a leaf node, the bitwise OR of this node is the node value itself.
- Otherwise, the Bitwise OR for the subtree is equal to the Bitwise OR of all subtree values of its children.
- After completing the above steps, print the value stored at ans[Queries[i]] for every ith query.
Below is the implementation of the above approach:
C++
| // C++ program for the above approach  #include <bits/stdc++.h>usingnamespacestd;  // Maximum Number of nodesconstintN = 1e5 + 5;  // Adjacency listvector<int> adj[N];  // Stores Bitwise OR of each nodevector<int> answer(N);  // Function to add edges to the TreevoidaddEdgesToGraph(intEdges[][2],                     intN){    // Traverse the edges    for(inti = 0; i < N - 1; i++) {        intu = Edges[i][0];        intv = Edges[i][1];          // Add edges        adj[u].push_back(v);        adj[v].push_back(u);    }}  // Function to perform DFS// Traversal on the given treevoidDFS(intnode, intparent, intVal[]){    // Initialize answer with bitwise    // OR of current node    answer[node] = Val[node];      // Iterate over each child    // of the current node    for(intchild : adj[node]) {          // Skip parent node        if(child == parent)            continue;          // Call DFS for each child        DFS(child, node, Val);          // Taking bitwise OR of the        // answer of the child to        // find node's OR value        answer[node] = (answer[node]                        | answer[child]);    }}  // Function to call DFS from the'=// root for precomputing answersvoidpreprocess(intVal[]){    DFS(1, -1, Val);}  // Function to calculate and print// the Bitwise OR for Q queriesvoidfindSubtreeOR(intQueries[], intQ,                   intVal[]){    // Perform preprocessing    preprocess(Val);      // Iterate over each given query    for(inti = 0; i < Q; i++) {          cout << answer[Queries[i]]             << ' ';    }}  // Utility function to find and// print bitwise OR for Q queriesvoidfindSubtreeORUtil(    intN, intEdges[][2], intVal[],    intQueries[], intQ){    // Function to add edges to graph    addEdgesToGraph(Edges, N);      // Function call    findSubtreeOR(Queries, Q, Val);}  // Driver Codeintmain(){    // Number of nodes    intN = 5;    intEdges[][2]        = { { 1, 2 }, { 1, 3 },             { 3, 4 }, { 3, 5 } };      intVal[] = { 0, 2, 3, 4, 8, 16 };    intQueries[] = { 2, 3, 1 };      intQ = sizeof(Queries)            / sizeof(Queries[0]);      // Function call    findSubtreeORUtil(N, Edges, Val,                      Queries, Q);      return0;} | 
Java
| // Java program for above approachimportjava.util.*;importjava.lang.*;importjava.io.*;  classGFG{    // Maximum Number of nodes  staticintN = (int)1e5 + 5;    // Adjacency list  staticArrayList<ArrayList<Integer>> adj;    // Stores Bitwise OR of each node  staticint[] answer;    // Function to add edges to the Tree  staticvoidaddEdgesToGraph(intEdges[][],                              intN)  {    // Traverse the edges    for(inti = 0; i < N - 1; i++)     {      intu = Edges[i][0];      intv = Edges[i][1];        // Add edges      adj.get(u).add(v);      adj.get(v).add(u);    }  }    // Function to perform DFS  // Traversal on the given tree  staticvoidDFS(intnode, intparent, intVal[])  {      // Initialize answer with bitwise    // OR of current node    answer[node] = Val[node];      // Iterate over each child    // of the current node    for(Integer child : adj.get(node))    {        // Skip parent node      if(child == parent)        continue;        // Call DFS for each child      DFS(child, node, Val);        // Taking bitwise OR of the      // answer of the child to      // find node's OR value      answer[node] = (answer[node]                      | answer[child]);    }  }    // Function to call DFS from the'=  // root for precomputing answers  staticvoidpreprocess(intVal[])  {    DFS(1, -1, Val);  }    // Function to calculate and print  // the Bitwise OR for Q queries  staticvoidfindSubtreeOR(intQueries[], intQ,                            intVal[])  {    Â    // Perform preprocessing    preprocess(Val);      // Iterate over each given query    for(inti = 0; i < Q; i++)     {      System.out.println(answer[Queries[i]] + " ");    }  }    // Utility function to find and  // print bitwise OR for Q queries  staticvoidfindSubtreeORUtil(intN, intEdges[][],                                 intVal[], intQueries[],                                 intQ)  {      // Function to add edges to graph    addEdgesToGraph(Edges, N);      // Function call    findSubtreeOR(Queries, Q, Val);  }    // Driver function  publicstaticvoidmain (String[] args)  {      adj = newArrayList<>();    for(inti = 0; i < N; i++)      adj.add(newArrayList<>());    answer = newint[N];    N = 5;    intEdges[][] = { { 1, 2}, { 1, 3},                     { 3, 4}, { 3, 5} };      intVal[] = { 0, 2, 3, 4, 8, 16};    intQueries[] = { 2, 3, 1};    intQ = Queries.length;      // Function call    findSubtreeORUtil(N, Edges, Val,                      Queries, Q);  }}  // This code is contributed by offbeat | 
Python3
| # Python3 program for the above approach Â# Maximum Number of nodesN =100005; Â# Adjacency listadj =[[] fori inrange(N)]; Â# Stores Bitwise OR of each nodeanswer =[0fori inrange(N)] Â# Function to add edges to the TreedefaddEdgesToGraph(Edges, N):      # Traverse the edges    fori inrange(N -1):    Â        u =Edges[i][0];        v =Edges[i][1]; Â        # Add edges        adj[u].append(v);        adj[v].append(u);    Â# Function to perform DFS# Traversal on the given treedefDFS(node, parent, Val):      # Initialize answer with bitwise    # OR of current node    answer[node] =Val[node]; Â    # Iterate over each child    # of the current node    forchild inadj[node]:    Â        # Skip parent node        if(child ==parent):            continue; Â        # Call DFS for each child        DFS(child, node, Val); Â        # Taking bitwise OR of the        # answer of the child to        # find node's OR value        answer[node] =(answer[node]                        | answer[child]);    Â# Function to call DFS from the'=# root for precomputing answersdefpreprocess( Val):      DFS(1, -1, Val);  # Function to calculate and print# the Bitwise OR for Q queriesdeffindSubtreeOR(Queries, Q, Val):      # Perform preprocessing    preprocess(Val); Â    # Iterate over each given query    fori inrange(Q):        Â        print(answer[Queries[i]], end=' ')  Â# Utility function to find and# print bitwise OR for Q queriesdeffindSubtreeORUtil( N, Edges, Val, Queries, Q):      # Function to add edges to graph    addEdgesToGraph(Edges, N); Â    # Function call    findSubtreeOR(Queries, Q, Val); Â# Driver Codeif__name__=='__main__':    Â    # Number of nodes    N =5;    Edges =[ [ 1, 2], [ 1, 3], [ 3, 4], [ 3, 5] ]; Â    Val =[ 0, 2, 3, 4, 8, 16];    Queries =[ 2, 3, 1]; Â    Q =len(Queries) Â    # Function call    findSubtreeORUtil(N, Edges, Val,Queries, Q);      # This code is contributed by rutvik_56 | 
C#
| // C# program to generate// n-bit Gray codesusingSystem;usingSystem.Collections.Generic;classGFG {    // Maximum Number of nodes  staticintN = (int)1e5 + 5;    // Adjacency list  staticList<List<int> > adj;    // Stores Bitwise OR of each node  staticint[] answer;    // Function to Add edges to the Tree  staticvoidAddEdgesToGraph(int[, ] Edges, intN)  {      // Traverse the edges    for(inti = 0; i < N - 1; i++) {      intu = Edges[i, 0];      intv = Edges[i, 1];        // Add edges      adj[u].Add(v);      adj[v].Add(u);    }  }    // Function to perform DFS  // Traversal on the given tree  staticvoidDFS(intnode, intparent, int[] Val)  {      // Initialize answer with bitwise    // OR of current node    answer[node] = Val[node];      // Iterate over each child    // of the current node    foreach(intchild inadj[node])    {        // Skip parent node      if(child == parent)        continue;        // Call DFS for each child      DFS(child, node, Val);        // Taking bitwise OR of the      // answer of the child to      // find node's OR value      answer[node] = (answer[node] | answer[child]);    }  }    // Function to call DFS from the'=  // root for precomputing answers  staticvoidpreprocess(int[] Val) { DFS(1, -1, Val); }    // Function to calculate and print  // the Bitwise OR for Q queries  staticvoidfindSubtreeOR(int[] Queries, intQ,                            int[] Val)  {      // Perform preprocessing    preprocess(Val);      // Iterate over each given query    for(inti = 0; i < Q; i++) {      Console.Write(answer[Queries[i]] + " ");    }  }    // Utility function to find and  // print bitwise OR for Q queries  staticvoidfindSubtreeORUtil(intN, int[, ] Edges,                                int[] Val, int[] Queries,                                intQ)  {      // Function to Add edges to graph    AddEdgesToGraph(Edges, N);      // Function call    findSubtreeOR(Queries, Q, Val);  }    // Driver function  publicstaticvoidMain(String[] args)  {      adj = newList<List<int> >();    for(inti = 0; i < N; i++)      adj.Add(newList<int>());    answer = newint[N];    N = 5;    int[, ] Edges      = { { 1, 2 }, { 1, 3 }, { 3, 4 }, { 3, 5 } };      int[] Val = { 0, 2, 3, 4, 8, 16 };    int[] Queries = { 2, 3, 1 };    intQ = Queries.Length;      // Function call    findSubtreeORUtil(N, Edges, Val, Queries, Q);  }}  // This code is contributed by grand_master. | 
Javascript
| <script>// Javascript program for the above approach  // Maximum Number of nodesconst N = 1e5 + 5;  // Adjacency listlet adj = [];  for(let i = 0; i < N; i++) {    adj.push([])}  // Stores Bitwise OR of each nodelet answer = newArray(N);  // Function to add edges to the TreefunctionaddEdgesToGraph(Edges, N) {    // Traverse the edges    for(let i = 0; i < N - 1; i++) {        let u = Edges[i][0];        let v = Edges[i][1];          // Add edges        adj[u].push(v);        adj[v].push(u);    }}  // Function to perform DFS// Traversal on the given treefunctionDFS(node, parent, Val) {    // Initialize answer with bitwise    // OR of current node    answer[node] = Val[node];      // Iterate over each child    // of the current node    for(let child of adj[node]) {          // Skip parent node        if(child == parent)            continue;          // Call DFS for each child        DFS(child, node, Val);          // Taking bitwise OR of the        // answer of the child to        // find node's OR value        answer[node] = (answer[node] | answer[child]);    }}  // Function to call DFS from the'=// root for precomputing answersfunctionpreprocess(Val) {    DFS(1, -1, Val);}  // Function to calculate and print// the Bitwise OR for Q queriesfunctionfindSubtreeOR(Queries, Q, Val) {    // Perform preprocessing    preprocess(Val);      // Iterate over each given query    for(let i = 0; i < Q; i++) {          document.write(answer[Queries[i]] + ' ');    }}  // Utility function to find and// print bitwise OR for Q queriesfunctionfindSubtreeORUtil(N, Edges, Val, Queries, Q) {    // Function to add edges to graph    addEdgesToGraph(Edges, N);      // Function call    findSubtreeOR(Queries, Q, Val);}  // Driver Code  // Number of nodeslet n = 5;let Edges    = [[1, 2], [1, 3],       [3, 4], [3, 5]];  let Val = [0, 2, 3, 4, 8, 16];let Queries = [2, 3, 1];  let Q = Queries.length;  // Function callfindSubtreeORUtil(n, Edges, Val, Queries, Q);      // This code is contributed by _saurabh_jaiswal</script> | 
3 28 31
Â
Time Complexity: O(N + Q)
Auxiliary Space: O(N)
Â
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

 
                                    








