leetcode

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

divide_arr_subarr_min_cost2.py (2801B)


# 3013. Divide an Array Into Subarrays With Minimum Cost II
import bisect

"""
you are given a 0 indexed array of integers 'nums' of length 'n', and two
positive integers 'k' and 'dist'. the cost of an array is the value of its
first element. for example, the cost of '1,2,3' is 1. you need to divide 'nums'
into 'k' disjoint contiguous subarrays, such that the difference between the
starting index of the second subarray and the starting index of the k'th
subarray should be less than or equal to 'dist'. in other words, if you divide
'nums' into the subarrays, then 'i_k-1 - i_1 <= dist'. return the minimum
possible sum of the cost of these subarrays.
"""


class Solution(object):
    class smart_window:
        def __init__(self, k):
            self.k = k
            self.low = []
            self.high = []
            self.sumLow = 0

        def window_size(self):
            return len(self.low) + len(self.high)

        def erase_one(self, arr, x):
            i = bisect.bisect_left(arr, x)
            if i < len(arr) and arr[i] == x:
                arr.pop(i)
                return True
            return False

        def rebalance(self):
            need = min(self.k, self.window_size())
            while len(self.low) > need:
                x = self.low.pop()
                self.sumLow -= x
                bisect.insort(self.high, x)
            while len(self.low) < need and self.high:
                x = self.high.pop(0)
                bisect.insort(self.low, x)
                self.sumLow += x

        def add(self, x):
            if not self.low or x <= self.low[-1]:
                bisect.insort(self.low, x)
                self.sumLow += x
            else:
                bisect.insort(self.high, x)
            self.rebalance()

        def remove(self, x):
            if self.erase_one(self.low, x):
                self.sumLow -= x
            else:
                self.erase_one(self.high, x)
            self.rebalance()

        def query(self):
            return self.sumLow

    def minimumCost(self, nums, k, dist):
        """
        :type nums: List[int]
        :type k: int
        :type dist: int
        :rtype: int
        """
        n = len(nums)
        k -= 1
        window = self.smart_window(k)
        for i in range(1, 1 + dist + 1):
            window.add(nums[i])
        ans = window.query()
        for i in range(2, n - dist):
            window.remove(nums[i - 1])
            window.add(nums[i + dist])
            ans = min(ans, window.query())
        return ans + nums[0]


if __name__ == "__main__":
    obj = Solution()
    print(obj.minimumCost(nums=[1, 3, 2, 6, 4, 2], k=3, dist=3))
    print(obj.minimumCost(nums=[10, 1, 2, 2, 2, 1], k=4, dist=3))
    print(obj.minimumCost(nums=[10, 8, 18, 9], k=3, dist=1))