给定一个n元树和Q个查询,其中每个查询都由表示节点的整数u组成。任务是打印给定节点的子树中所有节点值的异或。
例子:
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
天真的方法:对于每个节点,我们必须遍历每个查询的树,以找到子树所有节点的异或。因此,代码的复杂度将为O(N * Q) 。
高效的方法:如果我们先遍历整个树,然后首先计算子节点的子树的所有节点的异或,然后使用的值来预先计算子树的所有节点的异或子节点,用于计算父节点子树的所有节点的异或。这样,我们可以计算O(N)时间的异或并将其存储以进行查询。当询问查询时,我们将在O(1)时间中打印预先计算的值。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
// Adjacency list of the graph
vector > graph;
// Value of the node
vector 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 []graph = new Vector[n];
// Value of the node
static Vector values = new Vector(),
xor_values = new Vector(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();
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 []graph = new List[n];
// Value of the node
static List values = new List(),
xor_values = new List(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();
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