CSES Solutions - Company Queries II
Last Updated : 14 Jun, 2024
A company has n employees, who form a tree hierarchy where each employee has a boss, except for the general director. Your task is to process q queries of the form: who is the lowest common boss of employees a and b in the hierarchy?
The employees are numbered 1,2,…,n, and employee 1 is the general director. The array arr[] has n−1 integers e2,e3,…,en: for each employee 2,3,…,n their boss. Finally, there are q queries, each query has two integers a and b: who is the lowest common boss of employees a and b?
Examples:
Input: n = 5, q = 3, arr[] = {1, 1, 3, 3}, queries[][] = {{4, 5}, {2, 5}, {1, 4}}
Output:
3
1
1
Explanation:
- Lowest Common Boss of 4 and 5 is 3.
- Lowest Common Boss of 2 and 5 is 1.
- Lowest Common Boss of 1 and 4 is 1.
Input: n = 10, q = 3, arr[] = {1, 1, 1, 1, 2, 3, 4, 4, 1}, queries[][] = {{1, 8}, {2, 7}, {8, 3}}
Output:
1
1
1
Explanation:
- Lowest Common Boss of 1 and 8 is 1.
- Lowest Common Boss of 2 and 7 is 1.
- Lowest Common Boss of 8 and 3 is 1.
Approach: To solve the problem, follow the below idea:
The problem can be solved using Binary Lifting Technique. We can construct the LCA table, such that LCA[i][j] stores the (2^j)th ancestor of node i. In order to fill the first column of LCA table, update the first column of each node i with immediate boss of node i. To fill the remaining columns, we can use the formula: LCA[i][j] = LCA[LCA[i][j - 1]][j - 1]. After filling the LCA[][] table completely, we can answer each query in logN time using Binary Lifting.
Step-by-step algorithm:
- Run a Depth-First-Search to find the depth of all the nodes.
- Fill the first column for every node i with the immediate boss of node i.
- Fill the remaining columns with the formula: LCA[i][j] = LCA[LCA[i][j - 1]][j - 1].
- To answer each query,
- Find the difference in depth of both the nodes.
- From the deeper node, use the LCA[][] table to make jumps in upward direction till both the nodes reach the same depth.
- After reaching the same depth, make jumps from both nodes till their ancestors are different.
- When the ancestor becomes same, return the ancestor node.
Below is the implementation of the algorithm:
C++ #include <bits/stdc++.h> using namespace std; const int MAXN = 200000; const int LOG = 18; // because 2^18 > 200000 vector<int> adj[MAXN + 1]; // adjacency list of the tree int LCA[MAXN + 1] [LOG]; // LCA[i][j] stores the 2^j-th ancestor of i int depth[MAXN + 1]; // depth of each node // DFS to find the depth of all the nodes and initialize the // LCA table void dfs(int v, int p) { LCA[v][0] = p; // Fill the LCA table for (int i = 1; i < LOG; ++i) { if (LCA[v][i - 1] != -1) { LCA[v][i] = LCA[LCA[v][i - 1]][i - 1]; } else { LCA[v][i] = -1; } } // Explore the neoghboring nodes for (int u : adj[v]) { if (u != p) { depth[u] = depth[v] + 1; dfs(u, v); } } } // function to find the LCA of node a and b int lca(int a, int b) { if (depth[a] < depth[b]) { swap(a, b); } int diff = depth[a] - depth[b]; for (int i = 0; i < LOG; ++i) { if ((diff >> i) & 1) { a = LCA[a][i]; } } if (a == b) { return a; } for (int i = LOG - 1; i >= 0; --i) { if (LCA[a][i] != LCA[b][i]) { a = LCA[a][i]; b = LCA[b][i]; } } return LCA[a][0]; } int main() { int n = 5, q = 3; int arr[] = { 1, 1, 3, 3 }; vector<int> parent(n + 1); vector<vector<int> > queries = { { 4, 5 }, { 2, 5 }, { 1, 4 } }; for (int i = 1; i < n; i++) { parent[i + 1] = arr[i - 1]; } parent[1] = -1; // General director has no boss for (int i = 2; i <= n; ++i) { adj[parent[i]].push_back(i); adj[i].push_back(parent[i]); } depth[1] = 0; dfs(1, -1); for (int i = 0; i < q; ++i) { int a = queries[i][0], b = queries[i][1]; cout << lca(a, b) << endl; } return 0; }
Java import java.util.*; public class LCAFinder { static final int MAXN = 200000; static final int LOG = 18; // because 2^18 > 200000 static List<Integer>[] adj = new ArrayList[MAXN + 1]; static int[][] LCA = new int[MAXN + 1][LOG]; static int[] depth = new int[MAXN + 1]; // DFS to find the depth of all the nodes and initialize // the LCA table static void dfs(int v, int p) { LCA[v][0] = p; // Fill the LCA table for (int i = 1; i < LOG; ++i) { if (LCA[v][i - 1] != -1) { LCA[v][i] = LCA[LCA[v][i - 1]][i - 1]; } else { LCA[v][i] = -1; } } // Explore the neighboring nodes for (int u : adj[v]) { if (u != p) { depth[u] = depth[v] + 1; dfs(u, v); } } } // function to find the LCA of node a and b static int lca(int a, int b) { if (depth[a] < depth[b]) { int temp = a; a = b; b = temp; } int diff = depth[a] - depth[b]; for (int i = 0; i < LOG; ++i) { if ((diff >> i & 1) == 1) { a = LCA[a][i]; } } if (a == b) { return a; } for (int i = LOG - 1; i >= 0; --i) { if (LCA[a][i] != LCA[b][i]) { a = LCA[a][i]; b = LCA[b][i]; } } return LCA[a][0]; } public static void main(String[] args) { int n = 5, q = 3; int[] arr = { 1, 1, 3, 3 }; int[] parent = new int[n + 1]; List<int[]> queries = Arrays.asList( new int[] { 4, 5 }, new int[] { 2, 5 }, new int[] { 1, 4 }); for (int i = 0; i <= MAXN; ++i) { adj[i] = new ArrayList<>(); } for (int i = 1; i < n; i++) { parent[i + 1] = arr[i - 1]; } parent[1] = -1; // General director has no boss for (int i = 2; i <= n; ++i) { adj[parent[i]].add(i); adj[i].add(parent[i]); } depth[1] = 0; dfs(1, -1); for (int[] query : queries) { int a = query[0], b = query[1]; System.out.println(lca(a, b)); } } } // This code is contributed by Shivam Gupta
Time Complexity: O(nlogn + qlogn)
Auxiliary Space: O(nlogn)
Similar Reads
Must Do Questions for Companies like TCS, CTS, HCL, IBM ⦠As the placement season is back so are we to help you ace the interview. We have selected some most commonly asked and must do practice problems for you.You can also take part in our mock placement contests which will help you learn different topics and practice at the same time, simulating the feel
9 min read
Recently Asked Interview Questions in Product Based Companies Cracking interviews at top product-based companies can be challenging, especially with their main focus on problem-solving skills. This article compiles a comprehensive list of interview questions recently asked at leading firms such as Amazon, Microsoft, and Google. Covering a wide range of topics
6 min read
Cognizant SDE Sheet: Interview Questions and Answers Cognizant is an American multinational information technology services and consulting company, headquartered in new jersey, US. It has broadly two units. The vertical units focus on specific industries. This sheet will assist you to land a job at cognizant, we have compiled all the interview questio
7 min read
Oracle Corporation Work Experience Oracle is a multinational technology company providing a set of software and cloud solutions which include, among others, deploying and managing databases, software designed for accounting functions, tools for managing customer relationships, and also cloud infrastructure services. Oracle, started i
3 min read
Paytm Interview Experience | Set 4 (Walk-in Drive) I got a chance to participate in walk-in drive at Paytm Headquarters. Went through the following process. Written test: It contained 20 objective questions having a mix of C, networking and Database questions and 2 subjective questions. Subjective questions: Stock buy sell maximum profit and Find su
2 min read