Range Update Queries to XOR with 1 in a Binary Array . | Python program for the given problem ; Class for each node in the segment tree ; A utility function for merging two nodes ; utility function for updating a node ; A recursive function that constructs Segment Tree for given string ; If start is equal to end then insert the array element ; Build the segment tree for range qs to mid ; Build the segment tree for range mid + 1 to qe ; merge the two child nodes to obtain the parent node ; Query in a range qs to qe ; If the range lies in this segment ; If the range is out of the bounds of this segment ; Else query for the right and left child node of this subtree and merge them ; range update using lazy prpagation ; If the range is out of the bounds of this segment ; If the range lies in this segment ; Else query for the right and left child node of this subtree and merge them ; Driver code ; Build the segment tree ; Query of Type 2 in the range 3 to 7 ; Query of Type 3 in the range 2 to 5 ; Query of Type 1 in the range 1 to 4 ; Query of Type 4 in the range 3 to 7 ; Query of Type 5 in the range 4 to 9
from sys import maxsize NEW_LINE from typing import List NEW_LINE INT_MAX = maxsize NEW_LINE INT_MIN = - maxsize NEW_LINE lazy = [ 0 for _ in range ( 100001 ) ] NEW_LINE class node : NEW_LINE INDENT def __init__ ( self ) -> None : NEW_LINE INDENT self . l1 = self . r1 = self . l0 = self . r0 = - 1 NEW_LINE self . max0 = self . max1 = INT_MIN NEW_LINE self . min0 = self . min1 = INT_MAX NEW_LINE DEDENT DEDENT seg = [ node ( ) for _ in range ( 100001 ) ] NEW_LINE def MergeUtil ( l : node , r : node ) -> node : NEW_LINE INDENT x = node ( ) NEW_LINE x . l0 = l . l0 if ( l . l0 != - 1 ) else r . l0 NEW_LINE x . r0 = r . r0 if ( r . r0 != - 1 ) else l . r0 NEW_LINE x . l1 = l . l1 if ( l . l1 != - 1 ) else r . l1 NEW_LINE x . r1 = r . r1 if ( r . r1 != - 1 ) else l . r1 NEW_LINE x . min0 = min ( l . min0 , r . min0 ) NEW_LINE if ( l . r0 != - 1 and r . l0 != - 1 ) : NEW_LINE INDENT x . min0 = min ( x . min0 , r . l0 - l . r0 ) NEW_LINE DEDENT x . min1 = min ( l . min1 , r . min1 ) NEW_LINE if ( l . r1 != - 1 and r . l1 != - 1 ) : NEW_LINE INDENT x . min1 = min ( x . min1 , r . l1 - l . r1 ) NEW_LINE DEDENT x . max0 = max ( l . max0 , r . max0 ) NEW_LINE if ( l . l0 != - 1 and r . r0 != - 1 ) : NEW_LINE INDENT x . max0 = max ( x . max0 , r . r0 - l . l0 ) NEW_LINE DEDENT x . max1 = max ( l . max1 , r . max1 ) NEW_LINE if ( l . l1 != - 1 and r . r1 != - 1 ) : NEW_LINE INDENT x . max1 = max ( x . max1 , r . r1 - l . l1 ) NEW_LINE DEDENT return x NEW_LINE DEDENT def UpdateUtil ( x : node ) -> node : NEW_LINE INDENT x . l0 , x . l1 = x . l1 , x . l0 NEW_LINE x . r0 , x . r1 = x . r1 , x . r0 NEW_LINE x . min1 , x . min0 = x . min0 , x . min1 NEW_LINE x . max0 , x . max1 = x . max1 , x . max0 NEW_LINE return x NEW_LINE DEDENT def Build ( qs : int , qe : int , ind : int , arr : List [ int ] ) -> None : NEW_LINE INDENT if ( qs == qe ) : NEW_LINE INDENT if ( arr [ qs ] == 1 ) : NEW_LINE INDENT seg [ ind ] . l1 = seg [ ind ] . r1 = qs NEW_LINE DEDENT else : NEW_LINE INDENT seg [ ind ] . l0 = seg [ ind ] . r0 = qs NEW_LINE DEDENT lazy [ ind ] = 0 NEW_LINE return NEW_LINE DEDENT mid = ( qs + qe ) >> 1 NEW_LINE Build ( qs , mid , ind << 1 , arr ) NEW_LINE Build ( mid + 1 , qe , ind << 1 1 , arr ) NEW_LINE seg [ ind ] = MergeUtil ( seg [ ind << 1 ] , seg [ ind << 1 1 ] ) NEW_LINE DEDENT def Query ( qs : int , qe : int , ns : int , ne : int , ind : int ) -> node : NEW_LINE INDENT if ( lazy [ ind ] != 0 ) : NEW_LINE INDENT seg [ ind ] = UpdateUtil ( seg [ ind ] ) NEW_LINE if ( ns != ne ) : NEW_LINE INDENT lazy [ ind * 2 ] ^= lazy [ ind ] NEW_LINE lazy [ ind * 2 + 1 ] ^= lazy [ ind ] NEW_LINE DEDENT lazy [ ind ] = 0 NEW_LINE DEDENT x = node ( ) NEW_LINE if ( qs <= ns and qe >= ne ) : NEW_LINE INDENT return seg [ ind ] NEW_LINE DEDENT if ( ne < qs or ns > qe or ns > ne ) : NEW_LINE INDENT return x NEW_LINE DEDENT mid = ( ns + ne ) >> 1 NEW_LINE l = Query ( qs , qe , ns , mid , ind << 1 ) NEW_LINE r = Query ( qs , qe , mid + 1 , ne , ind << 1 1 ) NEW_LINE x = MergeUtil ( l , r ) NEW_LINE return x NEW_LINE DEDENT def RangeUpdate ( us : int , ue : int , ns : int , ne : int , ind : int ) -> None : NEW_LINE INDENT if ( lazy [ ind ] != 0 ) : NEW_LINE INDENT seg [ ind ] = UpdateUtil ( seg [ ind ] ) NEW_LINE if ( ns != ne ) : NEW_LINE INDENT lazy [ ind * 2 ] ^= lazy [ ind ] NEW_LINE lazy [ ind * 2 + 1 ] ^= lazy [ ind ] NEW_LINE DEDENT lazy [ ind ] = 0 NEW_LINE DEDENT if ( ns > ne or ns > ue or ne < us ) : NEW_LINE INDENT return NEW_LINE DEDENT if ( ns >= us and ne <= ue ) : NEW_LINE INDENT seg [ ind ] = UpdateUtil ( seg [ ind ] ) NEW_LINE if ( ns != ne ) : NEW_LINE INDENT lazy [ ind * 2 ] ^= 1 NEW_LINE lazy [ ind * 2 + 1 ] ^= 1 NEW_LINE DEDENT return NEW_LINE DEDENT mid = ( ns + ne ) >> 1 NEW_LINE RangeUpdate ( us , ue , ns , mid , ind << 1 ) NEW_LINE RangeUpdate ( us , ue , mid + 1 , ne , ind << 1 1 ) NEW_LINE l = seg [ ind << 1 ] NEW_LINE r = seg [ ind << 1 1 ] NEW_LINE seg [ ind ] = MergeUtil ( l , r ) NEW_LINE DEDENT if __name__ == " _ _ main _ _ " : NEW_LINE INDENT arr = [ 1 , 1 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 1 , 1 , 0 ] NEW_LINE n = len ( arr ) NEW_LINE Build ( 0 , n - 1 , 1 , arr ) NEW_LINE ans = Query ( 3 , 7 , 0 , n - 1 , 1 ) NEW_LINE print ( ans . min1 ) NEW_LINE ans = Query ( 2 , 5 , 0 , n - 1 , 1 ) NEW_LINE print ( ans . max1 ) NEW_LINE RangeUpdate ( 1 , 4 , 0 , n - 1 , 1 ) NEW_LINE ans = Query ( 3 , 7 , 0 , n - 1 , 1 ) NEW_LINE print ( ans . min0 ) NEW_LINE ans = Query ( 4 , 9 , 0 , n - 1 , 1 ) NEW_LINE print ( ans . max0 ) NEW_LINE DEDENT