Count and Toggle Queries on a Binary Array | Python program to implement toggle and count queries on a binary array . ; segment tree to store count of 1 's within range ; bool type tree to collect the updates for toggling the values of 1 and 0 in given range ; function for collecting updates of toggling node -- > index of current node in segment tree st -- > starting index of current node en -- > ending index of current node us -- > starting index of range update query ue -- > ending index of range update query ; If lazy value is non - zero for current node of segment tree , then there are some pending updates . So we need to make sure that the pending updates are done before making new updates . Because this value may be used by parent after recursive calls ( See last line of this function ) ; Make pending updates using value stored in lazy nodes ; checking if it is not leaf node because if it is leaf node then we cannot go further ; We can postpone updating children we don ' t ▁ ▁ need ▁ their ▁ new ▁ values ▁ now . ▁ ▁ Since ▁ we ▁ are ▁ not ▁ yet ▁ updating ▁ children ▁ of ▁ ' node ',  we need to set lazy flags for the children ; out of range ; Current segment is fully in range ; Add the difference to current node ; same logic for checking leaf node or not ; This is where we store values in lazy nodes , rather than updating the segment tree itelf Since we don 't need these updated values now  we postpone updates by storing values in lazy[] ; If not completely in rang , but overlaps , recur for children , ; And use the result of children calls to update this node ; function to count number of 1 's within given range ; current node is out of range ; If lazy flag is set for current node of segment tree , then there are some pending updates . So we need to make sure that the pending updates are done before processing the sub sum query ; Make pending updates to this node . Note that this node represents sum of elements in arr [ st . . en ] and all these elements must be increased by lazy [ node ] ; checking if it is not leaf node because if it is leaf node then we cannot go further ; Since we are not yet updating children os si , we need to set lazy values for the children ; At this point we are sure that pending lazy updates are done for current node . So we can return value If this segment lies in range ; If a part of this segment overlaps with the given range ; Driver Code ; Toggle 1 2 ; Toggle 2 4 ; count 2 3 ; Toggle 2 4 ; count 1 4
MAX = 100000 NEW_LINE tree = [ 0 ] * MAX NEW_LINE lazy = [ False ] * MAX NEW_LINE def toggle ( node : int , st : int , en : int , us : int , ue : int ) : NEW_LINE INDENT if lazy [ node ] : NEW_LINE INDENT lazy [ node ] = False NEW_LINE tree [ node ] = en - st + 1 - tree [ node ] NEW_LINE if st < en : NEW_LINE INDENT lazy [ node << 1 ] = not lazy [ node << 1 ] NEW_LINE lazy [ 1 + ( node << 1 ) ] = not lazy [ 1 + ( node << 1 ) ] NEW_LINE DEDENT DEDENT if st > en or us > en or ue < st : NEW_LINE INDENT return NEW_LINE DEDENT if us <= st and en <= ue : NEW_LINE INDENT tree [ node ] = en - st + 1 - tree [ node ] NEW_LINE if st < en : NEW_LINE INDENT lazy [ node << 1 ] = not lazy [ node << 1 ] NEW_LINE lazy [ 1 + ( node << 1 ) ] = not lazy [ 1 + ( node << 1 ) ] NEW_LINE DEDENT return NEW_LINE DEDENT mid = ( st + en ) // 2 NEW_LINE toggle ( ( node << 1 ) , st , mid , us , ue ) NEW_LINE toggle ( ( node << 1 ) + 1 , mid + 1 , en , us , ue ) NEW_LINE if st < en : NEW_LINE INDENT tree [ node ] = tree [ node << 1 ] + tree [ ( node << 1 ) + 1 ] NEW_LINE DEDENT DEDENT def countQuery ( node : int , st : int , en : int , qs : int , qe : int ) -> int : NEW_LINE INDENT if st > en or qs > en or qe < st : NEW_LINE INDENT return 0 NEW_LINE DEDENT if lazy [ node ] : NEW_LINE INDENT lazy [ node ] = False NEW_LINE tree [ node ] = en - st + 1 - tree [ node ] NEW_LINE if st < en : NEW_LINE INDENT lazy [ node << 1 ] = not lazy [ node << 1 ] NEW_LINE lazy [ ( node << 1 ) + 1 ] = not lazy [ ( node << 1 ) + 1 ] NEW_LINE DEDENT DEDENT if qs <= st and en <= qe : NEW_LINE INDENT return tree [ node ] NEW_LINE DEDENT mid = ( st + en ) // 2 NEW_LINE return countQuery ( ( node << 1 ) , st , mid , qs , qe ) + countQuery ( ( node << 1 ) + 1 , mid + 1 , en , qs , qe ) NEW_LINE DEDENT if __name__ == " _ _ main _ _ " : NEW_LINE INDENT n = 5 NEW_LINE DEDENT toggle ( 1 , 0 , n - 1 , 1 , 2 ) NEW_LINE toggle ( 1 , 0 , n - 1 , 2 , 4 ) NEW_LINE print ( countQuery ( 1 , 0 , n - 1 , 2 , 3 ) ) NEW_LINE toggle ( 1 , 0 , n - 1 , 2 , 4 ) NEW_LINE print ( countQuery ( 1 , 0 , n - 1 , 1 , 4 ) ) NEW_LINE