Queries to update a given index and find gcd in range in C++ Program


In this problem, we are given an array arr[] of size N and Q queries which can be of two types. Our task is to create a program to solve the queries to update a given index and find GCD in the range.

Queries are −

Type 1 − {1, index, value} - increase the element at given index by value.

Type 2 − {2, L, R} - find the GCD of elements in the index range [L, R].

Problem Description − We need to find the GCD of the elements that are in the range [L, R] and return the value.

Let’s take an example to understand the problem,

Input

arr[] = {5, 1, 7, 3, 8}, Q = 3
Queries: {{2, 2 , 5}, {1, 3, 6}, {2, 2, 5}}

Output

Explanation

Solution Approach

An approach to solve the problem is using segment Tree which is used to preprocess the GCD’s for the arrays. This will reduce the time for computing the GCD for each query.

Creating and working with Segment Tree

The segment tree we are using here is a tree that stores the elements of the array as leaf nodes and the GCD of elements as internal nodes .

Program to illustrate the working of our solution,

Example

 Live Demo

#include <bits/stdc++.h>
using namespace std;
int calcGcdRangeRec(int* st, int segL, int segR, int L, int R, int currNode) {
   if (L <= segL && R >= segR)
      return st[currNode];
   if (segR < L || segL > R)
      return 0;
   int mid = (segL + (segR - segL)/2);
   int GcdL = calcGcdRangeRec(st, segL, mid, L, R, 2 * currNode + 1) ;
   int GcdR = calcGcdRangeRec(st, mid + 1, segR, L, R, 2 * currNode + 2);
   return __gcd(GcdL, GcdR);
}
void updateArrayValueRec(int* st, int L, int R, int index, int diff, int currNode) {
   if (index < L || index > R)
      return;
   st[currNode] = st[currNode] + diff;
   if (R != L) {
      int mid = (L + (R - L)/ 2);
      updateArrayValueRec(st, L, mid, index, diff, 2 * currNode + 1);
      updateArrayValueRec(st, mid + 1, R, index, diff, 2 * currNode + 2);
   }
}
void updateArrayValue(int arr[], int* st, int n, int index, int newVal) {
   if (index < 0 || index > n - 1)
      cout << "Invalid Input";
   else{
      int diff = newVal - arr[index];
      arr[index] = newVal;
      updateArrayValueRec(st, 0, n - 1, index, diff, 0);
   }
}
int calcGcdRange(int* st, int n, int L, int R) {
   if (L < 0 || R > n - 1 || L > R) {
      cout << "Invalid Input";
      return -1;
   }
   return calcGcdRangeRec(st, 0, n - 1, L, R, 0);
}
int constructGcdST(int arr[], int L, int R, int* st, int currNode) {
   if (L == R) {
      st[currNode] = arr[L];
      return arr[L];
   }
   int mid = (L + (R - L)/2);
   int GcdL = constructGcdST(arr, L, mid, st, currNode * 2 + 1);
   int GcdR = constructGcdST(arr, mid + 1, R, st, currNode * 2 + 2);
   st[currNode] = __gcd(GcdL, GcdR);
   return st[currNode];
}
int main() {
   int arr[] = { 1, 3, 6, 9, 9, 11 };
   int n = sizeof(arr) / sizeof(arr[0]);
   int Q = 3;
   int query[3][3] = {{2, 1, 3}, {1, 1 , 10}, {2, 1, 3}};
   int value = (int)(ceil(log2(n)));
   int size = 2 * (int)pow(2, value) - 1;
   int* st = new int[size];
   constructGcdST(arr, 0, n - 1, st, 0);
   for(int i = 0; i < n; i++){
      if(query[i][0] == 1){
         cout<<"Query "<<(i + 1)<<": Updating Values!\n";
         updateArrayValue(arr, st, n, query[i][1], query[i][2]);
      }
      if(query[i][0] == 2)
      cout<<"Query "<<(i + 1)<<": GCD is "<<calcGcdRange(st, n, query[i][1], query[i][2])<<endl;
   }
   return 0;
}

Input

Query 1: GCD is 3
Query 2: Updating Values!
Query 3: GCD is 1

Updated on: 22-Dec-2020

138 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements