Skip to content
Related Articles
Get the best out of our app
GeeksforGeeks App
Open App
geeksforgeeks
Browser
Continue

Related Articles

Queries to calculate GCD of an array after multiplying first or last K elements by X

Improve Article
Save Article
Like Article
Improve Article
Save Article
Like Article

Given an array arr[] consisting of N positive integers and a 2D array queries[][] of the type {a, K, X} such that if the value of a is 1, then multiply first K array elements by X. Otherwise, multiply last K array elements by X. The task is to calculate GCD of the array after performing each query on the original array.

Examples:

Input: arr[] = {2, 3, 4, 8}, Queries[][3] = {{1, 2, 2}, {2, 4, 5}}
Output: 2 5
Explanation:
Query 1: The given query is {1, 2, 2}. After multiplying the first 2 array elements by 2, arr[] modifies to {4, 6, 4, 8}. GCD of the modified array is 2.
Query 2: The given query is {2, 4, 5}. After multiplying the last 4 elements array elements by 5, arr[] modifies to {10, 15, 20, 40}. GCD of the updated array is 5.

Input: arr[] = {4, 12, 4, 9}, Queries[][3] = {{1, 3, 3}, {2, 4, 1}}
Output: 3 1

Naive Approach: The simplest approach is to update the given array by performing each query and then find the GCD of the updated array.

Time Complexity: O(N * Q * log(M)), where M is the maximum element present in the array.
Auxiliary Space: O(N)

Efficient Approach: The above approach can be optimized by storing the prefix and suffix GCD arrays of the given array and solving each query in O(1) time by following the below steps:

  • Initialize an array prefix[] and suffix[] of size N to store the prefix and suffix GCD arrays of the given array.
  • Traverse the array from the front and the back and find the prefix and suffix GCD at each index and store it in prefix[] and suffix[] respectively.
  • Now, traverse the array queries[] and for each query {a, K, X} perform the following:
    • If the value of K is N then print the value of prefix[N – 1] * X as the result.
    • If the value of a is 1, then find the GCD of prefix[K – 1] * X and suffix[K] as the result as the prefix[K – 1] * X is the new GCD of first K numbers and suffix[K + 1] is the GCD of the remaining array elements.
    • If the value of a is 2, then find the GCD of prefix[N – K – 1] and suffix[N – K] * X as the result as the prefix[N – K – 1] * X is the new GCD of first K numbers and suffix[N – K] is the GCD of the remaining array elements.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the GCD after performing
// each query on array elements
void findGCDQueries(int arr[], int N,
                    int Queries[][3],
                    int Q)
{
    // Stores prefix array and suffix
    // array
    int prefix[N], suffix[N];
 
    prefix[0] = arr[0];
    suffix[N - 1] = arr[N - 1];
 
    // Build prefix array
    for (int i = 1; i < N; i++) {
        prefix[i] = __gcd(prefix[i - 1],
                          arr[i]);
    }
 
    // Build suffix array
    for (int i = N - 2; i >= 0; i--) {
        suffix[i] = __gcd(suffix[i + 1],
                          arr[i]);
    }
 
    // Traverse queries array
    for (int i = 0; i < Q; i++) {
 
        int a = Queries[i][0];
        int K = Queries[i][1];
        int X = Queries[i][2];
 
        // Edge Case when update is
        // is required till the end
        if (K == N) {
            cout << prefix[N - 1] * X;
            continue;
        }
 
        // Edge Case when update is
        // is required till the front
        if (a == 1) {
            cout << __gcd(prefix[K - 1] * X,
                          suffix[K]);
        }
 
        // Find the resultant operation
        // for each query
        else {
            cout << __gcd(suffix[N - K] * X,
                          prefix[N - K - 1]);
        }
 
        cout << " ";
    }
}
 
// Driver Code
int main()
{
    int arr[] = { 2, 3, 4, 8 };
    int N = sizeof(arr) / sizeof(arr[0]);
    int Queries[][3] = {
        { 1, 2, 2 },
        { 2, 4, 5 }
    };
    int Q = sizeof(Queries)
            / sizeof(Queries[0]);
 
    findGCDQueries(arr, N, Queries, Q);
 
    return 0;
}

Java




// Java program to implement
// the above approach
import java.io.*;
import java.util.*;
 
class GFG
{
 
  // Recursive function to return gcd of a and b
  static int gcd(int a, int b)
  {
 
    // Everything divides 0
    if (a == 0)
      return b;
    if (b == 0)
      return a;
 
    // base case
    if (a == b)
      return a;
 
    // a is greater
    if (a > b)
      return gcd(a - b, b);
    return gcd(a, b - a);
  }
 
 
  // Function to find the GCD after performing
  // each query on array elements
  static void findGCDQueries(int arr[], int N,
                             int Queries[][],
                             int Q)
  {
 
    // Stores prefix array and suffix
    // array
    int prefix[] = new int[N], suffix[] = new int[N];
 
    prefix[0] = arr[0];
    suffix[N - 1] = arr[N - 1];
 
    // Build prefix array
    for (int i = 1; i < N; i++) {
      prefix[i] = gcd(prefix[i - 1],
                      arr[i]);
    }
 
    // Build suffix array
    for (int i = N - 2; i >= 0; i--) {
      suffix[i] = gcd(suffix[i + 1],
                      arr[i]);
    }
 
    // Traverse queries array
    for (int i = 0; i < Q; i++) {
 
      int a = Queries[i][0];
      int K = Queries[i][1];
      int X = Queries[i][2];
 
      // Edge Case when update is
      // is required till the end
      if (K == N) {
        System.out.print(prefix[N - 1] * X);
        continue;
      }
 
      // Edge Case when update is
      // is required till the front
      if (a == 1) {
        System.out.print(gcd(prefix[K - 1] * X,
                             suffix[K]));
      }
 
      // Find the resultant operation
      // for each query
      else {
        System.out.print(gcd(suffix[N - K] * X,
                             prefix[N - K - 1]));
      }
 
      System.out.print(" ");
    }
  }
   
  // Driver Code
  public static void main(String[] args)
  {
 
    int arr[] = { 2, 3, 4, 8 };
    int N = arr.length;
    int Queries[][] = {
      { 1, 2, 2 },
      { 2, 4, 5 }
    };
    int Q = Queries.length;
 
    findGCDQueries(arr, N, Queries, Q);
  }
}
 
// This code is contributed by sanjoy_62.

Python3




# Python 3 program for the above approach
from math import gcd
 
# Function to find the GCD after performing
# each query on array elements
def findGCDQueries(arr, N, Queries, Q):
   
    # Stores prefix array and suffix
    # array
    prefix = [0 for i in range(N)]
    suffix = [0 for i in range(N)]
 
    prefix[0] = arr[0]
    suffix[N - 1] = arr[N - 1]
 
    # Build prefix array
    for i in range(1,N,1):
        prefix[i] = gcd(prefix[i - 1], arr[i])
 
    # Build suffix array
    i = N - 2
    while(i>= 0):
        suffix[i] = gcd(suffix[i + 1], arr[i])
        i -= 1
 
    # Traverse queries array
    for i in range(Q):
        a = Queries[i][0]
        K = Queries[i][1]
        X = Queries[i][2]
 
        # Edge Case when update is
        # is required till the end
        if (K == N):
            print(prefix[N - 1] * X,end = " ")
            continue
 
        # Edge Case when update is
        # is required till the front
        if (a == 1):
            print(gcd(prefix[K - 1] * X,suffix[K]),end = " ")
 
        # Find the resultant operation
        # for each query
        else:
            print(gcd(suffix[N - K] * X, prefix[N - K - 1]),end = " ")
 
# Driver Code
if __name__ == '__main__':
    arr =  [2, 3, 4, 8]
    N = len(arr)
    Queries = [[1, 2, 2], [2, 4, 5]]
    Q = len(Queries)
    findGCDQueries(arr, N, Queries, Q)
     
    # This code is contributed by SURENDRA_GANGWAR.

C#




// C# program to implement
// the above approach
using System;
public class GFG
{
 
  // Recursive function to return gcd of a and b
  static int gcd(int a, int b)
  {
 
    // Everything divides 0
    if (a == 0)
      return b;
    if (b == 0)
      return a;
 
    // base case
    if (a == b)
      return a;
 
    // a is greater
    if (a > b)
      return gcd(a - b, b);
    return gcd(a, b - a);
  }
 
  // Function to find the GCD after performing
  // each query on array elements
  static void findGCDQueries(int []arr, int N,
                             int [,]Queries,
                             int Q)
  {
 
    // Stores prefix array and suffix
    // array
    int []prefix = new int[N];
    int []suffix = new int[N];
 
    prefix[0] = arr[0];
    suffix[N - 1] = arr[N - 1];
 
    // Build prefix array
    for (int i = 1; i < N; i++) {
      prefix[i] = gcd(prefix[i - 1],
                      arr[i]);
    }
 
    // Build suffix array
    for (int i = N - 2; i >= 0; i--) {
      suffix[i] = gcd(suffix[i + 1],
                      arr[i]);
    }
 
    // Traverse queries array
    for (int i = 0; i < Q; i++) {
 
      int a = Queries[i,0];
      int K = Queries[i,1];
      int X = Queries[i,2];
 
      // Edge Case when update is
      // is required till the end
      if (K == N) {
        Console.Write(prefix[N - 1] * X);
        continue;
      }
 
      // Edge Case when update is
      // is required till the front
      if (a == 1) {
        Console.Write(gcd(prefix[K - 1] * X,
                          suffix[K]));
      }
 
      // Find the resultant operation
      // for each query
      else {
        Console.Write(gcd(suffix[N - K] * X,
                          prefix[N - K - 1]));
      }
 
      Console.Write(" ");
    }
  }
 
  // Driver Code
  public static void Main(string[] args)
  {
 
    int []arr = { 2, 3, 4, 8 };
    int N = arr.Length;
    int [,]Queries = {
      { 1, 2, 2 },
      { 2, 4, 5 }
    };
    int Q = Queries.GetLength(0);
 
    findGCDQueries(arr, N, Queries, Q);
  }
}
 
// This code is contributed by AnkThon.

Javascript




<script>
 
    // JavaScript program to implement the above approach
     
    // Recursive function to return gcd of a and b
    function gcd(a, b)
    {
 
      // Everything divides 0
      if (a == 0)
        return b;
      if (b == 0)
        return a;
 
      // base case
      if (a == b)
        return a;
 
      // a is greater
      if (a > b)
        return gcd(a - b, b);
      return gcd(a, b - a);
    }
 
 
    // Function to find the GCD after performing
    // each query on array elements
    function findGCDQueries(arr, N, Queries, Q)
    {
 
      // Stores prefix array and suffix
      // array
      let prefix = new Array(N), suffix = new Array(N);
 
      prefix[0] = arr[0];
      suffix[N - 1] = arr[N - 1];
 
      // Build prefix array
      for (let i = 1; i < N; i++) {
        prefix[i] = gcd(prefix[i - 1],
                        arr[i]);
      }
 
      // Build suffix array
      for (let i = N - 2; i >= 0; i--) {
        suffix[i] = gcd(suffix[i + 1],
                        arr[i]);
      }
 
      // Traverse queries array
      for (let i = 0; i < Q; i++) {
 
        let a = Queries[i][0];
        let K = Queries[i][1];
        let X = Queries[i][2];
 
        // Edge Case when update is
        // is required till the end
        if (K == N) {
          document.write(prefix[N - 1] * X);
          continue;
        }
 
        // Edge Case when update is
        // is required till the front
        if (a == 1) {
          document.write(gcd(prefix[K - 1] * X,
                               suffix[K]));
        }
 
        // Find the resultant operation
        // for each query
        else {
          document.write(gcd(suffix[N - K] * X,
                               prefix[N - K - 1]));
        }
 
        document.write(" ");
      }
    }
     
    let arr = [ 2, 3, 4, 8 ];
    let N = arr.length;
    let Queries = [
      [ 1, 2, 2 ],
      [ 2, 4, 5 ]
    ];
    let Q = Queries.length;
  
    findGCDQueries(arr, N, Queries, Q);
   
</script>

Output

2 5

Time Complexity: O((N + Q)* log M), where M is the maximum element of the array.
Auxiliary Space: O(N)


My Personal Notes arrow_drop_up
Last Updated : 06 Aug, 2021
Like Article
Save Article
Similar Reads
Related Tutorials