Related Articles
Array Range Queries to find the Maximum Armstrong number with updates
• Difficulty Level : Basic
• Last Updated : 25 Feb, 2021

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=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.

Simple Solution:
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. The first operation takes O(N) time and the second operation takes O(1) time.

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 ``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);` `    ``// 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 = 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 cona 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 = 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 = 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 cona 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 = 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`
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)

Attention reader! Don’t stop learning now. Get hold of all the important mathematical concepts for competitive programming with the Essential Maths for CP Course at a student-friendly price. To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

My Personal Notes arrow_drop_up