- Choose the invariant that makes a window valid or useful.
- Advance the right boundary and add the new element.
- Move the left boundary only as needed while maintaining the invariant and updating the answer.
Code notes
- 77 lines of Python from the credited upstream file 2819.py.
- The implementation visibly relies on sequence storage.
- No explicit loop blocks detected.
Complexity
Confirm that neither pointer moves backwards; if so, the scan is usually linear apart from the window’s data-structure operations.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
1class Solution:2 def minimumRelativeLosses(3 self,4 prices: list[int],5 queries: list[list[int]],6 ) -> list[int]:7 ans = []8 9 prices.sort()10 11 prefix = list(itertools.accumulate(prices, initial=0))12 13 for k, m in queries:14 countFront = self._getCountFront(k, m, prices)15 countBack = m - countFront16 ans.append(self._getRelativeLoss(countFront, countBack, k, prefix))17 18 return ans19 20 def _getCountFront(21 self,22 k: int,23 m: int,24 prices: list[int],25 ) -> int:26 """Returns `countFront` for query (k, m).27 28 Returns `countFront` for query (k, m) s.t. picking the first `countFront`29 and the last `m - countFront` chocolates is optimal.30 31 Define loss[i] := the relative loss of picking `prices[i]`.32 1. For prices[i] <= k, Bob pays prices[i] while Alice pays 0.33 Thus, loss[i] = prices[i] - 0 = prices[i].34 2. For prices[i] > k, Bob pays k while Alice pays prices[i] - k.35 Thus, loss[i] = k - (prices[i] - k) = 2 * k - prices[i].36 By observation, we deduce that it is always better to pick from the front37 or the back since loss[i] is increasing for 1. and is decreasing for 2.38 39 Assume that picking `left` chocolates from the left and `right = m - left`40 chocolates from the right is optimal. Therefore, we are selecting41 chocolates from `prices[0..left - 1]` and `prices[n - right..n - 1]`.42 43 To determine the optimal `left` in each iteration, we simply compare44 `loss[left]` with `loss[n - right]` if `loss[left] < loss[n - right]`,45 it's worth increasing `left`.46 """47 n = len(prices)48 countNoGreaterThanK = bisect.bisect_right(prices, k)49 l = 050 r = min(countNoGreaterThanK, m)51 52 while l < r:53 mid = (l + r) 254 right = m - mid55 56 if prices[mid] < 2 * k - prices[n - right]:57 l = mid + 158 else:59 r = mid60 61 return l62 63 def _getRelativeLoss(64 self,65 countFront: int,66 countBack: int,67 k: int,68 prefix: list[int],69 ) -> int:70 """71 Returns the relative loss of picking `countFront` and `countBack` 72 chocolates.73 """74 lossFront = prefix[countFront]75 lossBack = 2 * k * countBack - (prefix[-1] - prefix[-countBack - 1])76 return lossFront + lossBack77