





class   lowerCAmelCase				:
 def __init__( self    : List[Any]      )     ->      Optional[Any]:
     lowerCamelCase__       : Dict   					=						0
     lowerCamelCase__       : List[Any]   					=						0
     lowerCamelCase__       : Tuple   					=						{}
 def 	A_      ( self    : Any     ,	UpperCAmelCase    : str      )     ->      int:
     if vertex not in self.adjacency:
         lowerCamelCase__       : Tuple   					=						{}
         self.num_vertices += 1
 def 	A_      ( self    : Tuple     ,	UpperCAmelCase    : str     ,	UpperCAmelCase    : Optional[Any]     ,	UpperCAmelCase    : Optional[int]      )     ->      List[str]:
     self.add_vertex(UpperCAmelCase      )
     self.add_vertex(UpperCAmelCase      )

     if head == tail:
         return

     lowerCamelCase__       : List[str]   					=						weight
     lowerCamelCase__       : List[str]   					=						weight
 def 	A_      ( self    : Optional[Any]      )     ->      Union[str, Any]:
     lowerCamelCase__       : Union[str, Any]   					=						self.get_edges()
     for edge in edges:
         lowerCamelCase__					,				lowerCamelCase__					,				lowerCamelCase__       : Union[str, Any]   					=						edge
         edges.remove((tail, head, weight)      )
     for i in range(len(UpperCAmelCase      )      ):
         lowerCamelCase__       : Any   					=						list(edges[i]      )

     edges.sort(key=lambda UpperCAmelCase      : e[2]      )
     for i in range(len(UpperCAmelCase      ) - 1      ):
         if edges[i][2] >= edges[i + 1][2]:
             lowerCamelCase__       : str   					=						edges[i][2] + 1
     for edge in edges:
         lowerCamelCase__					,				lowerCamelCase__					,				lowerCamelCase__       : Any   					=						edge
         lowerCamelCase__       : Optional[int]   					=						weight
         lowerCamelCase__       : Tuple   					=						weight
 def __str__( self    : List[Any]      )     ->      Union[str, Any]:
     lowerCamelCase__       : List[str]   					=						''
     for tail in self.adjacency:
         for head in self.adjacency[tail]:
             lowerCamelCase__       : Optional[Any]   					=						self.adjacency[head][tail]
             string += F"""{head} -> {tail} == {weight}\n"""
     return string.rstrip('\n'      )
 def 	A_      ( self    : List[str]      )     ->      Dict:
     lowerCamelCase__       : List[Any]   					=						[]
     for tail in self.adjacency:
         for head in self.adjacency[tail]:
             output.append((tail, head, self.adjacency[head][tail])      )
     return output
 def 	A_      ( self    : Dict      )     ->      Dict:
     return self.adjacency.keys()
 @staticmethod
 def 	A_      ( UpperCAmelCase    : Optional[int]=None     ,	UpperCAmelCase    : List[str]=None      )     ->      str:
     lowerCamelCase__       : str   					=						Graph()
     if vertices is None:
         lowerCamelCase__       : Optional[int]   					=						[]
     if edges is None:
         lowerCamelCase__       : Union[str, Any]   					=						[]
     for vertex in vertices:
         g.add_vertex(UpperCAmelCase      )
     for edge in edges:
         g.add_edge(*UpperCAmelCase      )
     return g

 class   lowerCAmelCase				:
  def __init__( self    : str      )     ->      Optional[Any]:
      lowerCamelCase__       : Optional[Any]   					=						{}
      lowerCamelCase__       : Optional[Any]   					=						{}
  def __len__( self    : List[str]      )     ->      int:
      return len(self.parent      )
  def 	A_      ( self    : Union[str, Any]     ,	UpperCAmelCase    : Union[str, Any]      )     ->      Dict:
      if item in self.parent:
          return self.find(UpperCAmelCase      )

      lowerCamelCase__       : Optional[int]   					=						item
      lowerCamelCase__       : str   					=						0
      return item
  def 	A_      ( self    : List[Any]     ,	UpperCAmelCase    : Dict      )     ->      List[str]:
      if item not in self.parent:
          return self.make_set(UpperCAmelCase      )
      if item != self.parent[item]:
          lowerCamelCase__       : List[str]   					=						self.find(self.parent[item]      )
      return self.parent[item]







  def 	A_      ( self    : Dict     ,	UpperCAmelCase    : str     ,	UpperCAmelCase    : int      )     ->      Tuple:
      lowerCamelCase__       : Any   					=						self.find(UpperCAmelCase      )
      lowerCamelCase__       : Dict   					=						self.find(UpperCAmelCase      )

      if roota == roota:
          return roota

      if self.rank[roota] > self.rank[roota]:
          lowerCamelCase__       : Optional[Any]   					=						roota
          return roota

      if self.rank[roota] < self.rank[roota]:
          lowerCamelCase__       : List[Any]   					=						roota
          return roota

      if self.rank[roota] == self.rank[roota]:
          self.rank[roota] += 1
          lowerCamelCase__       : Dict   					=						roota
          return roota
      return None


 @staticmethod
 def 	A_      ( UpperCAmelCase    : Dict      )     ->      List[str]:
     lowerCamelCase__       : int   					=						graph.num_vertices

     lowerCamelCase__       : Dict   					=						Graph.UnionFind()
     lowerCamelCase__       : Union[str, Any]   					=						[]
     while num_components > 1:
         lowerCamelCase__       : str   					=						{}
         for vertex in graph.get_vertices():
             lowerCamelCase__       : List[str]   					=						-1

         lowerCamelCase__       : Dict   					=						graph.get_edges()
         for edge in edges:
             lowerCamelCase__					,				lowerCamelCase__					,				lowerCamelCase__       : Tuple   					=						edge
             edges.remove((tail, head, weight)      )
         for edge in edges:
             lowerCamelCase__					,				lowerCamelCase__					,				lowerCamelCase__       : Optional[int]   					=						edge
             lowerCamelCase__       : Optional[int]   					=						union_find.find(UpperCAmelCase      )
             lowerCamelCase__       : int   					=						union_find.find(UpperCAmelCase      )
             if seta != seta:
                 if cheap_edge[seta] == -1 or cheap_edge[seta][2] > weight:
                     lowerCamelCase__       : Union[str, Any]   					=						[head, tail, weight]

                 if cheap_edge[seta] == -1 or cheap_edge[seta][2] > weight:
                     lowerCamelCase__       : Optional[Any]   					=						[head, tail, weight]
         for vertex in cheap_edge:
             if cheap_edge[vertex] != -1:
                 lowerCamelCase__					,				lowerCamelCase__					,				lowerCamelCase__       : Tuple   					=						cheap_edge[vertex]
                 if union_find.find(UpperCAmelCase      ) != union_find.find(UpperCAmelCase      ):
                     union_find.union(UpperCAmelCase     ,	UpperCAmelCase      )
                     mst_edges.append(cheap_edge[vertex]      )
                     lowerCamelCase__       : int   					=						num_components - 1
     lowerCamelCase__       : Optional[int]   					=						Graph.build(edges=UpperCAmelCase      )
     return mst












from __future__ import annotations

import time
from collections.abc import Sequence
from random import randint

from matplotlib import pyplot as plt


def 			SCREAMING_SNAKE_CASE (			_UpperCAmelCase		,      _UpperCAmelCase		,      _UpperCAmelCase					)     ->	tuple[int | None, int | None, float]:
    if not arr:
        return None, None, 0
    if low == high:
        return low, high, arr[low]

    lowerCamelCase__       : Union[str, Any]   					=						(low + high) // 2
    lowerCamelCase__					,				lowerCamelCase__					,				lowerCamelCase__       : str   					=						max_subarray(_UpperCAmelCase		,      _UpperCAmelCase		,      _UpperCAmelCase					)
    lowerCamelCase__					,				lowerCamelCase__					,				lowerCamelCase__       : Optional[Any]   					=						max_subarray(_UpperCAmelCase		,      mid + 1		,      _UpperCAmelCase					)
    lowerCamelCase__					,				lowerCamelCase__					,				lowerCamelCase__       : int   					=						max_cross_sum(_UpperCAmelCase		,      _UpperCAmelCase		,      _UpperCAmelCase		,      _UpperCAmelCase					)
    if left_sum >= right_sum and left_sum >= cross_sum:
        return left_low, left_high, left_sum
    elif right_sum >= left_sum and right_sum >= cross_sum:
        return right_low, right_high, right_sum
    return cross_left, cross_right, cross_sum


def 			SCREAMING_SNAKE_CASE (			_UpperCAmelCase		,      _UpperCAmelCase		,      _UpperCAmelCase		,      _UpperCAmelCase					)     ->	tuple[int, int, float]:
    lowerCamelCase__					,				lowerCamelCase__       : Union[str, Any]   					=						float('-inf'					), -1
    lowerCamelCase__					,				lowerCamelCase__       : Tuple   					=						float('-inf'					), -1

    lowerCamelCase__       : int | float   					=						0
    for i in range(_UpperCAmelCase		,      low - 1		,      -1					):
        summ += arr[i]
        if summ > left_sum:
            lowerCamelCase__       : Optional[int]   					=						summ
            lowerCamelCase__       : Tuple   					=						i

    lowerCamelCase__       : int   					=						0
    for i in range(mid + 1		,      high + 1					):
        summ += arr[i]
        if summ > right_sum:
            lowerCamelCase__       : int   					=						summ
            lowerCamelCase__       : List[Any]   					=						i

    return max_left, max_right, (left_sum + right_sum)


def 			SCREAMING_SNAKE_CASE (			_UpperCAmelCase					)     ->	float:
    lowerCamelCase__       : Any   					=						[randint(1		,      _UpperCAmelCase					) for _ in range(_UpperCAmelCase					)]
    lowerCamelCase__       : Tuple   					=						time.time()
    max_subarray(_UpperCAmelCase		,      0		,      input_size - 1					)
    lowerCamelCase__       : List[Any]   					=						time.time()
    return end - start


def 			SCREAMING_SNAKE_CASE (			)     ->	None:
    lowerCamelCase__       : Optional[Any]   					=						[10, 100, 1000, 1_0000, 5_0000, 10_0000, 20_0000, 30_0000, 40_0000, 50_0000]
    lowerCamelCase__       : Optional[Any]   					=						[time_max_subarray(_UpperCAmelCase					) for input_size in input_sizes]
    print('No of Inputs\t\tTime Taken'					)
    for input_size, runtime in zip(_UpperCAmelCase		,      _UpperCAmelCase					):
        print(_UpperCAmelCase		,      '\t\t'		,      _UpperCAmelCase					)
    plt.plot(_UpperCAmelCase		,      _UpperCAmelCase					)
    plt.xlabel('Number of Inputs'					)
    plt.ylabel('Time taken in seconds'					)
    plt.show()


if __name__ == "__main__":
    from doctest import testmod

    testmod()





