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>using namespace std;Â
// Maximum Number of nodesconst int N = 1e5 + 5;Â
// Adjacency listvector<int> adj[N];Â
// Stores Bitwise OR of each nodevector<int> answer(N);Â
// Function to add edges to the Treevoid addEdgesToGraph(int Edges[][2],                     int N){    // Traverse the edges    for (int i = 0; i < N - 1; i++) {        int u = Edges[i][0];        int v = Edges[i][1];Â
        // Add edges        adj[u].push_back(v);        adj[v].push_back(u);    }}Â
// Function to perform DFS// Traversal on the given treevoid DFS(int node, int parent, int Val[]){    // Initialize answer with bitwise    // OR of current node    answer[node] = Val[node];Â
    // Iterate over each child    // of the current node    for (int child : 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 answersvoid preprocess(int Val[]){Â Â Â Â DFS(1, -1, Val);}Â
// Function to calculate and print// the Bitwise OR for Q queriesvoid findSubtreeOR(int Queries[], int Q,                   int Val[]){    // Perform preprocessing    preprocess(Val);Â
    // Iterate over each given query    for (int i = 0; i < Q; i++) {Â
        cout << answer[Queries[i]]             << ' ';    }}Â
// Utility function to find and// print bitwise OR for Q queriesvoid findSubtreeORUtil(    int N, int Edges[][2], int Val[],    int Queries[], int Q){    // Function to add edges to graph    addEdgesToGraph(Edges, N);Â
    // Function call    findSubtreeOR(Queries, Q, Val);}Â
// Driver Codeint main(){    // Number of nodes    int N = 5;    int Edges[][2]        = { { 1, 2 }, { 1, 3 },             { 3, 4 }, { 3, 5 } };Â
    int Val[] = { 0, 2, 3, 4, 8, 16 };    int Queries[] = { 2, 3, 1 };Â
    int Q = sizeof(Queries)            / sizeof(Queries[0]);Â
    // Function call    findSubtreeORUtil(N, Edges, Val,                      Queries, Q);Â
    return 0;} |
Java
// Java program for above approachimport java.util.*;import java.lang.*;import java.io.*;Â
class GFG{Â
  // Maximum Number of nodes  static int N = (int)1e5 + 5;Â
  // Adjacency list  static ArrayList<ArrayList<Integer>> adj;Â
  // Stores Bitwise OR of each node  static int[] answer;Â
  // Function to add edges to the Tree  static void addEdgesToGraph(int Edges[][],                              int N)  {    // Traverse the edges    for (int i = 0; i < N - 1; i++)     {      int u = Edges[i][0];      int v = Edges[i][1];Â
      // Add edges      adj.get(u).add(v);      adj.get(v).add(u);    }  }Â
  // Function to perform DFS  // Traversal on the given tree  static void DFS(int node, int parent, int Val[])  {Â
    // 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  static void preprocess(int Val[])  {    DFS(1, -1, Val);  }Â
  // Function to calculate and print  // the Bitwise OR for Q queries  static void findSubtreeOR(int Queries[], int Q,                            int Val[])  {         // Perform preprocessing    preprocess(Val);Â
    // Iterate over each given query    for (int i = 0; i < Q; i++)     {      System.out.println(answer[Queries[i]] + " ");    }  }Â
  // Utility function to find and  // print bitwise OR for Q queries  static void findSubtreeORUtil(int N, int Edges[][],                                 int Val[], int Queries[],                                 int Q)  {Â
    // Function to add edges to graph    addEdgesToGraph(Edges, N);Â
    // Function call    findSubtreeOR(Queries, Q, Val);  }Â
  // Driver function  public static void main (String[] args)  {Â
    adj = new ArrayList<>();    for(int i = 0; i < N; i++)      adj.add(new ArrayList<>());    answer = new int[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 };    int Q = 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 = [[] for i in range(N)];  # Stores Bitwise OR of each nodeanswer = [0 for i in range(N)]  # Function to add edges to the Treedef addEdgesToGraph(Edges, N):Â
    # Traverse the edges    for i in range(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 treedef DFS(node, parent, Val):Â
    # Initialize answer with bitwise    # OR of current node    answer[node] = Val[node];      # Iterate over each child    # of the current node    for child in 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 answersdef preprocess( Val):Â
    DFS(1, -1, Val);Â
# Function to calculate and print# the Bitwise OR for Q queriesdef findSubtreeOR(Queries, Q, Val):Â
    # Perform preprocessing    preprocess(Val);      # Iterate over each given query    for i in range(Q):                 print(answer[Queries[i]], end=' ')   # Utility function to find and# print bitwise OR for Q queriesdef findSubtreeORUtil( 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 codesusing System;using System.Collections.Generic;class GFG {Â
  // Maximum Number of nodes  static int N = (int)1e5 + 5;Â
  // Adjacency list  static List<List<int> > adj;Â
  // Stores Bitwise OR of each node  static int[] answer;Â
  // Function to Add edges to the Tree  static void AddEdgesToGraph(int[, ] Edges, int N)  {Â
    // Traverse the edges    for (int i = 0; i < N - 1; i++) {      int u = Edges[i, 0];      int v = Edges[i, 1];Â
      // Add edges      adj[u].Add(v);      adj[v].Add(u);    }  }Â
  // Function to perform DFS  // Traversal on the given tree  static void DFS(int node, int parent, int[] Val)  {Â
    // Initialize answer with bitwise    // OR of current node    answer[node] = Val[node];Â
    // Iterate over each child    // of the current node    foreach(int child in 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 answers  static void preprocess(int[] Val) { DFS(1, -1, Val); }Â
  // Function to calculate and print  // the Bitwise OR for Q queries  static void findSubtreeOR(int[] Queries, int Q,                            int[] Val)  {Â
    // Perform preprocessing    preprocess(Val);Â
    // Iterate over each given query    for (int i = 0; i < Q; i++) {      Console.Write(answer[Queries[i]] + " ");    }  }Â
  // Utility function to find and  // print bitwise OR for Q queries  static void findSubtreeORUtil(int N, int[, ] Edges,                                int[] Val, int[] Queries,                                int Q)  {Â
    // Function to Add edges to graph    AddEdgesToGraph(Edges, N);Â
    // Function call    findSubtreeOR(Queries, Q, Val);  }Â
  // Driver function  public static void Main(String[] args)  {Â
    adj = new List<List<int> >();    for (int i = 0; i < N; i++)      adj.Add(new List<int>());    answer = new int[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 };    int Q = 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 = new Array(N);Â
// Function to add edges to the Treefunction addEdgesToGraph(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 treefunction DFS(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 answersfunction preprocess(Val) {Â Â Â Â DFS(1, -1, Val);}Â
// Function to calculate and print// the Bitwise OR for Q queriesfunction findSubtreeOR(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 queriesfunction findSubtreeORUtil(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!

