Leetcode: 2158. Amount of New Area Painted Each Day

Problem Statement

from typing import List


class SegTree:
    def __init__(self, left, right, count=0):
        self.left = left
        self.mid = left + (right - left) // 2
        self.right = right
        self.count = count
        self.left_child = self.right_child = None

    def add(self, left, right):
        if self.right < left or right < self.left:
            return 0
        if self.is_full() or left <= self.left <= self.right <= right:
            self.left_child = None
            self.right_child = None
            self.fill()
            return self.count
        self._extend()
        self.left_child.add(left, right)
        self.right_child.add(left, right)
        before = self.count
        after = self.count = self.left_child.count + self.right_child.count
        return after - before

    def is_full(self):
        return self.count == self.right - self.left + 1

    def fill(self):
        self.count = self.right - self.left + 1

    def _extend(self):
        if self.left_child is None and self.left < self.right:
            self.left_child = SegTree(self.left, self.mid)
            self.right_child = SegTree(self.mid + 1, self.right)
            if self.is_full():
                self.left_child.fill()
                self.right_child.fill()

    def _print(self, level=0):
        print(" " * level, (self.left, self.right), self.count)
        if self.left_child:
            self.left_child._print(level + 1)
            self.right_child._print(level + 1)


class Solution:
    def amountPainted(self, paint: List[List[int]]) -> List[int]:
        st = SegTree(0, 50_000 + 1)
        ans = []
        for start, end in paint:
            ans.append(st.add(start, end - 1))
        return ans


assert Solution().amountPainted([[1, 4], [4, 7], [5, 8]]) == [3, 3, 1]
assert Solution().amountPainted([[1, 4], [5, 8], [4, 7]]) == [3, 3, 1]
assert Solution().amountPainted([[1, 5], [2, 4]]) == [4, 0]
class Solution:
    def amountPainted(self, paint: List[List[int]]) -> List[int]:
        N = len(paint)
        nxt = [None for i in range(50_001)]
        ans = []
        for start, end in paint:
            cur = 0
            while start < end:
                if nxt[start] is None:
                    nxt[start] = end
                    cur += 1
                    start += 1
                else:
                    nstart = nxt[start]
                    nxt[start] = max(nxt[start], end)
                    start = nstart
            ans.append(cur)
        return ans
class Solution:
    def amountPainted(self, paint: List[List[int]]) -> List[int]:
        N = len(paint)
        p = [i for i in range(50_001)]
        ans = []

        def find(a):
            if p[a] == a:
                return a
            p[a] = find(p[a])
            return p[a]

        def union(a, b):
            assert b > a
            pa = find(a)
            pb = find(b)
            p[pa] = pb
            return pb

        for start, end in paint:
            cur = 0
            start = find(start)
            while start < end:
                start = union(start, start + 1)
                cur += 1
            ans.append(cur)
        return ans