给定一个包含N 个节点的N 元树,与每个节点相关联的值和Q 个查询,其中每个查询包含一个节点。任务是找到子树中存在的所有节点(包括其自身)的值的GCD 。
例子:
Tree:
query[]: {2, 3, 1}
Output: {3, 4, 1}
Explanation:
For query 1: GCD(subtree(node2)) = GCD(node2) = GCD(3) = 3
For query 2: GCD(subtree(node3)) = GCD(node3, node4, node5) = GCD(4, 8, 16) = 4
天真的方法:
- 对于每个查询,遍历给定节点的整个子树。
- 计算子树中每个节点的 GCD 并返回它。
时间复杂度:O(Q*N)
空间复杂度:O(Q*N)
有效的方法:
- 最初使用深度优先搜索 (DFS) 为每个子树预先计算 GCD。
- 如果该节点是叶节点,则该节点的 GCD 就是编号本身。
- 对于非叶子节点,子树的 GCD 是其子树的所有子树值的 GCD。
- 现在,很容易在恒定时间内找到答案,因为答案已经存储
下面是上述方法的实现:
C++
1(2)
/ \
/ \
2(3) 3(4)
/ \
/ \
4(8) 5(16)
Java
// C++ program to find GCD
// of each subtree for
// a given node by Q queries
#include
using namespace std;
// Maximum Number of nodes
const int N = 1e5 + 5;
// Tree represented
// as adjacency list
vector > v(N);
// for storing value
// associates with node
vector val(N);
// for storing GCD
// of every subarray
vector answer(N);
// number of nodes
int n;
// Function to find GCD of two numbers
// using Euclidean algo
int gcd(int a, int b)
{
// if b == 0
// then simply return a
if (b == 0)
return a;
return gcd(b, a % b);
}
// DFS function to traverse the tree
void DFS(int node, int parent)
{
// initializing answer
// with GCD of this node.
answer[node] = val[node];
// iterate over each
// child of current node
for (int child : v[node])
{
// skipping the parent
if (child == parent)
continue;
// call DFS for each child
DFS(child, node);
// taking GCD of the answer
// of the child to
// find node's GCD
answer[node] = gcd(answer[node], answer[child]);
}
}
// Calling DFS from the root (1)
// for precomputing answers
void preprocess() { DFS(1, -1); }
// Function to find and
// print GCD for Q queries
void findGCD(int queries[], int q)
{
// doing preprocessing
preprocess();
// iterate over each given query
for (int i = 0; i < q; i++) {
int GCD = answer[queries[i]];
cout << "For subtree of " << queries[i]
<< ", GCD = " << GCD << endl;
}
}
// Driver code
int main()
{
/*
Tree:
1 (2)
/ \
2 (3) 3 (4)
/ \
4 (8) 5 (16)
*/
n = 5;
// making a undirected tree
v[1].push_back(2);
v[2].push_back(1);
v[1].push_back(3);
v[3].push_back(1);
v[3].push_back(4);
v[4].push_back(3);
v[3].push_back(5);
v[5].push_back(3);
// values associated with nodes
val[1] = 2;
val[2] = 3;
val[3] = 4;
val[4] = 8;
val[5] = 16;
int queries[] = { 2, 3, 1 };
int q = sizeof(queries) / sizeof(queries[0]);
// Function call
findGCD(queries, q);
return 0;
}
Python3
// Java program to find GCD
// of each subtree for
// a given node by Q queries
import java.util.*;
class GFG {
// Maximum Number of nodes
static int N = (int)(1e5 + 5);
// Tree represented
// as adjacency list
static Vector[] v = new Vector[N];
// For storing value
// associates with node
static int[] val = new int[N];
// For storing GCD
// of every subarray
static int[] answer = new int[N];
// Number of nodes
static int n;
// Function to find GCD of
// two numbers using
// Euclidean algo
static int gcd(int a, int b)
{
// If b == 0
// then simply return a
if (b == 0)
return a;
return gcd(b, a % b);
}
// DFS function to traverse
// the tree
static void DFS(int node, int parent)
{
// Initializing answer
// with GCD of this node.
answer[node] = val[node];
// Iterate over each
// child of current node
for (int child : v[node]) {
// Skipping the parent
if (child == parent)
continue;
// Call DFS for each child
DFS(child, node);
// Taking GCD of the answer
// of the child to
// find node's GCD
answer[node] = gcd(answer[node], answer[child]);
}
}
// Calling DFS from the root (1)
// for precomputing answers
static void preprocess() { DFS(1, -1); }
// Function to find and
// print GCD for Q queries
static void findGCD(int queries[], int q)
{
// Doing preprocessing
preprocess();
// iterate over each given query
for (int i = 0; i < q; i++) {
int GCD = answer[queries[i]];
System.out.print("For subtree of " + queries[i]
+ ", GCD = " + GCD + "\n");
}
}
// Driver code
public static void main(String[] args)
{
/*
Tree:
1 (2)
/ \
2 (3) 3 (4)
/ \
4 (8) 5 (16)
*/
n = 5;
for (int i = 0; i < v.length; i++)
v[i] = new Vector();
// Making a undirected tree
v[1].add(2);
v[2].add(1);
v[1].add(3);
v[3].add(1);
v[3].add(4);
v[4].add(3);
v[3].add(5);
v[5].add(3);
// Values associated with nodes
val[1] = 2;
val[2] = 3;
val[3] = 4;
val[4] = 8;
val[5] = 16;
int queries[] = { 2, 3, 1 };
int q = queries.length;
// Function call
findGCD(queries, q);
}
}
// This code is contributed by shikhasingrajput
C#
# Python3 program to find GCD
# of each subtree for a
# given node by Q queries
# Maximum number of nodes
N = 10**5 + 5
# Tree represented
# as adjacency list
v = [[] for i in range(N)]
# For storing value
# associates with node
val = [0] * (N)
# For storing GCD
# of every subarray
answer = [0] * (N)
# Number of nodes
n = 0
# Function to find GCD of two
# numbers. Using Euclidean algo
def gcd(a, b):
# If b == 0 then
# simply return a
if (b == 0):
return a
return gcd(b, a % b)
# DFS function to traverse the tree
def DFS(node, parent):
# Initializing answer
# with GCD of this node.
answer[node] = val[node]
# Iterate over each
# child of current node
for child in v[node]:
# Skipping the parent
if (child == parent):
continue
# Call DFS for each child
DFS(child, node)
# Taking GCD of the answer
# of the child to
# find node's GCD
answer[node] = gcd(answer[node],
answer[child])
# Calling DFS from the root (1)
# for precomputing answers
def preprocess():
DFS(1, -1)
# Function to find and
# prGCD for Q queries
def findGCD(queries, q):
# Doing preprocessing
preprocess()
# Iterate over each given query
for i in range(q):
GCD = answer[queries[i]]
print("For subtree of ", queries[i],
", GCD = ", GCD)
# Driver code
if __name__ == '__main__':
"""
Tree:
1 (2)
/ \
2 (3) 3 (4)
/ \
4 (8) 5 (16)
"""
n = 5
# Making a undirected tree
v[1].append(2)
v[2].append(1)
v[1].append(3)
v[3].append(1)
v[3].append(4)
v[4].append(3)
v[3].append(5)
v[5].append(3)
# Values associated with nodes
val[1] = 2
val[2] = 3
val[3] = 4
val[4] = 8
val[5] = 16
queries = [2, 3, 1]
q = len(queries)
# Function call
findGCD(queries, q)
# This code is contributed by mohit kumar 29
Javascript
// C# program to find GCD
// of each subtree for
// a given node by Q queries
using System;
using System.Collections.Generic;
public class GFG {
// Maximum Number of nodes
static int N = (int)(1e5 + 5);
// Tree represented
// as adjacency list
static List[] v = new List[ N ];
// For storing value
// associates with node
static int[] val = new int[N];
// For storing GCD
// of every subarray
static int[] answer = new int[N];
// Number of nodes
static int n;
// Function to find GCD of
// two numbers using
// Euclidean algo
static int gcd(int a, int b)
{
// If b == 0
// then simply return a
if (b == 0)
return a;
return gcd(b, a % b);
}
// DFS function to traverse
// the tree
static void DFS(int node, int parent)
{
// Initializing answer
// with GCD of this node.
answer[node] = val[node];
// Iterate over each
// child of current node
foreach(int child in v[node])
{
// Skipping the parent
if (child == parent)
continue;
// Call DFS for each child
DFS(child, node);
// Taking GCD of the answer
// of the child to
// find node's GCD
answer[node] = gcd(answer[node], answer[child]);
}
}
// Calling DFS from the root (1)
// for precomputing answers
static void preprocess() { DFS(1, -1); }
// Function to find and
// print GCD for Q queries
static void findGCD(int[] queries, int q)
{
// Doing preprocessing
preprocess();
// iterate over each given query
for (int i = 0; i < q; i++) {
int GCD = answer[queries[i]];
Console.Write("For subtree of " + queries[i]
+ ", GCD = " + GCD + "\n");
}
}
// Driver code
public static void Main(String[] args)
{
/*
Tree:
1 (2)
/ \
2 (3) 3 (4)
/ \
4 (8) 5 (16)
*/
n = 5;
for (int i = 0; i < v.Length; i++)
v[i] = new List();
// Making a undirected tree
v[1].Add(2);
v[2].Add(1);
v[1].Add(3);
v[3].Add(1);
v[3].Add(4);
v[4].Add(3);
v[3].Add(5);
v[5].Add(3);
// Values associated with nodes
val[1] = 2;
val[2] = 3;
val[3] = 4;
val[4] = 8;
val[5] = 16;
int[] queries = { 2, 3, 1 };
int q = queries.Length;
findGCD(queries, q);
}
}
// This code is contributed by Amit Katiyar
输出
时间复杂度: O(N + Q)
空间复杂度: O(N)