class Solution:
def maxSumSubmatrix(self, matrix: List[List[int]], k: int) -> int:
""" tc O(C*C*R*lgR) => O(max(R,C)^2 * min(R,C) * lg(min(R,C))) sc O(R)
*** here assume rows >> cols
1. create an array to save prefix sum for each row
2. for psum[0] ... psum[right-1], find an idx s.t. psum[idx] >= psum[right] - k
3. compare with global maxv, find the max value that <= k
"""
rows, cols = len(matrix), len(matrix[0])
res = float('-inf')
for i in range(rows):
for j in range(cols-1):
matrix[i][j+1] += matrix[i][j]
for left in range(cols):
for right in range(left,cols):
# for one row, presum [left,right] array
arr = [matrix[row][right] - (matrix[row][left-1] if left > 0 else 0 ) for row in range(rows)]
res = max(res, self.maxSubarraySum(arr,k))
return res
def maxSubarraySum(self, A, k):
maxv = float('-inf')
psum = 0
sortedL = [0]
for a in A:
psum += a # psum_right
idx = bisect.bisect_left(sortedL, psum-k) #psum_right - psum_left <= k psum_right - k <= psum_left
if idx < len(sortedL):
maxv = max(maxv, psum - sortedL[idx]) #psum_right - psum_left
bisect.insort(sortedL, psum) # can use OrderedList to reduce time complexity to O(LgR)
return maxv