鉴于N叉树由n个节点从1值至N,阵列ARR []选自N的正整数,其中ARR [i]是与所述第i个节点相关联的值,和Q查询,每个由一个的节点。每个查询的任务是找到给定节点的子树中存在的节点值的按位或。
例子:
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) = 31
Input: 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
天真的方法:解决此问题的最简单方法是遍历给定节点的子树,并针对每个查询,计算该节点的子树中每个节点的按位或,并打印该值。
时间复杂度: 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)