Open In App

Count elements which divide all numbers in range L-R

Improve
Improve
Like Article
Like
Save
Share
Report

The problem statement describes a scenario where we are given an array of N numbers and Q queries. Each query consists of two integers L and R, representing a range of indices in the array. The task is to find the count of numbers in the array that divide all the numbers in the range L-R.

Examples : 

Input : a = {3, 4, 2, 2, 4, 6} 
        Q = 2
        L = 1 R = 4  
        L = 2 R = 6
Output :  0
          2 
Explanation : The range 1-4 has {3, 4, 2, 2} 
which does not have any number that divides all the 
numbers in this range. 
The range 2-6 has {4, 2, 2, 4, 6} which has  2 numbers {2, 2} which divides 
all numbers in the given range. 

Input: a = {1, 2, 3, 5} 
       Q = 2 
       L = 1 R = 4 
       L = 2 R = 4 
Output: 1 
        0      

Naive approach : Iterate from range L-R for every query and check if the given element at index-i divide all the numbers in the range. We keep a count for of all the elements which divides all the numbers. The complexity of every query at worst case will be O(n2).

Below is the implementation of Naive Approach :  

C++




// CPP program to Count elements which
// divides all numbers in range L-R
#include <bits/stdc++.h>
using namespace std;
 
// function to count element
// Time complexity O(n^2) worst case
int answerQuery(int a[], int n,
                int l, int r)
{
    // answer for query
    int count = 0;
 
    // 0 based index
    l = l - 1;
 
    // iterate for all elements
    for (int i = l; i < r; i++)
    {
        int element = a[i];
        int divisors = 0;
 
        // check if the element divides
        // all numbers in range
        for (int j = l; j < r; j++)
        {
            // no of elements
            if (a[j] % a[i] == 0)
                divisors++;
            else
                break;
        }
         
        // if all elements are divisible by a[i]
        if (divisors == (r - l))
            count++;
    }
 
    // answer for every query
    return count;
}
 
// Driver Code
int main()
{
    int a[] = { 1, 2, 3, 5 };
    int n = sizeof(a) / sizeof(a[0]);
 
    int l = 1, r = 4;
    cout << answerQuery(a, n, l, r) << endl;
 
    l = 2, r = 4;   
    cout << answerQuery(a, n, l, r) << endl;
    return 0;
}


Java




// Java program to Count elements which
// divides all numbers in range L-R
import java.io.*;
 
class GFG
{
 
// function to count element
// Time complexity O(n^2) worst case
static int answerQuery(int a[], int n,
                       int l, int r)
{
    // answer for query
    int count = 0;
 
    // 0 based index
    l = l - 1;
 
    // iterate for all elements
    for (int i = l; i < r; i++)
    {
        int element = a[i];
        int divisors = 0;
 
        // check if the element divides
        // all numbers in range
        for (int j = l; j < r; j++)
        {
            // no of elements
            if (a[j] % a[i] == 0)
                divisors++;
            else
                break;
        }
         
        // if all elements are divisible by a[i]
        if (divisors == (r - l))
            count++;
    }
 
    // answer for every query
    return count;
}
 
// Driver Code
public static void main (String[] args)
{
    int a[] = { 1, 2, 3, 5 };
    int n = a.length;
     
    int l = 1, r = 4;
    System.out.println( answerQuery(a, n, l, r));
     
    l = 2; r = 4;
    System.out.println( answerQuery(a, n, l, r));
}
}
 
// This code is contributed by anuj_67..


Python3




# Python 3 program to Count elements which
# divides all numbers in range L-R
 
# function to count element
# Time complexity O(n^2) worst case
def answerQuery(a, n, l, r):
     
    # answer for query
    count = 0
 
    # 0 based index
    l = l - 1
 
    # iterate for all elements
    for i in range(l, r, 1):
        element = a[i]
        divisors = 0
 
        # check if the element divides
        # all numbers in range
        for j in range(l, r, 1):
             
            # no of elements
            if (a[j] % a[i] == 0):
                divisors += 1
            else:
                break
         
        # if all elements are divisible
        # by a[i]
        if (divisors == (r - l)):
            count += 1
 
    # answer for every query
    return count
 
# Driver Code
if __name__ =='__main__':
    a = [1, 2, 3, 5]
    n = len(a)
 
    l = 1
    r = 4
    print(answerQuery(a, n, l, r))
 
    l = 2
    r = 4
    print(answerQuery(a, n, l, r))
 
# This code is contributed by
# Shashank_Sharma


C#




// C# program to Count elements which
// divides all numbers in range L-R
using System;
 
class GFG
{
 
// function to count element
// Time complexity O(n^2) worst case
static int answerQuery(int []a, int n,
                       int l, int r)
{
    // answer for query
    int count = 0;
 
    // 0 based index
    l = l - 1;
 
    // iterate for all elements
    for (int i = l; i < r; i++)
    {
        //int element = a[i];
        int divisors = 0;
 
        // check if the element divides
        // all numbers in range
        for (int j = l; j < r; j++)
        {
            // no of elements
            if (a[j] % a[i] == 0)
                divisors++;
            else
                break;
        }
         
        // if all elements are divisible by a[i]
        if (divisors == (r - l))
            count++;
    }
 
    // answer for every query
    return count;
}
 
// Driver Code
public static void Main ()
{
    int []a = { 1, 2, 3, 5 };
    int n = a.Length;
     
    int l = 1, r = 4;
    Console.WriteLine(answerQuery(a, n, l, r));
     
    l = 2; r = 4;
    Console.WriteLine(answerQuery(a, n, l, r));
}
}
 
// This code is contributed by anuj_67..


PHP




<?php
// PHP program to Count elements which
// divides all numbers in range L-R
 
// function to count element
// Time complexity O(n^2) worst case
function answerQuery($a, $n, $l, $r)
{
    // answer for query
    $count = 0;
 
    // 0 based index
    $l = $l - 1;
 
    // iterate for all elements
    for ($i = $l; $i < $r; $i++)
    {
        $element = $a[$i];
        $divisors = 0;
 
        // check if the element divides
        // all numbers in range
        for ($j = $l; $j < $r; $j++)
        {
            // no of elements
            if ($a[$j] % $a[$i] == 0)
                $divisors++;
            else
                break;
        }
         
        // if all elements are divisible by a[i]
        if ($divisors == ($r - $l))
            $count++;
    }
 
    // answer for every query
    return $count;
}
 
// Driver Code
$a = array(1, 2, 3, 5);
$n = sizeof($a);
 
$l = 1; $r = 4;
echo answerQuery($a, $n, $l, $r) . "\n";
 
$l = 2; $r = 4;
echo answerQuery($a, $n, $l, $r) . "\n";
 
// This code is contributed
// by Akanksha Rai


Javascript




<script>
// javascript program to Count elements which
// divides all numbers in range L-R
 
    // function to count element
    // Time complexity O(n^2) worst case
    function answerQuery(a , n , l , r)
    {
     
        // answer for query
        var count = 0;
 
        // 0 based index
        l = l - 1;
 
        // iterate for all elements
        for (i = l; i < r; i++) {
            var element = a[i];
            var divisors = 0;
 
            // check if the element divides
            // all numbers in range
            for (j = l; j < r; j++) {
                // no of elements
                if (a[j] % a[i] == 0)
                    divisors++;
                else
                    break;
            }
 
            // if all elements are divisible by a[i]
            if (divisors == (r - l))
                count++;
        }
 
        // answer for every query
        return count;
    }
 
    // Driver Code
        var a = [ 1, 2, 3, 5 ];
        var n = a.length;
 
        var l = 1, r = 4;
        document.write(answerQuery(a, n, l, r)+"<br/>");
 
        l = 2;
        r = 4;
        document.write(answerQuery(a, n, l, r));
 
// This code is contributed by gauravrajput1
</script>


Output

1
0

Time Complexity:-The time complexity of the given Java program is O(n^2) in the worst case, where n is the length of the input array. This is because the program has two nested loops, each iterating over the input array, resulting in a time complexity of O(n^2) for the worst case.

Space Complexity:-The space complexity of the program is O(1), which means that the amount of memory used by the program is constant, regardless of the input size. This is because the program only uses a fixed amount of memory for storing variables and does not create any new data structures or objects that grow in size with the input size.

Efficient approach : 

Use Segment Trees to solve this problem. If an element divides all the numbers in a given range, then the element is the minimum number in that range and it is the gcd of all elements in the given range L-R. So the count of the number of minimums in range L-R, given that minimum is equal to the gcd of that range will be our answer to every query. The problem boils down to finding the GCD, MINIMUM and countMINIMUM for every range using Segment trees. On every node of the tree, three values are stored. 

On querying for a given range, if the gcd and minimum of the given range are equal, countMINIMUM is returned as the answer. If they are unequal, 0 is returned as the answer.

Below is the implementation of efficient approach : 

C++




// CPP program to Count elements
// which divides all numbers in
// range L-R efficient approach
#include <bits/stdc++.h>
using namespace std;
 
#define N 100005
 
// predefines the tree with nodes
// storing gcd, min and count
struct node
{
    int gcd;
    int min;
    int cnt;
} tree[5 * N];
 
// function to construct the tree
void buildtree(int low, int high,
               int pos, int a[])
{
    // base condition
    if (low == high)
    {
        // initially always gcd and min
        // are same at leaf node
        tree[pos].min =  tree[pos].gcd = a[low];
        tree[pos].cnt = 1;
         
        return;
    }
 
    int mid = (low + high) >> 1;
     
    // left-subtree
    buildtree(low, mid, 2 * pos + 1, a);
 
    // right-subtree
    buildtree(mid + 1, high, 2 * pos + 2, a);
 
    // finds gcd of left and right subtree
    tree[pos].gcd = __gcd(tree[2 * pos + 1].gcd,
                      tree[2 * pos + 2].gcd);
 
    // left subtree has the minimum element
    if (tree[2 * pos + 1].min < tree[2 * pos + 2].min)
    {
        tree[pos].min = tree[2 * pos + 1].min;
        tree[pos].cnt = tree[2 * pos + 1].cnt;
    }
     
    // right subtree has the minimum element
    else
    if (tree[2 * pos + 1].min > tree[2 * pos + 2].min)
    {
        tree[pos].min = tree[2 * pos + 2].min;
        tree[pos].cnt = tree[2 * pos + 2].cnt;
    }
     
    // both subtree has the same minimum element
    else
    {
        tree[pos].min = tree[2 * pos + 1].min;
        tree[pos].cnt = tree[2 * pos + 1].cnt +
                        tree[2 * pos + 2].cnt;
    }
}
 
// function that answers every query
node query(int s, int e, int low, int high, int pos)
{
    node dummy;
     
    // out of range
    if (e < low or s > high)
    {
        dummy.gcd = dummy.min = dummy.cnt = 0;
        return dummy;
    }
     
    // in range
    if (s >= low and e <= high)
    {
        node dummy;
        dummy.gcd = tree[pos].gcd;
        dummy.min = tree[pos].min;
        if (dummy.gcd != dummy.min)
            dummy.cnt = 0;
        else
            dummy.cnt = tree[pos].cnt;
         
        return dummy;
    }
 
    int mid = (s + e) >> 1;
     
    // left-subtree
    node ans1 = query(s, mid, low,
                high, 2 * pos + 1);
     
    // right-subtree
    node ans2 = query(mid + 1, e, low,
                   high, 2 * pos + 2);
 
    node ans;
     
    // when both left subtree and
    // right subtree is in range
    if (ans1.gcd and ans2.gcd)
    {
        // merge two trees
        ans.gcd = __gcd(ans1.gcd, ans2.gcd);
        ans.min = min(ans1.min, ans2.min);
 
        // when gcd is not equal to min
        if (ans.gcd != ans.min)        
            ans.cnt = 0;       
        else
        {
            // add count when min is
            // same of both subtree
            if (ans1.min == ans2.min)            
                ans.cnt = ans2.cnt + ans1.cnt;           
             
            // store the minimal's count
            else
            if (ans1.min < ans2.min)            
                ans.cnt = ans1.cnt;           
            else            
                ans.cnt = ans2.cnt;           
        }
         
        return ans;
    }
     
    // only left subtree is in range
    else if (ans1.gcd)
        return ans1;
     
    // only right subtree is in range
    else if (ans2.gcd)
        return ans2;
}
 
// function to answer query in range l-r
int answerQuery(int a[], int n, int l, int r)
{
    // calls the function which returns
    // a node this function returns the
    // count which will be the answer
    return query(0, n - 1, l - 1, r - 1, 0).cnt;
}
 
// Driver Code
int main()
{
    int a[] = { 3, 4, 2, 2, 4, 6 };
 
    int n = sizeof(a) / sizeof(a[0]);
    buildtree(0, n - 1, 0, a);
    int l = 1, r = 4;
 
    // answers 1-st query
    cout << answerQuery(a, n, l, r) << endl;
 
    l = 2, r = 6;
    // answers 2nd query
    cout << answerQuery(a, n, l, r) << endl;
    return 0;
}


Java




// Java program to Count elements which divides all numbers
// in range L-R efficient approach
import java.io.*;
 
// predefines the tree with nodes storing gcd, min and count
class Node {
  int gcd;
  int min;
  int cnt;
}
 
class GFG {
 
  static final int N = 100005;
  static Node[] tree = new Node[5 * N];
 
  // function to construct the tree
  static void buildtree(int low, int high, int pos,
                        int[] a)
  {
    // base condition
    if (low == high) {
      // initially always gcd and min
      // are same at leaf node
      tree[pos] = new Node();
      tree[pos].min = tree[pos].gcd = a[low];
      tree[pos].cnt = 1;
      return;
    }
 
    int mid = (low + high) >> 1;
 
    // left-subtree
    buildtree(low, mid, 2 * pos + 1, a);
 
    // right-subtree
    buildtree(mid + 1, high, 2 * pos + 2, a);
 
    // finds gcd of left and right subtree
    tree[pos] = new Node();
    tree[pos].gcd = gcd(tree[2 * pos + 1].gcd,
                        tree[2 * pos + 2].gcd);
 
    // left subtree has the minimum element
    if (tree[2 * pos + 1].min < tree[2 * pos + 2].min) {
      tree[pos].min = tree[2 * pos + 1].min;
      tree[pos].cnt = tree[2 * pos + 1].cnt;
    }
 
    // right subtree has the minimum element
    else if (tree[2 * pos + 1].min
             > tree[2 * pos + 2].min) {
      tree[pos].min = tree[2 * pos + 2].min;
      tree[pos].cnt = tree[2 * pos + 2].cnt;
    }
 
    // both subtree has the same minimum element
    else {
      tree[pos].min = tree[2 * pos + 1].min;
      tree[pos].cnt = tree[2 * pos + 1].cnt
        + tree[2 * pos + 2].cnt;
    }
  }
 
  // Helper function to calculate GCD of two integers
  static int gcd(int a, int b)
  {
    return b == 0 ? a : gcd(b, a % b);
  }
 
  // Function that answers every query
  static Node query(int s, int e, int low, int high,
                    int pos, Node[] tree)
  {
    Node dummy = new Node();
 
    // out of range
    if (e < low || s > high) {
      dummy.gcd = dummy.min = dummy.cnt = 0;
      return dummy;
    }
 
    // in range
    if (s >= low && e <= high) {
      Node result = new Node();
      result.gcd = tree[pos].gcd;
      result.min = tree[pos].min;
      if (result.gcd != result.min)
        result.cnt = 0;
      else
        result.cnt = tree[pos].cnt;
 
      return result;
    }
 
    int mid = (s + e) >> 1;
 
    // left-subtree
    Node ans1
      = query(s, mid, low, high, 2 * pos + 1, tree);
 
    // right-subtree
    Node ans2 = query(mid + 1, e, low, high,
                      2 * pos + 2, tree);
 
    Node ans = new Node();
 
    // when both left subtree and right subtree is in
    // range
    if (ans1.gcd != 0 && ans2.gcd != 0) {
      // merge two trees
      ans.gcd = gcd(ans1.gcd, ans2.gcd);
      ans.min = Math.min(ans1.min, ans2.min);
 
      // when gcd is not equal to min
      if (ans.gcd != ans.min)
        ans.cnt = 0;
      else {
        // add count when min is same of both
        // subtree
        if (ans1.min == ans2.min)
          ans.cnt = ans2.cnt + ans1.cnt;
        // store the minimal's count
        else if (ans1.min < ans2.min)
          ans.cnt = ans1.cnt;
        else
          ans.cnt = ans2.cnt;
      }
 
      return ans;
    }
 
    // only left subtree is in range
    else if (ans1.gcd != 0)
      return ans1;
 
    // only right subtree is in range
    else if (ans2.gcd != 0)
      return ans2;
 
    return dummy;
  }
 
  // function to answer query in range l-r
  static int answerQuery(int[] a, int n, int l, int r,
                         Node[] tree)
  {
    // calls the function which returns a node this
    // function returns the count which will be the
    // answer
    return query(0, n - 1, l - 1, r - 1, 0, tree).cnt;
  }
 
  public static void main(String[] args)
  {
    int a[] = { 3, 4, 2, 2, 4, 6 };
 
    int n = a.length;
    buildtree(0, n - 1, 0, a);
    int l = 1, r = 4;
 
    // answers 1-st query
    System.out.println(answerQuery(a, n, l, r, tree));
 
    l = 2;
    r = 6;
    // answers 2nd query
    System.out.println(answerQuery(a, n, l, r, tree));
  }
}
 
// This code is contributed by sankar.


Python3




# Python program to count elements which divide all numbers
# in range L-R efficient approach
 
# predefines the tree with nodes storing gcd, min and count
class Node:
    def __init__(self):
        self.gcd = 0
        self.min = 0
        self.cnt = 0
 
 
def buildtree(low, high, pos, a, tree):
    # base condition
    if low == high:
        # initially always gcd and min are same at leaf node
        tree[pos] = Node()
        tree[pos].min = tree[pos].gcd = a[low]
        tree[pos].cnt = 1
        return
 
    mid = (low + high) >> 1
 
    # left-subtree
    buildtree(low, mid, 2 * pos + 1, a, tree)
 
    # right-subtree
    buildtree(mid + 1, high, 2 * pos + 2, a, tree)
 
    # finds gcd of left and right subtree
    tree[pos] = Node()
    tree[pos].gcd = gcd(tree[2 * pos + 1].gcd, tree[2 * pos + 2].gcd)
 
    # left subtree has the minimum element
    if tree[2 * pos + 1].min < tree[2 * pos + 2].min:
        tree[pos].min = tree[2 * pos + 1].min
        tree[pos].cnt = tree[2 * pos + 1].cnt
 
    # right subtree has the minimum element
    elif tree[2 * pos + 1].min > tree[2 * pos + 2].min:
        tree[pos].min = tree[2 * pos + 2].min
        tree[pos].cnt = tree[2 * pos + 2].cnt
 
    # both subtree has the same minimum element
    else:
        tree[pos].min = tree[2 * pos + 1].min
        tree[pos].cnt = tree[2 * pos + 1].cnt + tree[2 * pos + 2].cnt
 
# Helper function to calculate GCD of two integers
def gcd(a, b):
    return a if b == 0 else gcd(b, a % b)
 
# Function that answers every query
def query(s, e, low, high, pos, tree):
    dummy = Node()
 
    # out of range
    if e < low or s > high:
        dummy.gcd = dummy.min = dummy.cnt = 0
        return dummy
 
    # in range
    if s >= low and e <= high:
        result = Node()
        result.gcd = tree[pos].gcd
        result.min = tree[pos].min
        if result.gcd != result.min:
            result.cnt = 0
        else:
            result.cnt = tree[pos].cnt
        return result
 
    mid = (s + e) >> 1
 
    # left-subtree
    ans1 = query(s, mid, low, high, 2 * pos + 1, tree)
 
    # right-subtree
    ans2 = query(mid + 1, e, low, high, 2 * pos + 2, tree)
 
    ans = Node()
 
    # when both left subtree and right subtree is in range
    if ans1.gcd != 0 and ans2.gcd != 0:
        # merge two trees
        ans.gcd = gcd(ans1.gcd, ans2.gcd)
        ans.min = min(ans1.min, ans2.min)
 
        # when gcd is not equal to min
        if ans.gcd != ans.min:
            ans.cnt = 0
        else:
            # add count when min is same of both subtree
            if ans1.min == ans2.min:
                ans.cnt = ans2.cnt + ans1.cnt
            # store the minimal's count
            elif ans1.min < ans2.min:
                ans.cnt = ans1.cnt
            else:
                ans.cnt = ans2.cnt
 
        return ans
 
    # only left subtree is in range
    elif ans1.gcd != 0:
        return ans1
 
    # only right subtree is in range
    elif ans2.gcd != 0:
        return ans2
 
    return dummy
 
# Function to answer query in range l-r
def answerQuery(a, n, l, r, tree):
    # calls the function which returns a node this function
    # returns the count which will be the answer
    return query(0, n - 1, l - 1, r - 1, 0, tree).cnt
 
 
a = [3, 4, 2, 2, 4, 6]
 
n = len(a)
tree = [None] * (5 * n)
buildtree(0, n - 1, 0, a, tree)
l, r = 1, 4
 
# answers 1st query
print(answerQuery(a, n, l, r, tree))
 
l, r = 2, 6
# answers 2nd query
print(answerQuery(a, n, l, r, tree))
 
# This code is contributed by karthik.


C#




// C# program to Count elements which divides all numbers in
// range L-R efficient approach
 
using System;
 
// predefines the tree with nodes storing gcd, min and count
public class Node {
    public int gcd;
    public int min;
    public int cnt;
}
 
public class GFG {
 
    static int N = 100005;
    static Node[] tree = new Node[5 * N];
 
    // function to construct the tree
    static void buildtree(int low, int high, int pos,
                          int[] a)
    {
        // base condition
        if (low == high) {
            // initially always gcd and min
            // are same at leaf node
            tree[pos] = new Node();
            tree[pos].min = tree[pos].gcd = a[low];
            tree[pos].cnt = 1;
            return;
        }
 
        int mid = (low + high) >> 1;
 
        // left-subtree
        buildtree(low, mid, 2 * pos + 1, a);
 
        // right-subtree
        buildtree(mid + 1, high, 2 * pos + 2, a);
 
        // finds gcd of left and right subtree
        tree[pos] = new Node();
        tree[pos].gcd = gcd(tree[2 * pos + 1].gcd,
                            tree[2 * pos + 2].gcd);
 
        // left subtree has the minimum element
        if (tree[2 * pos + 1].min < tree[2 * pos + 2].min) {
            tree[pos].min = tree[2 * pos + 1].min;
            tree[pos].cnt = tree[2 * pos + 1].cnt;
        }
 
        // right subtree has the minimum element
        else if (tree[2 * pos + 1].min
                 > tree[2 * pos + 2].min) {
            tree[pos].min = tree[2 * pos + 2].min;
            tree[pos].cnt = tree[2 * pos + 2].cnt;
        }
 
        // both subtree has the same minimum element
        else {
            tree[pos].min = tree[2 * pos + 1].min;
            tree[pos].cnt = tree[2 * pos + 1].cnt
                            + tree[2 * pos + 2].cnt;
        }
    }
 
    // Helper function to calculate GCD of two integers
    static int gcd(int a, int b)
    {
        return b == 0 ? a : gcd(b, a % b);
    }
 
    // Function that answers every query
    static Node query(int s, int e, int low, int high,
                      int pos, Node[] tree)
    {
        Node dummy = new Node();
 
        // out of range
        if (e < low || s > high) {
            dummy.gcd = dummy.min = dummy.cnt = 0;
            return dummy;
        }
 
        // in range
        if (s >= low && e <= high) {
            Node result = new Node();
            result.gcd = tree[pos].gcd;
            result.min = tree[pos].min;
            if (result.gcd != result.min)
                result.cnt = 0;
            else
                result.cnt = tree[pos].cnt;
 
            return result;
        }
 
        int mid = (s + e) >> 1;
 
        // left-subtree
        Node ans1
            = query(s, mid, low, high, 2 * pos + 1, tree);
 
        // right-subtree
        Node ans2 = query(mid + 1, e, low, high,
                          2 * pos + 2, tree);
 
        Node ans = new Node();
 
        // when both left subtree and right subtree is in
        // range
        if (ans1.gcd != 0 && ans2.gcd != 0) {
            // merge two trees
            ans.gcd = gcd(ans1.gcd, ans2.gcd);
            ans.min = Math.Min(ans1.min, ans2.min);
 
            // when gcd is not equal to min
            if (ans.gcd != ans.min)
                ans.cnt = 0;
            else {
                // add count when min is same of both
                // subtree
                if (ans1.min == ans2.min)
                    ans.cnt = ans2.cnt + ans1.cnt;
                // store the minimal's count
                else if (ans1.min < ans2.min)
                    ans.cnt = ans1.cnt;
                else
                    ans.cnt = ans2.cnt;
            }
 
            return ans;
        }
 
        // only left subtree is in range
        else if (ans1.gcd != 0)
            return ans1;
 
        // only right subtree is in range
        else if (ans2.gcd != 0)
            return ans2;
 
        return dummy;
    }
 
    // function to answer query in range l-r
    static int answerQuery(int[] a, int n, int l, int r,
                           Node[] tree)
    {
        // calls the function which returns a node this
        // function returns the count which will be the
        // answer
        return query(0, n - 1, l - 1, r - 1, 0, tree).cnt;
    }
 
    static public void Main()
    {
 
        // Code
        int[] a = { 3, 4, 2, 2, 4, 6 };
 
        int n = a.Length;
        buildtree(0, n - 1, 0, a);
        int l = 1, r = 4;
 
        // answers 1-st query
        Console.WriteLine(answerQuery(a, n, l, r, tree));
 
        l = 2;
        r = 6;
        // answers 2nd query
        Console.WriteLine(answerQuery(a, n, l, r, tree));
    }
}
 
// This code is contributed by karthik.


Javascript




<script>
 
// JavaScript program to Count elements which divides
// all numbers in range L-R efficient approach
 
// predefines the tree with nodes storing gcd, min and count
class Node {
  constructor() {
    this.gcd = 0;
    this.min = 0;
    this.cnt = 0;
  }
}
 
const N = 100005;
const tree = new Array(5 * N).fill(null).map(() => new Node());
 
// function to construct the tree
function buildtree(low, high, pos, a) {
  // base condition
  if (low == high) {
    // initially always gcd and min are same at leaf node
    tree[pos].min = tree[pos].gcd = a[low];
    tree[pos].cnt = 1;
    return;
  }
 
  const mid = (low + high) >> 1;
 
  // left-subtree
  buildtree(low, mid, 2 * pos + 1, a);
 
  // right-subtree
  buildtree(mid + 1, high, 2 * pos + 2, a);
 
  // finds gcd of left and right subtree
  tree[pos] = new Node();
  tree[pos].gcd = gcd(tree[2 * pos + 1].gcd, tree[2 * pos + 2].gcd);
 
  // left subtree has the minimum element
  if (tree[2 * pos + 1].min < tree[2 * pos + 2].min) {
    tree[pos].min = tree[2 * pos + 1].min;
    tree[pos].cnt = tree[2 * pos + 1].cnt;
  }
 
  // right subtree has the minimum element
  else if (tree[2 * pos + 1].min > tree[2 * pos + 2].min) {
    tree[pos].min = tree[2 * pos + 2].min;
    tree[pos].cnt = tree[2 * pos + 2].cnt;
  }
 
  // both subtree has the same minimum element
  else {
    tree[pos].min = tree[2 * pos + 1].min;
    tree[pos].cnt = tree[2 * pos + 1].cnt + tree[2 * pos + 2].cnt;
  }
}
 
// Helper function to calculate GCD of two integers
function gcd(a, b) {
  return b == 0 ? a : gcd(b, a % b);
}
 
// Function that answers every query
function query(s, e, low, high, pos) {
  const dummy = new Node();
 
  // out of range
  if (e < low || s > high) {
    dummy.gcd = dummy.min = dummy.cnt = 0;
    return dummy;
  }
 
  // in range
  if (s >= low && e <= high) {
    const result = new Node();
    result.gcd = tree[pos].gcd;
    result.min = tree[pos].min;
    if (result.gcd != result.min) result.cnt = 0;
    else result.cnt = tree[pos].cnt;
 
    return result;
  }
 
  const mid = (s + e) >> 1;
 
  // left-subtree
  const ans1 = query(s, mid, low, high, 2 * pos + 1);
 
  // right-subtree
  const ans2 = query(mid + 1, e, low, high, 2 * pos + 2);
 
  const ans = new Node();
 
  // when both left subtree and right subtree is in range
  if (ans1.gcd != 0 && ans2.gcd != 0) {
    // merge two trees
    ans.gcd = gcd(ans1.gcd, ans2.gcd);
    ans.min = Math.min(ans1.min, ans2.min);
     
    // when gcd is not equal to min
    if (ans.gcd != ans.min) {
        ans.cnt = 0;
    }
    else {
        // add count when min is same of both subtree
        if (ans1.min === ans2.min) {
            ans.cnt = ans2.cnt + ans1.cnt;
        }
        // store the minimal's count
        else if (ans1.min < ans2.min) {
            ans.cnt = ans1.cnt;
        }
        else {
            ans.cnt = ans2.cnt;
        }
    }
     
    return ans;
  }
   
  // only left subtree is in range.
  else if (ans1.gcd != 0) {
    return ans1;
  }
   
  // only right subtree is in range
  else if (ans2.gcd != 0) {
    return ans2;
  }
   
  return dummy;
}
 
// function to answer query in range l-r
function answerQuery(a, n, l, r, tree) {
  // Calls the function which returns a node this function
  // returns the count which will be the answer.
  return query(0, n-1, l-1, r-1, 0, tree).cnt;
}
 
var a = [3, 4, 2, 2, 4, 6];
var n = a.length;
buildtree(0, n-1, 0, a);
var l = 1, r = 4;
 
// answers 1st query
document.write(answerQuery(a, n, l, r, tree) + "<br>");
 
l = 2;
r = 6;
// answers 2nd query
document.write(answerQuery(a, n, l, r, tree));
 
// This code is contributed by karthik.
 
</script>


Output

0
2

Time Complexity: Time Complexity for tree construction is O(n logn) since tree construction takes O(n) and finding out gcd takes O(log n). The time taken for every query in worst case will be O(log n * log n) since the inbuilt function __gcd takes O(log n)

Space Complexity: O(n)



Last Updated : 27 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads