📌  相关文章
📜  查询以计算N元树中给定节点的每个子树的按位或

📅  最后修改于: 2021-05-25 10:02:56             🧑  作者: Mango

鉴于N叉树由n个节点从1值至N,阵列ARR []选自N的正整数,其中ARR [i]是与所述i节点相关联的值,和Q查询,每个由一个的节点。每个查询的任务是找到给定节点的子树中存在的节点值的按位或

例子:

天真的方法:解决此问题的最简单方法是遍历给定节点的子树,并针对每个查询,计算该节点的子树中每个节点的按位或,并打印该值。
时间复杂度: O(Q * N)
辅助空间: O(Q * N)

高效方法:为了优化上述方法,其思想是预先计算给定树中存在的所有子树的按位或,对于每个查询,为每个给定节点找到子树的按位XOR。请按照以下步骤解决问题:

  • 初始化向量ans []以存储给定Tree中存在的所有子树的按位或。
  • 使用深度优先搜索(DFS)为每个子树预计算按位或。
  • 如果该节点是叶节点,则此节点的按位“或”即是节点值本身。
  • 否则,子树的按位或等于其子级的所有子树值的按位或。
  • 完成上述步骤后,为每个i查询打印存储在ans [Queries [i]]中的值。

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
using namespace std;
 
// Maximum Number of nodes
const int N = 1e5 + 5;
 
// Adjacency list
vector adj[N];
 
// Stores Bitwise OR of each node
vector answer(N);
 
// Function to add edges to the Tree
void 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 tree
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 (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 answers
void preprocess(int Val[])
{
    DFS(1, -1, Val);
}
 
// Function to calculate and print
// the Bitwise OR for Q queries
void 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 queries
void 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 Code
int 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 approach
import java.util.*;
import java.lang.*;
import java.io.*;
 
class GFG
{
 
  // Maximum Number of nodes
  static int N = (int)1e5 + 5;
 
  // Adjacency list
  static ArrayList> 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 nodes
N = 100005;
  
# Adjacency list
adj = [[] for i in range(N)];
  
# Stores Bitwise OR of each node
answer = [0 for i in range(N)]
  
# Function to add edges to the Tree
def 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 tree
def 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 answers
def preprocess( Val):
 
    DFS(1, -1, Val);
 
# Function to calculate and print
# the Bitwise OR for Q queries
def 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 queries
def findSubtreeORUtil( N, Edges, Val, Queries, Q):
 
    # Function to add edges to graph
    addEdgesToGraph(Edges, N);
  
    # Function call
    findSubtreeOR(Queries, Q, Val);
  
# Driver Code
if __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 codes
using System;
using System.Collections.Generic;
class GFG
{
 
  // Maximum Number of nodes
  static int N = (int)1e5 + 5;
 
  // Adjacency list
  static List > 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 >();
    for (int i = 0; i < N; i++)
      adj.Add(new List());
    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.


输出:
3 28 31

时间复杂度: O(N + Q)
辅助空间: O(N)