Open In App

Array Range Queries to find the Maximum Armstrong 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 Armstrong 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

If there is no Armstrong number in the sub-array, print -1.

Example: 

Input: arr = [192, 113, 535, 7, 19, 111] 
Query 1: maximum(start=1, end=3)
Query 2: update(i=1, x=153) i.e. arr[1]=153
Output: 
Maximum Armstrong number in given range = 7 
Updated Maximum Armstrong number in given range = 153
Explanation: 
In the Maximum Query, the sub-array [1…3] has 1 Armstrong number 7 viz. [113, 535, 7] 
Hence, 7 is the maximum Armstrong number in the given range.
In the Update Query, the value at index 1 is updated to 153, the array arr now is, [192, 153, 535, 7, 19, 111]
In Updated Maximum Query, the sub-array [1…3] has 2 Armstrong numbers 153 and 7 viz. [153, 535, 7] 
Hence, 153 is the maximum Armstrong number in the given range. 

Naive Approach:
A simple solution is to run a loop from l to r and calculate the maximum Armstrong number of elements in a given range. To update a value, simply do arr[i] = x. After updating the value check again for the maximum Armstrong number in a given range.

Below is the implementation of the above approach: 

C++14




// C++ code to implement above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function that return true
// if num is Armstrong
// else return false
bool isArmstrong(int x) {
    int n = to_string(x).size();
    int sum1 = 0;
    int temp = x;
    while (temp > 0) {
        int digit = temp % 10;
        sum1 += pow(digit, n);
        temp /= 10;
    }
    if (sum1 == x)
        return true;
    return false;
}
 
// Function to find the maximum Armstrong
// number in the given range
int getMax(int arr[], int n, int start, int end) {
    int maxArmstrong = -1;
    for (int i = start; i <= end; i++) {
         
        // check for each element
        if (isArmstrong(arr[i])) {
            maxArmstrong = max(maxArmstrong, arr[i]);
        }
    }
    return maxArmstrong;
}
 
// Function to update the value of arr[i]
void updateValue(int arr[], int i, int x) {
    arr[i] = x;
}
 
// Driver code
int main() {
    int arr[] = {192, 113, 535, 7, 19, 111};
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // Print max of values in array
    // from index 1 to 3
    cout << "Maximum Armstrong "
         << "number in given range = "
         << getMax(arr, n, 1, 3) << endl;
 
    // Update: set arr[1] = 153 and update
    // corresponding segment tree nodes.
    updateValue(arr, 1, 153);
 
    // Find max after the value is updated
    cout << "Updated Maximum Armstrong "
         << "number in given range = "
         << getMax(arr, n, 1, 3) << endl;
 
    return 0;
}


Java




// Java code to implement above approach
import java.util.Arrays;
 
public class GFG {
 
    // Function that returns true
    // if num is Armstrong
    // else returns false
    static boolean isArmstrong(int x)
    {
        int n = Integer.toString(x).length();
        int sum1 = 0;
        int temp = x;
        while (temp > 0) {
            int digit = temp % 10;
            sum1 += Math.pow(digit, n);
            temp /= 10;
        }
        return sum1 == x;
    }
 
    // Function to find the maximum Armstrong
    // number in the given range
    static int getMax(int[] arr, int start, int end)
    {
        int maxArmstrong = -1;
        for (int i = start; i <= end; i++) {
 
            // check for each element
            if (isArmstrong(arr[i])) {
                maxArmstrong
                    = Math.max(maxArmstrong, arr[i]);
            }
        }
        return maxArmstrong;
    }
 
    // Function to update the value of arr[i]
    static void updateValue(int[] arr, int i, int x)
    {
        arr[i] = x;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int[] arr = { 192, 113, 535, 7, 19, 111 };
        int n = arr.length;
 
        // Print max of values in array
        // from index 1 to 3
        System.out.println("Maximum Armstrong "
                           + "number in given range = "
                           + getMax(arr, 1, 3));
 
        // Update: set arr[1] = 153 and update
        // corresponding segment tree nodes.
        updateValue(arr, 1, 153);
 
        // Find max after the value is updated
        System.out.println("Updated Maximum Armstrong "
                           + "number in given range = "
                           + getMax(arr, 1, 3));
    }
}
 
// This code is contributed by Susobhan Akhuli


Python3




# Function that returns True
# if num is Armstrong
# else returns False
def is_armstrong(x):
    n = len(str(x))
    sum1 = 0
    temp = x
    while temp > 0:
        digit = temp % 10
        sum1 += digit ** n
        temp //= 10
    return sum1 == x
 
# Function to find the maximum Armstrong
# number in the given range
def get_max(arr, start, end):
    max_armstrong = -1
    for i in range(start, end + 1):
        # check for each element
        if is_armstrong(arr[i]):
            max_armstrong = max(max_armstrong, arr[i])
    return max_armstrong
 
# Function to update the value of arr[i]
def update_value(arr, i, x):
    arr[i] = x
 
# Driver code
if __name__ == "__main__":
    arr = [192, 113, 535, 7, 19, 111]
    n = len(arr)
 
    # Print max of values in array
    # from index 1 to 3
    print("Maximum Armstrong number in given range =", get_max(arr, 1, 3))
 
    # Update: set arr[1] = 153 and update
    # corresponding elements.
    update_value(arr, 1, 153)
 
    # Find max after the value is updated
    print("Updated Maximum Armstrong number in given range =", get_max(arr, 1, 3))
     
# This code is contributed by akshitaguprzj3


C#




using System;
 
class Program
{
    // Function that returns true
    // if num is Armstrong
    // else returns false
    static bool IsArmstrong(int x)
    {
        int n = x.ToString().Length;
        int sum1 = 0;
        int temp = x;
        while (temp > 0)
        {
            int digit = temp % 10;
            sum1 += (int)Math.Pow(digit, n);
            temp /= 10;
        }
        if (sum1 == x)
            return true;
        return false;
    }
 
    // Function to find the maximum Armstrong
    // number in the given range
    static int GetMax(int[] arr, int start, int end)
    {
        int maxArmstrong = -1;
        for (int i = start; i <= end; i++)
        {
            // Check for each element
            if (IsArmstrong(arr[i]))
            {
                maxArmstrong = Math.Max(maxArmstrong, arr[i]);
            }
        }
        return maxArmstrong;
    }
 
    // Function to update the value of arr[i]
    static void UpdateValue(int[] arr, int i, int x)
    {
        arr[i] = x;
    }
 
    // Main driver code
    static void Main()
    {
        int[] arr = { 192, 113, 535, 7, 19, 111 };
        int n = arr.Length;
 
        // Print max of values in array
        // from index 1 to 3
        Console.WriteLine("Maximum Armstrong " +
            "number in given range = " +
            GetMax(arr, 1, 3));
 
        // Update: set arr[1] = 153 and update
        // corresponding array element.
        UpdateValue(arr, 1, 153);
 
        // Find max after the value is updated
        Console.WriteLine("Updated Maximum Armstrong " +
            "number in given range = " +
            GetMax(arr, 1, 3));
    }
}


Javascript




// Function that returns true if num is an Armstrong number, else returns false
function isArmstrong(x) {
    const n = String(x).length;
    let sum1 = 0;
    let temp = x;
 
    while (temp > 0) {
        const digit = temp % 10;
        sum1 += Math.pow(digit, n);
        temp = Math.floor(temp / 10);
    }
 
    return sum1 === x;
}
 
// Function to find the maximum Armstrong number in the given range
function getMax(arr, start, end) {
    let maxArmstrong = -1;
 
    for (let i = start; i <= end; i++) {
        // Check for each element
        if (isArmstrong(arr[i])) {
            maxArmstrong = Math.max(maxArmstrong, arr[i]);
        }
    }
 
    return maxArmstrong;
}
 
// Function to update the value of arr[i]
function updateValue(arr, i, x) {
    arr[i] = x;
}
 
// Driver code
const arr = [192, 113, 535, 7, 19, 111];
const n = arr.length;
 
// Print the max of values in the array from index 1 to 3
console.log("Maximum Armstrong number in the given range =", getMax(arr, 1, 3));
 
// Update: set arr[1] = 153 and update corresponding elements
updateValue(arr, 1, 153);
 
// Find the max after the value is updated
console.log("Updated Maximum Armstrong number in the given range =", getMax(arr, 1, 3));


Output: 

Maximum Armstrong number in given range = 7
Updated Maximum Armstrong number in given range = 153

Time Complexity: O(N*Q*log N), where N is the size of the input array, Q is the given range of query and the isArmstrong function takes O(log N).
Space Complexity: O(1)

Efficient Approach: 

  • An efficient approach will be to build a Segment Tree where each node stores two values(value and max_set_bits), and do a range query on it to find the maximum Armstrong number.
  • If we have a deep look into it, the maximum Armstrong number for any two range combining will either be the maximum Armstrong number from the left side or the maximum Armstrong number from the right side, whichever is maximum will be taken into account.
  • Representation of Segment trees: 
    1. Leaf Nodes are the elements of the given array.
    2. Each internal node represents the maximum Armstrong number of all of its child or -1 is no Armstrong number exists in the range.
    3. An array representation of a 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 2*i+2 and the parent is at (i-1)/2.
  • Construction of Segment Tree from the given array: 
    1. 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 Armstrong 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. The 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, the size of memory allocated for the segment tree will be 2*( 2ceil(log2n) ) – 1.
    2. A positive integer of n digits is called an Armstrong number of order n (order is a number of digits) if

abcd… = pow(a, n) + pow(b, n) + pow(c, n) + pow(d, n) + …. 

  • In order to check for Armstrong numbers, the idea is to first count number digits (or find order). Let the number of digits be n. For every digit r in input number x, compute rn. If the sum of all such values is equal to n, then return true else false.
  • We then do a range query on the segment tree to find out the maximum Armstrong number for the given range and output the corresponding value.

Below is the implementation of the above approach: 
 

C++




// C++ code to implement above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// A utility function to get the
// middle index of given range.
int getMid(int s, int e)
{
    return s + (e - s) / 2;
}
 
// Function that return true
// if num is armstrong
// else return false
bool isArmstrong(int x)
{
    int n = to_string(x).size();
    int sum1 = 0;
    int temp = x;
    while (temp > 0) {
        int digit = temp % 10;
        sum1 += pow(digit, n);
        temp /= 10;
    }
    if (sum1 == x)
        return true;
    return false;
}
 
/*  A recursive function to get
    the sum of values in the
    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
   the 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 (isArmstrong(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] = 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 (isArmstrong(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] = max(constructSTUtil(
                     arr, ss, mid, st,
                     si * 2 + 1),
                 constructSTUtil(
                     arr, mid + 1, se,
                     st, si * 2 + 2));
 
    return st[si];
}
 
/* Function to construct a 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[] = { 192, 113,
                  535, 7, 19, 111 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // Build segment tree from
    // given array
    int* st = constructST(arr, n);
 
    // Print max of values in array
    // from index 1 to 3
    cout << "Maximum armstrong "
         << "number in given range = "
         << getMax(st, n, 1, 3) << endl;
 
    // Update: set arr[1] = 153 and update
    // corresponding segment tree nodes.
    updateValue(arr, st, 0,
                n - 1, 1, 153, 0);
 
    // Find max after the value is updated
    cout << "Updated Maximum armstrong "
         << "number in given range = "
         << getMax(st, n, 1, 3) << endl;
 
    return 0;
}


Java




// Java code to implement
// the above approach
import java.util.*;
class GFG{
 
// A utility function to get the
// middle index of given range.
static int getMid(int s, int e)
{
    return s + (e - s) / 2;
}
 
// Function that return true
// if num is armstrong
// else return false
static boolean isArmstrong(int x)
{
    int n = String.valueOf(x).length();
    int sum1 = 0;
    int temp = x;
    while (temp > 0)
    {
        int digit = temp % 10;
        sum1 += Math.pow(digit, n);
        temp /= 10;
    }
    if (sum1 == x)
        return true;
    return false;
}
 
/* A recursive function to get
the sum of values in the
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 ),
                    MaxUtil(st, mid + 1,
                            se, l, r,
                            2 * node + 1));
}
 
/* A recursive function to update
the nodes which have the given
the 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.print("Invalid Input" + "\n");
        return;
    }
 
    if (ss == se)
    {
        // update value in array
        // and in segment tree
        arr[index] = value;
 
        if (isArmstrong(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);
        else
            updateValue(arr, st, mid + 1,
                        se, index, value,
                        2 * node +1);
 
        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");
        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 (isArmstrong(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 ),
                      constructSTUtil(arr, mid + 1,
                                      se, st,
                                      si * 2 + 1));
 
    return st[si];
}
 
/* Function to construct a 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)));
 
    // 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[] = {192, 113,
                 535, 7, 19, 111};
    int n = arr.length;
 
    // Build segment tree from
    // given array
    int[] st = constructST(arr, n);
 
    // Print max of values in array
    // from index 1 to 3
    System.out.print("Maximum armstrong " +
                     "number in given range = " +
                      getMax(st, n, 1, 3) + "\n");
 
    // Update: set arr[1] = 153 and update
    // corresponding segment tree nodes.
    updateValue(arr, st, 0,
                n - 1, 1, 153, 0);
 
    // Find max after the value is updated
    System.out.print("Updated Maximum armstrong " +
                       "number in given range = " +
                       getMax(st, n, 1, 3) + "\n");
 
}
}
 
// This code is contributed by gauravrajput1


Python3




# Python code to implement above approach
import math
 
# A utility function to get the
# middle index of given range.
def getMid(s: int, e: int) -> int:
    return s + (e - s) // 2
 
# Function that return true
# if num is armstrong
# else return false
def isArmstrong(x: int) -> bool:
    n = len(str(x))
    sum1 = 0
    temp = x
    while (temp > 0):
        digit = temp % 10
        sum1 += pow(digit, n)
        temp //= 10
 
    if (sum1 == x):
        return True
    return False
 
'''  A recursive function to get
    the sum of values in the
    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 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 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 = 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
   the 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 updateValue(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 (isArmstrong(value)):
            st[node] = value
        else:
            st[node] = -1
 
    else:
        mid = getMid(ss, se)
 
        if (index >= ss and 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).
def getMax(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 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
def 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 (isArmstrong(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
    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 a segment tree
   from given array. This function
   allocates memory for segment tree.'''
def constructST(arr, n):
 
    # Height of segment tree
    x = int(math.ceil(math.log2(n)))
 
    # Maximum size of segment tree
    max_size = 2 * int(math.pow(2, x)) - 1
 
    # Allocate memory
    st = [0 for _ in range(max_size)]
 
    # Fill the allocated memory st
    constructSTUtil(arr, 0, n - 1, st, 0)
 
    # Return the constructed
    # segment tree
    return st
 
# Driver code
if __name__ == "__main__":
 
    arr = [192, 113, 535, 7, 19, 111]
    n = len(arr)
 
    # Build segment tree from
    # given array
    st = constructST(arr, n)
 
    # Print max of values in array
    # from index 1 to 3
    print("Maximum armstrong number in given range = {}".format(
        getMax(st, n, 1, 3)))
 
    # Update: set arr[1] = 153 and update
    # corresponding segment tree nodes.
    updateValue(arr, st, 0, n - 1, 1, 153, 0)
 
    # Find max after the value is updated
    print("Updated Maximum armstrong number in given range = {}".format(
        getMax(st, n, 1, 3)))
 
# This code is contributed by sanjeev2552


C#




// C# code to implement
// the above approach
using System;
class GFG{
 
// A utility function to get the
// middle index of given range.
static int getMid(int s, int e)
{
  return s + (e - s) / 2;
}
 
// Function that return true
// if num is armstrong
// else return false
static bool isArmstrong(int x)
{
  int n = String.Join("", x).Length;
  int sum1 = 0;
  int temp = x;
  while (temp > 0)
  {
    int digit = temp % 10;
    sum1 += (int)Math.Pow(digit, n);
    temp /= 10;
  }
  if (sum1 == x)
    return true;
  return false;
}
 
/* A recursive function to get
the sum of values in the
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),
                  MaxUtil(st, mid + 1,
                          se, l, r,
                          2 * node + 1));
}
 
/* A recursive function to update
the nodes which have the given
the 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)
  {
    Console.Write("Invalid Input" + "\n");
    return;
  }
 
  if (ss == se)
  {
    // update value in array
    // and in segment tree
    arr[index] = value;
 
    if (isArmstrong(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);
    else
      updateValue(arr, st, mid + 1,
                  se, index, value,
                  2 * node + 1);
 
    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)
  {
    Console.Write("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
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 (isArmstrong(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),
                    constructSTUtil(arr, mid + 1,
                                    se, st,
                                    si * 2 + 1));
  return st[si];
}
 
/* Function to construct a 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.Ceiling(Math.Log(n)));
 
  // 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 = {192, 113,
               535, 7, 19, 111};
  int n = arr.Length;
 
  // Build segment tree from
  // given array
  int[] st = constructST(arr, n);
 
  // Print max of values in array
  // from index 1 to 3
  Console.Write("Maximum armstrong " +
                "number in given range = " +
                 getMax(st, n, 1, 3) + "\n");
 
  // Update: set arr[1] = 153 and update
  // corresponding segment tree nodes.
  updateValue(arr, st, 0,
              n - 1, 1, 153, 0);
 
  // Find max after the value is updated
  Console.Write("Updated Maximum armstrong " +
                "number in given range = " +
                 getMax(st, n, 1, 3) + "\n");
}
}
 
// This code is contributed by shikhasingrajput


Javascript




<script>
 
// JavaScript code to implement
// the above approach
 
// A utility function to get the
// middle index of given range.
function getMid(s,e)
{
    return s + Math.floor((e - s) / 2);
}
 
// Function that return true
// if num is armstrong
// else return false
function isArmstrong(x)
{
    let n = (x).toString().length;
    let sum1 = 0;
    let temp = x;
    while (temp > 0)
    {
        let digit = temp % 10;
        sum1 += Math.pow(digit, n);
        temp = Math.floor(temp/10);
    }
    if (sum1 == x)
        return true;
    return false;
}
 
/* A recursive function to get
the sum of values in the
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 ),
                    MaxUtil(st, mid + 1,
                            se, l, r,
                            2 * node + 1));
}
 
/* A recursive function to update
the nodes which have the given
the 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)
    {
        document.write("Invalid Input" + "<br>");
        return;
    }
  
    if (ss == se)
    {
        // update value in array
        // and in segment tree
        arr[index] = value;
  
        if (isArmstrong(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);
        else
            updateValue(arr, st, mid + 1,
                        se, index, value,
                        2 * node +1);
  
        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)
    {
        document.write("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 (isArmstrong(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 ),
                      constructSTUtil(arr, mid + 1,
                                      se, st,
                                      si * 2 + 1));
  
    return st[si];
}
 
/* Function to construct a segment tree
from given array. This function
allocates memory for segment tree.*/
function constructST(arr,n)
{
    // Height of segment tree
    let x = (Math.ceil(Math.log(n)));
  
    // Maximum size of segment tree
    let max_size = 2 * Math.pow(2, x) - 1;
  
    // Allocate memory
    let st = new Array(max_size);
  
    // Fill the allocated memory st
    constructSTUtil(arr, 0,
                     n - 1, st, 0);
  
    // Return the constructed
    // segment tree
    return st;
}
 
// Driver code
let arr=[192, 113,
                 535, 7, 19, 111];
let n = arr.length;
  
// Build segment tree from
// given array
let st = constructST(arr, n);
 
// Print max of values in array
// from index 1 to 3
document.write("Maximum armstrong " +
                 "number in given range = " +
                 getMax(st, n, 1, 3) + "<br>");
 
// Update: set arr[1] = 153 and update
// corresponding segment tree nodes.
updateValue(arr, st, 0,
            n - 1, 1, 153, 0);
 
// Find max after the value is updated
document.write("Updated Maximum armstrong " +
                 "number in given range = " +
                 getMax(st, n, 1, 3) + "<br>");
 
 
// This code is contributed by patel2127
 
</script>


Output

Maximum armstrong number in given range = 7 
Updated Maximum armstrong number in given range = 153




Time Complexity: The time complexity of each query and update is O(log N) and that of building the segment tree is O(N) 



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