from typing import List


def dna_union(
    start, end, audio_length: int, do_not_align_segments: List[dict],
) -> List[dict]:
    """ Return the DNA list to include [start,end] and exclude do_not_align_segments

    Given time range [start, end] to keep, and a list of do-not-align-segments to
    exclude, calculate the equivalent do-not-align-segment list to keeping only
    what's in [start, end], and removing both what's outside [start, end] and
    do_not_align_segments.

    Args:
        start (Optional[int]): the start time of the range to keep, None meaning 0,
            i.e., the beginning of the audio file
        end (Optional[int]): the end of the range to keep, None meaning the end of the audio file
        audio_length (int): the full length of the audio file
        do_not_align_segments (List[dict]): the original list of DNA segments

    Returns:
        List[dict]:
            the union of DNA lists [[0, start], [end, audio_length]] and do_not_align_segments
    """
    current_list = do_not_align_segments
    if start:
        new_list = []
        new_list.append({"begin": 0, "end": start})
        for seg in current_list:
            if seg["end"] <= start:
                pass  # dna segments that end before start are subsumed by [0,start)
            elif seg["begin"] <= start:
                start = seg["end"]
                new_list[0]["end"] = start
            else:
                new_list.append(seg)
        current_list = new_list
    if end:
        new_list = []
        for seg in current_list:
            if seg["begin"] >= end:
                pass  # dna segments after end are subsumed by [end, audio_length)
            elif seg["end"] >= end:
                end = seg["begin"]
            else:
                new_list.append(seg)
        new_list.append({"begin": end, "end": audio_length})
        current_list = new_list
    return current_list