Open In App

Array range queries to find the maximum Fibonacci number with updates

Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] of N integers, the task is to perform the following two queries: 

  • maximum(start, end): Print the maximum Fibonacci number of elements in the sub-array from start to end
  • update(i, x): Add x to the array element referenced by array index i, that is: arr[i] = x

Note: The below example consists of 0 based indexing.

Example: 

Input: arr = [1, 3, 5, 7, 9, 11] 
Query 1: Maximum (Start = 1, End = 3) 
Query 2: Update (3, 8) i.e. arr[3] = 8
Output: 
Maximum Fibonacci number in given range = 5 
Updated Maximum Fibonacci number in given range = 8
Explanation: 
In the Maximum Query, the sub-array [1…3] 
has 2 Fibonacci 3 and 5 viz. {3, 5, 7} 
Hence, 5 is the maximum Fibonacci number in the given range.
In the Update Query, the value at index 3 is updated 
to 8, the array arr now is, [1, 3, 5, 8, 9, 11]
In Updated Maximum Query, the sub-array [1…3] 
has all 3 Fibonacci numbers 3, 5 and 8 viz. [3, 5, 8] 
Hence, 8 is the maximum Fibonacci number in the given range. 
 

Simple Approach:

A simple solution is to run a loop from l to r and calculate the maximum Fibonacci number out of all the elements in a given range. To update a value, simply do arr[i] = x. The first operation takes O(N*F) time and the second operation takes O(1) time.

Below is the implementation of the above approach : 

C++14




// CPP code for range maximum
// query and updates
#include <bits/stdc++.h>
using namespace std;
 
// Function to calculate the nth
// Fibonacci number
int fib(int n)
{
    if (n <= 1)
        return n;
    return fib(n - 1) + fib(n - 2);
}
 
// Function to get the maximum Fibonacci
// number in the given range
int getMax(int arr[], int n, int l, int r)
{
    int maxFib = -1;
    for (int i = l; i <= r; i++) {
        for (int j = 0; j <= n; j++) {
            int fibNum = fib(j);
            if (fibNum == arr[i]) {
                maxFib = max(maxFib, fibNum);
                break;
            }
            else if (fibNum > arr[i]) {
                break;
            }
        }
    }
    return maxFib;
}
 
// Function to update an array element
void updateValue(int arr[], int i, int x)
{
      arr[i] = x;
}
 
// Driver Code
int main()
{
    int arr[] = { 1, 3, 5, 7, 9, 11 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // Print max of values in array
    // from index 1 to 3
    cout << "Maximum fibonacci number"
         << " in given range = " << getMax(arr, n, 1, 3)
         << endl;
 
    // Update: set arr[1] = 8 and update
    // corresponding segment tree nodes.
    updateValue(arr, 1, 8);
 
    // Find max after the value is updated
    cout << "Updated Maximum Fibonacci"
         << " number in given range = "
         << getMax(arr, n, 1, 3) << endl;
 
    return 0;
}


Java




import java.util.Arrays;
 
public class FibonacciMaxRange {
 
    // Function to calculate the nth Fibonacci number
    static int fib(int n) {
        if (n <= 1)
            return n;
        return fib(n - 1) + fib(n - 2);
    }
 
    // Function to get the maximum Fibonacci number in the given range
    static int getMax(int[] arr, int l, int r) {
        int maxFib = -1;
        for (int i = l; i <= r; i++) {
            for (int j = 0; ; j++) {
                int fibNum = fib(j);
                if (fibNum == arr[i]) {
                    maxFib = Math.max(maxFib, fibNum);
                    break;
                } else if (fibNum > arr[i]) {
                    break;
                }
            }
        }
        return maxFib;
    }
 
    // Function to update an array element
    static void updateValue(int[] arr, int i, int x) {
        arr[i] = x;
    }
 
    public static void main(String[] args) {
        int[] arr = { 1, 3, 5, 7, 9, 11 };
 
        // Print max of values in array from index 1 to 3
        System.out.println("Maximum Fibonacci number in given range = " + getMax(arr, 1, 3));
 
        // Update: set arr[1] = 8
        updateValue(arr, 1, 8);
 
        // Find max after the value is updated
        System.out.println("Updated Maximum Fibonacci number in given range = " + getMax(arr, 1, 3));
    }
}


Python3




# Function to calculate the nth Fibonacci number
def fib(n):
    if n <= 1:
        return n
    a, b = 0, 1
    for _ in range(2, n + 1):
        a, b = b, a + b
    return b
 
# Function to get the maximum Fibonacci number in the given range
def get_max(arr, l, r):
    max_fib = -1
    for i in range(l, r + 1):
        j = 0
        while True:
            fib_num = fib(j)
            if fib_num == arr[i]:
                max_fib = max(max_fib, fib_num)
                break
            elif fib_num > arr[i]:
                break
            j += 1
    return max_fib
 
# Function to update an array element
def update_value(arr, i, x):
    arr[i] = x
 
arr = [1, 3, 5, 7, 9, 11]
 
# Print max of values in array from index 1 to 3
print("Maximum Fibonacci number in given range =", get_max(arr, 1, 3))
 
# Update: set arr[1] = 8
update_value(arr, 1, 8)
 
# Find max after the value is updated
print("Updated Maximum Fibonacci number in given range =", get_max(arr, 1, 3))


C#




using System;
 
class Program {
    // Function to calculate the nth Fibonacci number
    static int Fib(int n) {
        if (n <= 1) {
            return n;
        }
        return Fib(n - 1) + Fib(n - 2);
    }
 
    // Function to get the maximum Fibonacci number in the given range
    static int GetMax(int[] arr, int n, int l, int r) {
        int maxFib = -1;
        for (int i = l; i <= r; i++) {
            for (int j = 0; j <= n; j++) {
                int fibNum = Fib(j);
                if (fibNum == arr[i]) {
                    maxFib = Math.Max(maxFib, fibNum);
                    break;
                } else if (fibNum > arr[i]) {
                    break;
                }
            }
        }
        return maxFib;
    }
 
    // Function to update an array element
    static void UpdateValue(int[] arr, int i, int x) {
        arr[i] = x;
    }
 
    static void Main() {
        int[] arr = { 1, 3, 5, 7, 9, 11 };
        int n = arr.Length;
 
        // Print max of values in array from index 1 to 3
        Console.WriteLine("Maximum Fibonacci number in given range: " + GetMax(arr, n, 1, 3));
 
        // Update: set arr[1] = 8 and update corresponding array element
        UpdateValue(arr, 1, 8);
 
        // Find max after the value is updated
        Console.WriteLine("Updated Maximum Fibonacci number in given range: " + GetMax(arr, n, 1, 3));
    }
}


Javascript




// JavaScript code for range maximum
// query and updates
 
// Function to calculate the
// nth Fibonacci number
function fib(n) {
    if (n <= 1) {
        return n;
    }
    return fib(n - 1) + fib(n - 2);
}
 
// Function to get the maximum Fibonacci
// number in the given range
function getMax(arr, n, l, r) {
    let maxFib = -1;
    for (let i = l; i <= r; i++) {
        for (let j = 0; j <= n; j++) {
            const fibNum = fib(j);
            if (fibNum === arr[i]) {
                maxFib = Math.max(maxFib, fibNum);
                break;
            }
            else if (fibNum > arr[i]) {
                break;
            }
        }
    }
    return maxFib;
}
 
// Function to update an array element
function updateValue(arr, i, x) {
    arr[i] = x;
}
 
// Driver Code
const arr = [1, 3, 5, 7, 9, 11];
const n = arr.length;
 
// Print max of values in array
// from index 1 to 3
console.log("Maximum fibonacci number in given range = ", getMax(arr, n, 1, 3));
 
// Update: set arr[1] = 8 and update
// corresponding array element
updateValue(arr, 1, 8);
 
// Find max after the value is updated
console.log("Updated Maximum Fibonacci number in given range = ", getMax(arr, n, 1, 3));


Output

Maximum fibonacci number in given range = 5
Updated Maximum Fibonacci number in given range = 8







Time Complexity: O(N * F), where N is the size of the range and F is the maximum Fibonacci number in the range. 
Space Complexity: O(1)

Efficient Approach : 
Here, we need to perform operations in O(Log N) time so we can use Segment Tree to do both operations in O(Log N) time.
Representation of Segment trees:
1. Leaf Nodes are the elements of the input array. 
2. Each internal node represents the maximum Fibonacci number of all of its child nodes or -1 if there is no Fibonacci number existing in the range.
An array representation of tree is used to represent Segment Trees. For each node at index i, the left child is at index 2*i+1, right child at index 2*i+2 and the parent is at index (i-1)/2.
Construction of Segment Tree from given array : 
We start with a segment arr[0 . . . n-1], and every time we divide the current segment into two halves(if it has not yet become a segment of length 1), and then call the same procedure on both halves, and for each such segment, we store the maximum Fibonacci number value or -1 in a segment tree node. All levels of the constructed segment tree will be completely filled except the last level. Also, the tree will be a full Binary Tree because we always divide segments into two halves at every level. Since the constructed tree is always a full binary tree with n leaves, there will be n-1 internal nodes. So total nodes will be 2*n – 1. Height of the segment tree will be log2N. Since the tree is represented using array and relation between parent and child indexes must be maintained, size of memory allocated for segment tree will be 2*( 2ceil(log2n) ) – 1.
In order to check for Fibonacci numbers, we can build a hash table using dynamic programming containing all the Fibonacci numbers less than or equal to the maximum value arr can take say MAX which will be used to test a number in O(1) time.
We then do a range query on the segment tree to find out the max_set_bits for the given range and output the corresponding value.

Below is the implementation of above approach : 
 

CPP




// CPP code for range maximum query and updates
#include <bits/stdc++.h>
using namespace std;
 
set<int> fibonacci;
 
// A utility function to get the
// middle index of given range.
int getMid(int s, int e)
{
    return s + (e - s) / 2;
}
 
// Function to create hash table
// to check Fibonacci numbers
void createHash(int maxElement)
{
    int prev = 0, curr = 1;
    fibonacci.insert(prev);
    fibonacci.insert(curr);
 
    while (curr <= maxElement) {
        int temp = curr + prev;
        fibonacci.insert(temp);
        prev = curr;
        curr = temp;
    }
}
 
/*  A recursive function to get the sum of
    values in given range of the array.
    The following are parameters for this
    function.
 
    st       -> Pointer to segment tree
    node     -> Index of current node in
                the segment tree .
    ss & se  -> Starting and ending indexes
                of the segment represented
                by current node, i.e., st[node]
    l & r    -> Starting and ending indexes
                of range query */
int MaxUtil(int* st, int ss, int se, int l,
            int r, int node)
{
    // If segment of this node is completely
    // part of given range, then return
    // the max of segment
    if (l <= ss && r >= se)
        return st[node];
 
    // If segment of this node does not
    // belong to given range
    if (se < l || ss > r)
        return -1;
 
    // If segment of this node is partially
    // the part of given range
    int mid = getMid(ss, se);
 
    return max(MaxUtil(st, ss, mid, l, r,
                       2 * node + 1),
               MaxUtil(st, mid + 1, se, l,
                       r, 2 * node + 2));
}
 
/* A recursive function to update the nodes which
   have the given index in their range. The following
   are parameters st, ss and se are same as defined
   above index -> index of the element to be updated.*/
void updateValue(int arr[], int* st, int ss, int se,
                 int index, int value, int node)
{
    if (index < ss || index > se) {
        cout << "Invalid Input" << endl;
        return;
    }
 
    if (ss == se) {
        // update value in array and in segment tree
        arr[index] = value;
 
        if (fibonacci.find(value) != fibonacci.end())
            st[node] = value;
        else
            st[node] = -1;
    }
    else {
        int mid = getMid(ss, se);
 
        if (index >= ss && index <= mid)
            updateValue(arr, st, ss, mid, index,
                        value, 2 * node + 1);
        else
            updateValue(arr, st, mid + 1, se,
                        index, value, 2 * node + 2);
 
        st[node] = max(st[2 * node + 1],
                       st[2 * node + 2]);
    }
    return;
}
 
// Return max of elements in range from
// index l (query start) to r (query end).
int getMax(int* st, int n, int l, int r)
{
    // Check for erroneous input values
    if (l < 0 || r > n - 1 || l > r) {
        printf("Invalid Input");
        return -1;
    }
 
    return MaxUtil(st, 0, n - 1, l, r, 0);
}
 
// A recursive function that constructs Segment
// Tree for array[ss..se]. si is index of
// current node in segment tree st
int constructSTUtil(int arr[], int ss, int se,
                    int* st, int si)
{
    // If there is one element in array, store
    // it in current node of segment tree and return
    if (ss == se) {
        if (fibonacci.find(arr[ss])
            != fibonacci.end())
            st[si] = arr[ss];
        else
            st[si] = -1;
        return st[si];
    }
 
    // If there are more than one elements, then
    // recur for left and right subtrees and
    // store the max of values in this node
    int mid = getMid(ss, se);
 
    st[si]
        = max(constructSTUtil(
                  arr, ss, mid, st,
                  si * 2 + 1),
              constructSTUtil(
                  arr, mid + 1, se,
                  st, si * 2 + 2));
 
    return st[si];
}
 
/* Function to construct segment tree
   from given array.
   This function allocates memory
   for segment tree.*/
int* constructST(int arr[], int n)
{
    // Height of segment tree
    int x = (int)(ceil(log2(n)));
 
    // Maximum size of segment tree
    int max_size = 2 * (int)pow(2, x) - 1;
 
    // Allocate memory
    int* st = new int[max_size];
 
    // Fill the allocated memory st
    constructSTUtil(arr, 0, n - 1, st, 0);
 
    // Return the constructed segment tree
    return st;
}
 
// Driver code
int main()
{
    int arr[] = { 1, 3, 5, 7, 9, 11 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // find the largest node value
    // in the array
    int maxEle = *max_element(arr, arr + n);
 
    // creating a set containing
    // all fibonacci numbers
    // upto the maximum data value
    // in the array
    createHash(maxEle);
 
    // Build segment tree from given array
    int* st = constructST(arr, n);
 
    // Print max of values in array
    // from index 1 to 3
    cout << "Maximum fibonacci number"
         << " in given range = "
         << getMax(st, n, 1, 3) << endl;
 
    // Update: set arr[1] = 8 and update
    // corresponding segment tree nodes.
    updateValue(arr, st, 0, n - 1, 3, 8, 0);
 
    // Find max after the value is updated
    cout << "Updated Maximum Fibonacci"
         << " number in given range = "
         << getMax(st, n, 1, 3) << endl;
 
    return 0;
}


Java




// Java code for range maximum query and updates
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
 
class GFG {
 
  static Set<Integer> fibonacci = new HashSet<>();
 
  // A utility function to get the
  // middle index of given range.
  static int getMid(int s, int e) {
    return s + (e - s) / 2;
  }
 
  // Function to create hash table
  // to check Fibonacci numbers
  static void createHash(int maxElement) {
    int prev = 0, curr = 1;
    fibonacci.add(prev);
    fibonacci.add(curr);
 
    while (curr <= maxElement) {
      int temp = curr + prev;
      fibonacci.add(temp);
      prev = curr;
      curr = temp;
    }
  }
 
  /*
     * A recursive function to get the sum of
     * values in given range of the array.
     * The following are parameters for this function.
     *
     * st       -> Pointer to segment tree
     * node     -> Index of current node
     *             in the segment tree .
     * ss & se  -> Starting and ending indexes
     *             of the segment represented
     *             by current node, i.e., st[node]
     * l & r    -> Starting and ending indexes
     *             of range query
     */
  static int MaxUtil(int[] st, int ss, int se,
                     int l, int r, int node)
  {
 
    // If segment of this node is completely
    // part of given range, then return
    // the max of segment
    if (l <= ss && r >= se)
      return st[node];
 
    // If segment of this node does not
    // belong to given range
    if (se < l || ss > r)
      return -1;
 
    // If segment of this node is partially
    // the part of given range
    int mid = getMid(ss, se);
 
    return Math.max(MaxUtil(st, ss, mid, l, r, 2 * node + 1),
                    MaxUtil(st, mid + 1, se, l, r, 2 * node + 2));
  }
 
  /*
     * A recursive function to update the nodes which
     * have the given index in their range. The following
     * are parameters st, ss and se are same as defined
     * above index -> index of the element to be updated.
     */
  static void updateValue(int arr[], int[] st, int ss, int se,
                          int index, int value, int node) {
    if (index < ss || index > se) {
      System.out.println("Invalid Input");
      return;
    }
 
    if (ss == se) {
      // update value in array and in segment tree
      arr[index] = value;
 
      if (fibonacci.contains(value))
        st[node] = value;
      else
        st[node] = -1;
    } else {
      int mid = getMid(ss, se);
 
      if (index >= ss && index <= mid)
        updateValue(arr, st, ss, mid, index,
                    value, 2 * node + 1);
      else
        updateValue(arr, st, mid + 1, se,
                    index, value, 2 * node + 2);
 
      st[node] = Math.max(st[2 * node + 1], st[2 * node + 2]);
    }
    return;
  }
 
  // Return max of elements in range from
  // index l (query start) to r (query end).
  static int getMax(int[] st, int n, int l, int r)
  {
 
    // Check for erroneous input values
    if (l < 0 || r > n - 1 || l > r)
    {
      System.out.printf("Invalid Input\n");
      return -1;
    }
 
    return MaxUtil(st, 0, n - 1, l, r, 0);
  }
 
  // A recursive function that constructs Segment
  // Tree for array[ss..se]. si is index of
  // current node in segment tree st
  static int constructSTUtil(int arr[], int ss, int se,
                             int[] st, int si)
  {
 
    // If there is one element in array, store
    // it in current node of segment tree and return
    if (ss == se) {
      if (fibonacci.contains(arr[ss]))
        st[si] = arr[ss];
      else
        st[si] = -1;
      return st[si];
    }
 
    // If there are more than one elements, then
    // recur for left and right subtrees and
    // store the max of values in this node
    int mid = getMid(ss, se);
 
    st[si] = Math.max(constructSTUtil(arr, ss, mid, st, si * 2 + 1),
                      constructSTUtil(arr, mid + 1, se, st, si * 2 + 2));
 
    return st[si];
  }
 
  /*
     * Function to construct segment tree
     * from given array. This function allocates
     * memory for segment tree.
     */
  static int[] constructST(int arr[], int n)
  {
 
    // Height of segment tree
    int x = (int) (Math.ceil(Math.log(n) / Math.log(2)));
 
    // Maximum size of segment tree
    int max_size = 2 * (int) Math.pow(2, x) - 1;
 
    // Allocate memory
    int[] st = new int[max_size];
 
    // Fill the allocated memory st
    constructSTUtil(arr, 0, n - 1, st, 0);
 
    // Return the constructed segment tree
    return st;
  }
 
  // Driver code
  public static void main(String[] args)
  {
 
    int arr[] = { 1, 3, 5, 7, 9, 11 };
    int n = arr.length;
 
    // find the largest node value
    // in the array
    int maxEle = Arrays.stream(arr).max().getAsInt();
 
    // creating a set containing
    // all fibonacci numbers
    // upto the maximum data value
    // in the array
    createHash(maxEle);
 
    // Build segment tree from given array
    int[] st = constructST(arr, n);
 
    // Print max of values in array
    // from index 1 to 3
    System.out.println("Maximum fibonacci number in given range = " +
                       getMax(st, n, 1, 3));
 
    // Update: set arr[1] = 8 and update
    // corresponding segment tree nodes.
    updateValue(arr, st, 0, n - 1, 3, 8, 0);
 
    // Find max after the value is updated
    System.out.println("Updated Maximum fibonacci number in given range = " +
                       getMax(st, n, 1, 3));
  }
}
 
// This code is contributed by sanjeev2552


Python3




# Python code for range maximum query and updates
import math
fibonacci = set()
 
# A utility function to get the
# middle index of given range.
def get_mid(s, e):
    return s + (e - s) // 2
 
# Function to create hash table
# to check Fibonacci numbers
def create_hash(max_element):
    prev = 0
    curr = 1
    fibonacci.add(prev)
    fibonacci.add(curr)
 
    while curr <= max_element:
        temp = curr + prev
        fibonacci.add(temp)
        prev = curr
        curr = temp
 
'''  A recursive function to get the sum of
    values in given range of the array.
    The following are parameters for this
    function.
 
    st       -> Pointer to segment tree
    node     -> Index of current node in
                the segment tree .
    ss & se  -> Starting and ending indexes
                of the segment represented
                by current node, i.e., st[node]
    l & r    -> Starting and ending indexes
                of range query '''
def max_util(st, ss, se, l, r, node):
    # If segment of this node is completely
    # part of given range, then return
    # the max of segment
    if l <= ss and r >= se:
        return st[node]
 
    # If segment of this node does not
    # belong to given range
    if se < l or ss > r:
        return -1
 
    # If segment of this node is partially
    # the part of given range
    mid = get_mid(ss, se)
 
    return max(max_util(st, ss, mid, l, r,
                        2 * node + 1),
               max_util(st, mid + 1, se, l,
                        r, 2 * node + 2))
 
 
''' A recursive function to update the nodes which
   have the given index in their range. The following
   are parameters st, ss and se are same as defined
   above index -> index of the element to be updated.'''
def update_value(arr, st, ss, se, index, value, node):
    if index < ss or index > se:
        print("Invalid Input")
        return
 
    if ss == se:
        # update value in array and in segment tree
        arr[index] = value
 
        if value in fibonacci:
            st[node] = value
        else:
            st[node] = -1
    else:
        mid = get_mid(ss, se)
 
        if index >= ss and index <= mid:
            update_value(arr, st, ss, mid, index,
                         value, 2 * node + 1)
        else:
            update_value(arr, st, mid + 1, se,
                         index, value, 2 * node + 2)
 
        st[node] = max(st[2 * node + 1], st[2 * node + 2])
    return
 
# Return max of elements in range from
# index l (query start) to r (query end).
def get_max(st, n, l, r):
    # Check for erroneous input values
    if l < 0 or r > n - 1 or l > r:
        print("Invalid Input")
        return -1
 
    return max_util(st, 0, n - 1, l, r, 0)
 
# A recursive function that constructs Segment
# Tree for array[ss..se]. si is index of
# current node in segment tree st
def construct_st_util(arr, ss, se, st, si):
    # If there is one element in array, store
    # it in current node of segment tree and return
    if ss == se:
        if arr[ss] in fibonacci:
            st[si] = arr[ss]
        else:
            st[si] = -1
        return st[si]
 
    # If there are more than one elements, then
    # recur for left and right subtrees and
    # store the max of values in this node
    mid = get_mid(ss, se)
 
    st[si] = max(construct_st_util(
        arr, ss, mid, st, si * 2 + 1),
        construct_st_util(arr, mid + 1, se,
                          st, si * 2 + 2))
 
    return st[si]
 
''' Function to construct segment tree
   from given array.
   This function allocates memory
   for segment tree.'''
def construct_st(arr, n):
    # Height of segment tree
    x = int(math.ceil(math.log2(n)))
 
    # Maximum size of segment tree
    max_size = 2 * (2 ** x) - 1
 
    # Allocate memory
    st = [0] * max_size
 
    # Fill the allocated memory st
    construct_st_util(arr, 0, n - 1, st, 0)
 
    # Return the constructed segment tree
    return st
 
# Driver code
if __name__ == "__main__":
    arr = [1, 3, 5, 7, 9, 11]
    n = len(arr)
 
    # find the largest node value
    # in the array
    max_ele = max(arr)
 
    # creating a set containing
    # all fibonacci numbers
    # upto the maximum data value
    # in the array
    create_hash(max_ele)
 
    # Build segment tree from given array
    st = construct_st(arr, n)
 
    # Print max of values in array
    # from index 1 to 3
    print("Maximum fibonacci number in given range = ",
          get_max(st, n, 1, 3))
 
    # Update: set arr[1] = 8 and update
    # corresponding segment tree nodes.
    update_value(arr, st, 0, n - 1, 3, 8, 0)
 
    # Find max after the value is updated
    print("Updated Maximum Fibonacci number in given range = ",
          get_max(st, n, 1, 3))
     
# This code is contributed by akashish__


C#




// Include namespace system
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections;
 
public class GFG
{
  public static HashSet<int> fibonacci = new HashSet<int>();
 
  // A utility function to get the
  // middle index of given range.
  public static int getMid(int s, int e)
  {
    return s + (int)((e - s) / 2);
  }
 
  // Function to create hash table
  // to check Fibonacci numbers
  public static void createHash(int maxElement)
  {
    var prev = 0;
    var curr = 1;
    fibonacci.Add(prev);
    fibonacci.Add(curr);
    while (curr <= maxElement)
    {
      var temp = curr + prev;
      fibonacci.Add(temp);
      prev = curr;
      curr = temp;
    }
  }
  //     * A recursive function to get the sum of
  //     * values in given range of the array.
  //     * The following are parameters for this function.
  //     *
  //     * st       -> Pointer to segment tree
  //     * node     -> Index of current node
  //     *             in the segment tree .
  //     * ss & se  -> Starting and ending indexes
  //     *             of the segment represented
  //     *             by current node, i.e., st[node]
  //     * l & r    -> Starting and ending indexes
  //     *             of range query
  public static int MaxUtil(int[] st, int ss, int se, int l, int r, int node)
  {
    // If segment of this node is completely
    // part of given range, then return
    // the max of segment
    if (l <= ss && r >= se)
    {
      return st[node];
    }
    // If segment of this node does not
    // belong to given range
    if (se < l || ss > r)
    {
      return -1;
    }
 
    // If segment of this node is partially
    // the part of given range
    var mid = GFG.getMid(ss, se);
    return Math.Max(GFG.MaxUtil(st, ss, mid, l, r, 2 * node + 1),GFG.MaxUtil(st, mid + 1, se, l, r, 2 * node + 2));
  }
 
  //     * A recursive function to update the nodes which
  //     * have the given index in their range. The following
  //     * are parameters st, ss and se are same as defined
  //     * above index -> index of the element to be updated.
  public static void updateValue(int[] arr, int[] st, int ss, int se, int index, int value, int node)
  {
    if (index < ss || index > se)
    {
      Console.WriteLine("Invalid Input");
      return;
    }
    if (ss == se)
    {
 
      // update value in array and in segment tree
      arr[index] = value;
      if (fibonacci.Contains(value))
      {
        st[node] = value;
      }
      else
      {
        st[node] = -1;
      }
    }
    else
    {
      var mid = GFG.getMid(ss, se);
      if (index >= ss && index <= mid)
      {
        GFG.updateValue(arr, st, ss, mid, index, value, 2 * node + 1);
      }
      else
      {
        GFG.updateValue(arr, st, mid + 1, se, index, value, 2 * node + 2);
      }
      st[node] = Math.Max(st[2 * node + 1],st[2 * node + 2]);
    }
    return;
  }
 
  // Return max of elements in range from
  // index l (query start) to r (query end).
  public static int getMax(int[] st, int n, int l, int r)
  {
 
    // Check for erroneous input values
    if (l < 0 || r > n - 1 || l > r)
    {
      Console.Write("Invalid Input\n");
      return -1;
    }
    return GFG.MaxUtil(st, 0, n - 1, l, r, 0);
  }
 
  // A recursive function that constructs Segment
  // Tree for array[ss..se]. si is index of
  // current node in segment tree st
  public static int constructSTUtil(int[] arr, int ss, int se, int[] st, int si)
  {
 
    // If there is one element in array, store
    // it in current node of segment tree and return
    if (ss == se)
    {
      if (fibonacci.Contains(arr[ss]))
      {
        st[si] = arr[ss];
      }
      else
      {
        st[si] = -1;
      }
      return st[si];
    }
 
    // If there are more than one elements, then
    // recur for left and right subtrees and
    // store the max of values in this node
    var mid = GFG.getMid(ss, se);
    st[si] = Math.Max(GFG.constructSTUtil(arr, ss, mid, st, si * 2 + 1),GFG.constructSTUtil(arr, mid + 1, se, st, si * 2 + 2));
    return st[si];
  }
 
  //     * Function to construct segment tree
  //     * from given array. This function allocates
  //     * memory for segment tree.
  public static int[] constructST(int[] arr, int n)
  {
 
    // Height of segment tree
    var x = (int)(Math.Ceiling(Math.Log(n) / Math.Log(2)));
 
    // Maximum size of segment tree
    var max_size = 2 * (int)Math.Pow(2,x) - 1;
 
    // Allocate memory
    int[] st = new int[max_size];
 
    // Fill the allocated memory st
    GFG.constructSTUtil(arr, 0, n - 1, st, 0);
 
    // Return the constructed segment tree
    return st;
  }
 
  // Driver code
  public static void Main(String[] args)
  {
    int[] arr = {1, 3, 5, 7, 9, 11};
    var n = arr.Length;
 
    // find the largest node value
    // in the array
    var maxEle = arr.Max();
 
    // creating a set containing
    // all fibonacci numbers
    // upto the maximum data value
    // in the array
    GFG.createHash(maxEle);
 
    // Build segment tree from given array
    int[] st = GFG.constructST(arr, n);
 
    // Print max of values in array
    // from index 1 to 3
    Console.WriteLine("Maximum fibonacci number in given range = " + GFG.getMax(st, n, 1, 3).ToString());
 
    // Update: set arr[1] = 8 and update
    // corresponding segment tree nodes.
    GFG.updateValue(arr, st, 0, n - 1, 3, 8, 0);
 
    // Find max after the value is updated
    Console.WriteLine("Updated Maximum fibonacci number in given range = " + GFG.getMax(st, n, 1, 3).ToString());
  }
}
 
// This code is contributed by aadityaburujwale.


Javascript




// JavaScript code for range maximum query and updates
 
let fibonacci = new Set();
 
// A utility function to get the
// middle index of given range.
function getMid(s, e)
{
    return s + Math.floor((e - s) / 2);
}
 
// Function to create hash table
// to check Fibonacci numbers
function createHash(maxElement)
{
    let prev = 0;
    let curr = 1;
    fibonacci.add(prev);
    fibonacci.add(curr);
 
    while (curr <= maxElement) {
        let temp = curr + prev;
        fibonacci.add(temp);
        prev = curr;
        curr = temp;
    }
}
 
/*  A recursive function to get the sum of
    values in given range of the array.
    The following are parameters for this
    function.
 
    st       -> Pointer to segment tree
    node     -> Index of current node in
                the segment tree .
    ss & se  -> Starting and ending indexes
                of the segment represented
                by current node, i.e., st[node]
    l & r    -> Starting and ending indexes
                of range query */
function MaxUtil(st, ss, se, l, r, node)
{
    // If segment of this node is completely
    // part of given range, then return
    // the max of segment
    if (l <= ss && r >= se)
        return st[node];
 
    // If segment of this node does not
    // belong to given range
    if (se < l || ss > r)
        return -1;
 
    // If segment of this node is partially
    // the part of given range
    let mid = getMid(ss, se);
 
    return Math.max(MaxUtil(st, ss, mid, l, r, 2 * node + 1),MaxUtil(st, mid + 1, se, l, r, 2 * node + 2));
}
 
/* A recursive function to update the nodes which
   have the given index in their range. The following
   are parameters st, ss and se are same as defined
   above index -> index of the element to be updated.*/
function updateValue(arr, st, ss, se, index, value, node)
{
    if (index < ss || index > se) {
        console.log("Invalid Input");
        return;
    }
 
    if (ss == se) {
        // update value in array and in segment tree
        arr[index] = value;
 
        if (fibonacci.has(value))
            st[node] = value;
        else
            st[node] = -1;
    }
    else {
        let mid = getMid(ss, se);
 
        if (index >= ss && index <= mid)
            updateValue(arr, st, ss, mid, index, value, 2 * node + 1);
        else
            updateValue(arr, st, mid + 1, se, index, value, 2 * node + 2);
 
        st[node] = Math.max(st[2 * node + 1], st[2 * node + 2]);
    }
    return;
}
 
// Return max of elements in range from
// index l (query start) to r (query end).
function getMax(st, n, l, r)
{
    // Check for erroneous input values
    if (l < 0 || r > n - 1 || l > r) {
        console.log("Invalid Input");
        return -1;
    }
 
    return MaxUtil(st, 0, n - 1, l, r, 0);
}
 
// A recursive function that constructs Segment
// Tree for array[ss..se]. si is index of
// current node in segment tree st
function constructSTUtil(arr, ss, se, st, si)
{
    // If there is one element in array, store
    // it in current node of segment tree and return
    if (ss == se) {
        if (fibonacci.has(arr[ss]))
            st[si] = arr[ss];
        else
            st[si] = -1;
        return st[si];
    }
 
    // If there are more than one elements, then
    // recur for left and right subtrees and
    // store the max of values in this node
    let mid = getMid(ss, se);
 
    st[si] = Math.max(constructSTUtil(arr, ss, mid, st, si * 2 + 1),constructSTUtil(
arr, mid + 1, se, st, si * 2 + 2));
 
    return st[si];
}
 
/* Function to construct segment tree
   from given array.
   This function allocates memory
   for segment tree.*/
function constructST(arr, n)
{
    // Height of segment tree
    let x = Math.floor(Math.ceil(Math.log2(n)));
 
    // Maximum size of segment tree
    let max_size = 2 * Math.floor(Math.pow(2, x)) - 1;
 
    // Allocate memory
    let st = new Array(max_size).fill(0);
 
    // Fill the allocated memory st
    constructSTUtil(arr, 0, n - 1, st, 0);
 
    // Return the constructed segment tree
    return st;
}
 
// Driver code
let arr = [ 1, 3, 5, 7, 9, 11 ];
let n = arr.length;
 
// find the largest node value
// in the array
 
let maxEle = Math.max(...arr);
 
// creating a set containing
// all fibonacci numbers
// upto the maximum data value
// in the array
createHash(maxEle);
 
// Build segment tree from given array
let st = constructST(arr, n);
 
// Print max of values in array
// from index 1 to 3
console.log("Maximum fibonacci number in given range = ",getMax(st, n, 1, 3));
 
// Update: set arr[1] = 8 and update
// corresponding segment tree nodes.
updateValue(arr, st, 0, n - 1, 3, 8, 0);
 
// Find max after the value is updated
console.log("Updated Maximum Fibonacci number in given range = ", getMax(st, n, 1, 3));
 
// The code is contributed by Gautam goel (gautamgoelo962)


Output:

 

Maximum fibonacci number in given range = 5 

Updated Maximum fibonacci number in given range = 8

 



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