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 :
// 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 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.. |
# 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# 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 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 |
<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> |
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 :
// 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 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. |
# 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# 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. |
<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> |
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)