leetcode

Leetcode Solutions (0x6A73)
git clone https://git.pngu.org/leetcode
Log | Files | Refs | Submodules | README

longest_balance_subarr2.py (2377B)


# 3721. Longest Balanced Subarray II

"""
you are given an integer array 'nums'. a subarray is called balance if the
number of distinct even numbers in the subarray is equal to the number of
distinct odd numbers. return the legnth of the longest balance subarray.
"""


class Solution(object):
    def longestBalanced(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        m = 1 << n.bit_length()
        mx = [0] * (m << 1)
        mn = [0] * (m << 1)
        lz = [0] * (m << 1)
        last = {}
        ans, curr = 0, 0

        def ctz(i):
            return (i & -i).bit_length() - 1

        def update(i, v):
            mx[i] += v
            mn[i] += v
            lz[i] += v

        def push(i):
            h = i.bit_length()
            i |= m
            while h:
                j = i >> h
                if t := lz[j]:
                    update(j << 1, t)
                    update(j << 1 | 1, t)
                    lz[j] = 0
                h -= 1

        def pull(i):
            i |= m
            while i > 1:
                i >>= 1
                mx[i] = max(mx[i << 1], mx[i << 1 | 1]) + lz[i]
                mn[i] = max(mn[i << 1], mn[i << 1 | 1]) + lz[i]

        def add(i, v):
            push(i)
            s, t = i | m, m << 1
            while s < t:
                z = ctz(s)
                s >>= z
                t >>= z
                if s == t:
                    break
                update(s, v)
                s += 1
            pull(i)

        def query(v):
            i = 1
            while i < m:
                if t := lz[i]:
                    update(i << 1, t)
                    update(i << 1 | 1, t)
                    lz[i] = 0
                i <<= 1
                if not mn[i] <= v <= mx[i]:
                    i |= 1
            return i - m

        for i, v in enumerate(nums, 1):
            x = 1 if v & 1 else -1
            if pi := last.get(v):
                curr -= x
                add(pi, -x)
            curr += x
            add(i, x)
            last[v] = i
            ans = max(ans, i - query(curr))
        return ans


if __name__ == "__main__":
    obj = Solution()
    print(obj.longestBalanced(nums=[2, 5, 4, 3]))
    print(obj.longestBalanced(nums=[3, 2, 2, 5, 4]))
    print(obj.longestBalanced(nums=[1, 2, 3, 2]))