Array range queries to find the number of perfect square elements with updates | C # program to find number of perfect square numbers in a subarray and performing updates ; Function to check if a number is a perfect square or not ; Find floating point value of square root of x . ; If square root is an integer ; A utility function to get the middle index from corner indexes . ; where st - . Pointer to segment tree index - . Index of current node in the segment tree . Initially 0 is passed as root is always at index 0 ss & se - . Starting and ending indexes of the segment represented by current node i . e . st [ index ] qs & qe - . Starting and ending indexes of query range ; If segment of this node is a part of given range , then return the number of perfect square numbers in the segment ; If segment of this node is outside the given range ; If a part of this segment overlaps with the given range ; where st , si , ss & se are same as getSumUtil ( ) i - . index of the element to be updated . This index is in input array . diff - . Value to be added to all nodes which have i in range ; Base Case : If the input index lies outside the range of this segment ; If the input index is in range of this node , then update the value of the node and its children ; Function to update a value in the input array and segment tree . It uses updateValueUtil ( ) to update the value in segment tree ; Check for erroneous input index ; Update the value in array ; Case 1 : Old and new values both are perfect square numbers ; Case 2 : Old and new values both not perfect square numbers ; Case 3 : Old value was perfect square , new value is not a perfect square ; Case 4 : Old value was non - perfect square , new_val is perfect square ; Update values of nodes in segment tree ; Return no . of perfect square numbers in range from index qs ( query start ) to qe ( query end ) . It mainly uses queryUtil ( ) ; Recursive function that constructs Segment Tree for array [ ss . . se ] . si is index of current node in segment tree st ; If there is one element in array , check if it is perfect square number then store 1 in the segment tree else store 0 and return ; if arr [ ss ] is a perfect square number ; If there are more than one elements , then recur for left and right subtrees and store the sum of the two values in this node ; Function to cona segment tree from given array . This function allocates memory for segment tree and calls constructSTUtil ( ) to fill the allocated memory ; Allocate memory for segment tree Height of segment tree ; Maximum size of segment tree ; Fill the allocated memory st ; Return the constructed segment tree ; Driver Code ; Build segment tree from given array ; Query 1 : Query ( start = 0 , end = 4 ) ; Query 2 : Update ( i = 3 , x = 11 ) , i . e Update a [ i ] to x ; Query 3 : Query ( start = 0 , end = 4 )
using System ; class GFG { static readonly int MAX = 1000 ; static bool isPerfectSquare ( int x ) { double sr = Math . Sqrt ( x ) ; return ( ( sr - Math . Floor ( sr ) ) == 0 ) ? true : false ; } static int getMid ( int s , int e ) { return s + ( e - s ) / 2 ; } static int queryUtil ( int [ ] st , int ss , int se , int qs , int qe , int index ) { if ( qs <= ss && qe >= se ) return st [ index ] ; if ( se < qs ss > qe ) return 0 ; int mid = getMid ( ss , se ) ; return queryUtil ( st , ss , mid , qs , qe , 2 * index + 1 ) + queryUtil ( st , mid + 1 , se , qs , qe , 2 * index + 2 ) ; } static void updateValueUtil ( int [ ] st , int ss , int se , int i , int diff , int si ) { if ( i < ss i > se ) return ; st [ si ] = st [ si ] + diff ; if ( se != ss ) { int mid = getMid ( ss , se ) ; updateValueUtil ( st , ss , mid , i , diff , 2 * si + 1 ) ; updateValueUtil ( st , mid + 1 , se , i , diff , 2 * si + 2 ) ; } } static void updateValue ( int [ ] arr , int [ ] st , int n , int i , int new_val ) { if ( i < 0 i > n - 1 ) { Console . Write ( " Invalid ▁ Input " ) ; return ; } int diff = 0 , oldValue ; oldValue = arr [ i ] ; arr [ i ] = new_val ; if ( isPerfectSquare ( oldValue ) && isPerfectSquare ( new_val ) ) return ; if ( ! isPerfectSquare ( oldValue ) && ! isPerfectSquare ( new_val ) ) return ; if ( isPerfectSquare ( oldValue ) && ! isPerfectSquare ( new_val ) ) { diff = - 1 ; } if ( ! isPerfectSquare ( oldValue ) && ! isPerfectSquare ( new_val ) ) { diff = 1 ; } updateValueUtil ( st , 0 , n - 1 , i , diff , 0 ) ; } static void query ( int [ ] st , int n , int qs , int qe ) { int perfectSquareInRange = queryUtil ( st , 0 , n - 1 , qs , qe , 0 ) ; Console . Write ( perfectSquareInRange + " STRNEWLINE " ) ; } static int constructSTUtil ( int [ ] arr , int ss , int se , int [ ] st , int si ) { if ( ss == se ) { if ( isPerfectSquare ( arr [ ss ] ) ) st [ si ] = 1 ; else st [ si ] = 0 ; return st [ si ] ; } int mid = getMid ( ss , se ) ; st [ si ] = constructSTUtil ( arr , ss , mid , st , si * 2 + 1 ) + constructSTUtil ( arr , mid + 1 , se , st , si * 2 + 2 ) ; return st [ si ] ; } static int [ ] constructST ( int [ ] arr , int n ) { int x = ( int ) ( Math . Ceiling ( Math . Log ( n ) ) ) ; int max_size = 4 * ( int ) Math . Pow ( 2 , x ) + 1 ; int [ ] st = new int [ max_size ] ; constructSTUtil ( arr , 0 , n - 1 , st , 0 ) ; return st ; } public static void Main ( String [ ] args ) { int [ ] arr = { 16 , 15 , 8 , 9 , 14 , 25 } ; int n = arr . Length ; int [ ] st = constructST ( arr , n ) ; int start = 0 ; int end = 4 ; query ( st , n , start , end ) ; int i = 3 ; int x = 11 ; updateValue ( arr , st , n , i , x ) ; start = 0 ; end = 4 ; query ( st , n , start , end ) ; } }