Open In App

Find the number of colored nodes according to given queries in a full Binary Tree

Last Updated : 12 Dec, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Consider a full Binary Tree where the root of the Tree is colored as Black initially. Each black-colored node will have red children, and red-colored nodes will have black children. You are given two integer arrays Start[] and End[]. Along with Start[] and End[], there is a Query[] array of size Q with the values:

  • Interchange: Interchange the color of all nodes, i.e. black nodes into red and red nodes into black.
  • Black: Output the number of Black nodes between the nodes Start and End.
  • Red: Output the number of Red nodes between the nodes Start and End.

Examples:

Input: Query[] = {“Black”, “Interchange”, “Red”}, Start[] = {1, 0, 3}, End[] = {5, 0, 8}
Output: First Query=2, Third Query=2
Explanation:

  • Query[0]=Black, Start[0]=1, End[0] = 5. Means we have to count of total number of Black nodes in the path from node 1 to 5.
  • First Query:

      case1

      First Test Case

    • Query[1]=Interchange. Means, we just have to interchange the color of all nodes. No output will be there for this query.
    • Second Query:

        case2

        Second Test Case

      • Third Query:
        • Query[2]=Red, Start[2]=3, End[2]=8. Means we have to count of total number of Red nodes in the path from node 3 to 8.

        case3

        Third Test Case

      Input: Query[] = {“Black”, “Interchange”, “Red”}, Start[] = {1, 0, 8}, End[] = {5, 0, 15}
      Output: First Query=2, Third Query=3
      Explanation: It can be verified that the number of colored nodes in each query will be same as output.

      Approach: Implement the idea below to solve the problem

      The problem is based on the concept of Lowest Common Ancestor (LCA). Suppose, if two nodes are in different branch like node 9 and node 11, they are child of node 4 and node 5. So, we have to find a common ground for both the nodes which is the LCA (2 for above nodes) .

      Therefore, we just need to

      • Calculate total number of nodes (Black or Red according to query type) from the root to both the nodes
      • Subtract the number of nodes (Black or Red) from root to LCA as these nodes are were counted twice.
      • Also, we have to add 1 to the answer if the LCA node has the same color as it was not counted before.

      Steps to solve the problem:

      • Create a boolean variable rootBlack and mark it initially as true.
      • Create a function getBlackNodes(x, y) to return the total number of black nodes between x and y, if root is black.
      • Create a function getRedNodes(x, y) to return the total number of red nodes between x and y, if root is black.
      • For each Query[i],
        • If (Query[i] == “Interchange”), then rootBlack = !rootBlack
        • Else If (Query[i] == “Black”)
          • If root is black, it means that we currently have the original binary tree, so return getBlackNodes(start[i], end[i])
          • else if root is not black, it means that we currently have the interchanged binary tree, so return getRedNodes(start[i], end[i])
        • Else
          • If root is black, it means that we currently have the original binary tree, so return getRedNodes(start[i], end[i])
          • else if root is not black, it means that we currently have the interchanged binary tree, so return getBlackNodes(start[i], end[i])

      Code to implement the approach:

      C++




      #include <iostream>
      #include <cmath>
       
      using namespace std;
       
      // Function to find the Lowest Common Ancestor (LCA) of two nodes
      long findLca(long x, long y) {
          while (x != y) {
              if (x > y)
                  x /= 2;
              else if (y > x)
                  y /= 2;
          }
          return x;
      }
      // Function to calculate the height of a node in the tree
      long height(long n) {
          return (log2(n) + 1);
      }
      // Function to calculate the black height of a node
      long blackHeight(long n) {
          return (height(n) + 1) / 2;
      }
       
      // Function to calculate the red height of a node
      long redHeight(long n) {
          return height(n) / 2;
      }
       
       
      // Function to calculate the number of black nodes between two nodes
      long getBlackNodes(long x, long y) {
          long lca = findLca(x, y);
          long ans = blackHeight(x) + blackHeight(y) - 2 * blackHeight(height(lca));
          return (height(lca) % 2 == 1) ? ans + 1 : ans;
      }
       
      // Function to calculate the number of red nodes between two nodes
      long getRedNodes(long x, long y) {
          long lca = findLca(x, y);
          long ans = redHeight(x) + redHeight(y) - 2 * redHeight(lca);
          return (height(lca) % 2 == 0) ? ans + 1 : ans;
      }
       
      // Function to process queries and print the results
      void Function(string Query[], int start[], int end[], int n) {
          bool rootBlack = true;
       
          for (int i = 0; i < n; i++) {
              long ans = 0;
              if (Query[i] == "Interchange")
                  rootBlack = !rootBlack;
              else if ((rootBlack && Query[i] == "Black") || (!rootBlack && Query[i] == "Red"))
                  ans = getBlackNodes(start[i], end[i]);
              else
                  ans = getRedNodes(start[i], end[i]);
       
              cout << ans << endl;
          }
      }
       
      int main() {
          string Query[] = { "Black", "Interchange", "Red" };
          int start[] = { 1, 0, 3 };
          int end[] = { 5, 0, 8 };
          int n = 3;
       
          // Function call
          Function(Query, start, end, n);
       
          return 0;
      }

      
      

      Java




      import java.io.*;
      import java.lang.*;
      import java.util.*;
       
      class Main {
          public static void main(String[] args)
              throws java.lang.Exception
          {
              // Inputs
              String[] Query = { "Black", "Interchange", "Red" };
              int[] start = { 1, 0, 3 };
              int[] end = { 5, 0, 8 };
       
              // Function call
              Function(Query, start, end);
          }
       
          // Method to print output of query asked
          public static void Function(String[] Query, int[] start,
                                      int[] end)
          {
       
              // Initially root Black is marked
              // as true
              boolean rootBlack = true;
       
              // Loop for processing queries
              for (int i = 0; i < Query.length; i++) {
                  long ans = 0;
                  if (Query[i].equals("Interchange"))
                      rootBlack = !rootBlack;
       
                  // Root is black and we need to count
                  // the number of black nodes or Root
                  // is red and we need to count the
                  // number of red nodes
                  else if ((rootBlack && Query[i].equals("Black"))
                           || (!rootBlack
                               && Query[i].equals("Red")))
                      ans = getBlackNodes(start[i], end[i]);
       
                  // Root is black and we need to count
                  // the number of red nodes or Root is
                  // red and we need to count the number
                  // of black nodes
                  else
                      ans = getRedNodes(start[i], end[i]);
       
                  System.out.println(ans);
              }
          }
       
          // Function to return the LCA of
          // start and end
          static long findLca(long x, long y)
          {
              while (x != y) {
                  if (x > y)
                      x /= 2;
                  else if (y > x)
                      y /= 2;
              }
              return x;
          }
       
          // Function to return the black height of n
          static long blackHeight(long n)
          {
              return (height(n) + 1) / 2;
          }
       
          // Function to return the red height of n
          static long redHeight(long n) { return height(n) / 2; }
       
          // Function to return the height
          static long height(long n)
          {
              return (long)(Math.log(n) / Math.log(2)) + 1;
          }
       
          // Static function to return black nodes
          // between 2 nodes
          static long getBlackNodes(long x, long y)
          {
              long lca = findLca(x, y);
              long ans = blackHeight(x) + blackHeight(y)
                         - 2 * blackHeight(height(lca));
              return (height(lca) % 2 == 1) ? ans + 1 : ans;
          }
       
          // Static function to return red nodes
          // between 2 nodes
          static long getRedNodes(long x, long y)
          {
              long lca = findLca(x, y);
              long ans = redHeight(x) + redHeight(y)
                         - 2 * redHeight(lca);
              return (height(lca) % 2 == 0) ? ans + 1 : ans;
          }
      }

      
      

      Python3




      # Python Code
       
      import math
       
      # Function to find the Lowest Common Ancestor (LCA) of two nodes
      def find_lca(x, y):
          while x != y:
              if x > y:
                  x //= 2
              elif y > x:
                  y //= 2
          return x
       
      # Function to calculate the height of a node in the tree
      def height(n):
          return int(math.log2(n) + 1)
       
      # Function to calculate the black height of a node
      def black_height(n):
          return (height(n) + 1) // 2
       
      # Function to calculate the red height of a node
      def red_height(n):
          return height(n) // 2
       
      # Function to calculate the number of black nodes between two nodes
      def get_black_nodes(x, y):
          lca = find_lca(x, y)
          ans = black_height(x) + black_height(y) - 2 * black_height(height(lca))
          return ans + 1 if height(lca) % 2 == 1 else ans
       
      # Function to calculate the number of red nodes between two nodes
      def get_red_nodes(x, y):
          lca = find_lca(x, y)
          ans = red_height(x) + red_height(y) - 2 * red_height(lca)
          return ans + 1 if height(lca) % 2 == 0 else ans
       
      # Function to process queries and print the results
      def function(query, start, end, n):
          root_black = True
       
          for i in range(n):
              ans = 0
              if query[i] == "Interchange":
                  root_black = not root_black
              elif (root_black and query[i] == "Black") or (not root_black and query[i] == "Red"):
                  ans = get_black_nodes(start[i], end[i])
              else:
                  ans = get_red_nodes(start[i], end[i])
       
              print(ans)
       
      if __name__ == "__main__":
          query = ["Black", "Interchange", "Red"]
          start = [1, 0, 3]
          end = [5, 0, 8]
          n = 3
       
          # Function call
          function(query, start, end, n)
       
      # This code is contributed by guptapratik

      
      

      C#




      // C# Implementation
       
      using System;
       
      namespace LCA
      {
          class Program
          {
              // Function to find the Lowest Common Ancestor (LCA) of two nodes
              static long FindLca(long x, long y)
              {
                  while (x != y)
                  {
                      if (x > y)
                          x /= 2;
                      else if (y > x)
                          y /= 2;
                  }
                  return x;
              }
       
              // Function to calculate the height of a node in the tree
              static long Height(long n)
              {
                  return (long)(Math.Log(n, 2) + 1);
              }
       
              // Function to calculate the black height of a node
              static long BlackHeight(long n)
              {
                  return (Height(n) + 1) / 2;
              }
       
              // Function to calculate the red height of a node
              static long RedHeight(long n)
              {
                  return Height(n) / 2;
              }
       
              // Function to calculate the number of black nodes between two nodes
              static long GetBlackNodes(long x, long y)
              {
                  long lca = FindLca(x, y);
                  long ans = BlackHeight(x) + BlackHeight(y) - 2 * BlackHeight(Height(lca));
                  return (Height(lca) % 2 == 1) ? ans + 1 : ans;
              }
       
              // Function to calculate the number of red nodes between two nodes
              static long GetRedNodes(long x, long y)
              {
                  long lca = FindLca(x, y);
                  long ans = RedHeight(x) + RedHeight(y) - 2 * RedHeight(lca);
                  return (Height(lca) % 2 == 0) ? ans + 1 : ans;
              }
       
              // Function to process queries and print the results
              static void Function(string[] query, int[] start, int[] end, int n)
              {
                  bool rootBlack = true;
       
                  for (int i = 0; i < n; i++)
                  {
                      long ans = 0;
                      if (query[i] == "Interchange")
                          rootBlack = !rootBlack;
                      else if ((rootBlack && query[i] == "Black") || (!rootBlack && query[i] == "Red"))
                          ans = GetBlackNodes(start[i], end[i]);
                      else
                          ans = GetRedNodes(start[i], end[i]);
       
                      Console.WriteLine(ans);
                  }
              }
       
              static void Main(string[] args)
              {
                  string[] query = { "Black", "Interchange", "Red" };
                  int[] start = { 1, 0, 3 };
                  int[] end = { 5, 0, 8 };
                  int n = 3;
       
                  // Function call
                  Function(query, start, end, n);
              }
          }
      }
       
      // This code is contributed by Sakshi

      
      

      Javascript




      function find(x, y) {
          while (x !== y) {
              if (x > y)
                  x = Math.floor(x / 2);
              else if (y > x)
                  y = Math.floor(y / 2);
          }
          return x;
      }
      // Function to calculate the height of
      // node in the tree
      function height(n) {
          return Math.floor(Math.log2(n) + 1);
      }
      // Function to calculate the black height of node
      function blackHeight(n) {
          return Math.floor((height(n) + 1) / 2);
      }
      // Function to calculate the red height of node
      function redHeight(n) {
          return Math.floor(height(n) / 2);
      }
      // Function to calculate the number of the black nodes between two nodes
      function getBlackNodes(x, y) {
          const lca = find(x, y);
          let ans = blackHeight(x) + blackHeight(y) - 2 * blackHeight(height(lca));
          return (height(lca) % 2 === 1) ? ans + 1 : ans;
      }
      // Function to calculate the number of the red nodes between two nodes
      function getRedNodes(x, y) {
          const lca = find(x, y);
          let ans = redHeight(x) + redHeight(y) - 2 * redHeight(lca);
          return (height(lca) % 2 === 0) ? ans + 1 : ans;
      }
      // Function to process queries and print the results
      function GFG(queries, start, end) {
          let rootBlack = true;
          for (let i = 0; i < queries.length; i++) {
              let ans = 0;
              if (queries[i] === "Interchange")
                  rootBlack = !rootBlack;
              else if ((rootBlack && queries[i] === "Black") || (!rootBlack && queries[i] === "Red"))
                  ans = getBlackNodes(start[i], end[i]);
              else
                  ans = getRedNodes(start[i], end[i]);
              console.log(ans);
          }
      }
      // Main function
      function main() {
          const queries = ["Black", "Interchange", "Red"];
          const start = [1, 0, 3];
          const end = [5, 0, 8];
          const n = 3;
          // Function call
          GFG(queries, start, end, n);
      }
      // Call the main function
      main();

      
      

      Output

      2
      0
      2
      
      
      
      
      
      
      
      
      
      
      
      
      

      Time Complexity: O(Query.length * (log(x) + log(y)), where x and y are the values of start and end array
      Auxiliary Space: O(1)



      Like Article
      Suggest improvement
      Share your thoughts in the comments

      Similar Reads