- Choose the aggregate stored for each interval or prefix.
- Build or initialize the structure from the input.
- Apply updates and combine the affected nodes to answer each query.
Code notes
- 78 lines of Python from the credited upstream file minimum-operations-to-equalize-subarrays.py.
- The implementation visibly relies on sequence storage, ordered lookup.
- No explicit loop blocks detected.
Complexity
Count the build once, then multiply the logarithmic update or query path by the number of operations.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
123 45class PersistentSegmentTree(object):6 LEFT, RIGHT, CNT, TOTAL = range(4)7 8 def __init__(self, vals):9 self.sorted_unique_vals = sorted(set(vals))10 self.val_to_idx = {x: i for i, x in enumerate(self.sorted_unique_vals)}11 self.n = len(self.val_to_idx)12 self.roots = []13 self.__build(vals)14 15 def __new_node(self):16 return [None, None, 0, 0]17 18 def __build(self, vals):19 root = self.__new_node()20 self.roots.append(root)21 for x in vals:22 root = root[:]23 self.roots.append(root)24 curr = root25 left, right = 0, self.n-126 i = self.val_to_idx[x]27 while left < right:28 curr[self.CNT] += 129 curr[self.TOTAL] += x30 mid = left+(right-left)231 if i <= mid:32 curr[self.LEFT] = curr = curr[self.LEFT][:] if curr[self.LEFT] else self.__new_node()33 right = mid34 else:35 curr[self.RIGHT] = curr = curr[self.RIGHT][:] if curr[self.RIGHT] else self.__new_node()36 left = mid+137 curr[self.CNT] += 138 curr[self.TOTAL] += x39 40 def query(self, l, r):41 a, b = self.roots[l], self.roots[r+1]42 left_cnt = left_total = 043 med_cnt = (r-l+1)2+144 left, right = 0, self.n-145 while left < right:46 mid = left+(right-left)247 cnt = ((b[self.LEFT][self.CNT] if b and b[self.LEFT] else 0)-48 (a[self.LEFT][self.CNT] if a and a[self.LEFT] else 0))49 if med_cnt <= cnt:50 a = a[self.LEFT] if a else None51 b = b[self.LEFT] if b else None52 right = mid53 else:54 med_cnt -= cnt55 left_cnt += cnt56 left_total += ((b[self.LEFT][self.TOTAL] if b and b[self.LEFT] else 0)-57 (a[self.LEFT][self.TOTAL] if a and a[self.LEFT] else 0))58 a = a[self.RIGHT] if a else None59 b = b[self.RIGHT] if b else None60 left = mid+161 return ((self.sorted_unique_vals[left]*left_cnt-left_total)+((self.roots[r+1][self.TOTAL]-62 self.roots[l][self.TOTAL]-left_total)-self.sorted_unique_vals[left]*((r-l+1)-left_cnt)))63 64 65class Solution(object):66 def minOperations(self, nums, k, queries):67 """68 :type nums: List[int]69 :type k: int70 :type queries: List[List[int]]71 :rtype: List[int]72 """73 prefix = [0]*(len(nums)+1)74 for i, x in enumerate(nums):75 prefix[i+1] = prefix[i]+(1 if i-1 >= 0 and nums[i]%k != nums[i-1]%k else 0)76 pst = PersistentSegmentTree([xk for x in nums])77 return [pst.query(s, t) if prefix[t+1]-prefix[s+1] == 0 else -1 for s, t in queries]78