Use this to learn the idea, then write your own version.
123 4import bisect5 6 7class Solution(object):8 def fallingSquares(self, positions):9 result = []10 pos = [-1]11 heights = [0]12 maxH = 013 for left, side in positions:14 l = bisect.bisect_right(pos, left)15 r = bisect.bisect_left(pos, left+side)16 high = max(heights[l-1:r] or [0]) + side17 pos[l:r] = [left, left+side] 18 heights[l:r] = [high, heights[r-1]] 19 maxH = max(maxH, high)20 result.append(maxH)21 return result22 23 24class SegmentTree(object):25 def __init__(self, N,26 query_fn=min,27 update_fn=lambda x, y: y,28 default_val=float("inf")):29 self.N = N30 self.H = (N-1).bit_length()31 self.query_fn = query_fn32 self.update_fn = update_fn33 self.default_val = default_val34 self.tree = [default_val] * (2 * N)35 self.lazy = [None] * N36 37 def __apply(self, x, val):38 self.tree[x] = self.update_fn(self.tree[x], val)39 if x < self.N:40 self.lazy[x] = self.update_fn(self.lazy[x], val)41 42 def update(self, L, R, h):43 def pull(x):44 while x > 1:45 x = 246 self.tree[x] = self.query_fn(self.tree[x*2], self.tree[x*2 + 1])47 if self.lazy[x] is not None:48 self.tree[x] = self.update_fn(self.tree[x], self.lazy[x])49 50 L += self.N51 R += self.N52 L0, R0 = L, R53 while L <= R:54 if L & 1:55 self.__apply(L, h)56 L += 157 if R & 1 == 0:58 self.__apply(R, h)59 R -= 160 L = 261 R = 262 pull(L0)63 pull(R0)64 65 def query(self, L, R):66 def push(x):67 n = 2**self.H68 while n != 1:69 y = x n70 if self.lazy[y] is not None:71 self.__apply(y*2, self.lazy[y])72 self.__apply(y*2 + 1, self.lazy[y])73 self.lazy[y] = None74 n = 275 76 result = self.default_val77 if L > R:78 return result79 80 L += self.N81 R += self.N82 push(L)83 push(R)84 while L <= R:85 if L & 1:86 result = self.query_fn(result, self.tree[L])87 L += 188 if R & 1 == 0:89 result = self.query_fn(result, self.tree[R])90 R -= 191 L = 292 R = 293 return result94 95 def data(self):96 showList = []97 for i in xrange(self.N):98 showList.append(self.query(i, i))99 return showList100 101 102class SegmentTree2(object):103 def __init__(self, nums,104 query_fn=min,105 update_fn=lambda x, y: y,106 default_val=float("inf")):107 """108 initialize your data structure here.109 :type nums: List[int]110 """111 N = len(nums)112 self.__original_length = N113 self.__tree_length = 2**(N.bit_length() + (N&(N-1) != 0))-1114 self.__query_fn = query_fn115 self.__update_fn = update_fn116 self.__default_val = default_val117 self.__tree = [default_val for _ in range(self.__tree_length)]118 self.__lazy = [None for _ in range(self.__tree_length)]119 self.__constructTree(nums, 0, self.__original_length-1, 0)120 121 def update(self, i, j, val):122 self.__updateTree(val, i, j, 0, self.__original_length-1, 0)123 124 def query(self, i, j):125 return self.__queryRange(i, j, 0, self.__original_length-1, 0)126 127 def __constructTree(self, nums, left, right, idx):128 if left > right:129 return130 if left == right:131 self.__tree[idx] = self.__update_fn(self.__tree[idx], nums[left])132 return 133 mid = left + (right-left)2134 self.__constructTree(nums, left, mid, idx*2 + 1)135 self.__constructTree(nums, mid+1, right, idx*2 + 2)136 self.__tree[idx] = self.__query_fn(self.__tree[idx*2 + 1], self.__tree[idx*2 + 2])137 138 def __apply(self, left, right, idx, val):139 self.__tree[idx] = self.__update_fn(self.__tree[idx], val)140 if left != right:141 self.__lazy[idx*2 + 1] = self.__update_fn(self.__lazy[idx*2 + 1], val)142 self.__lazy[idx*2 + 2] = self.__update_fn(self.__lazy[idx*2 + 2], val)143 144 def __updateTree(self, val, range_left, range_right, left, right, idx):145 if left > right:146 return147 if self.__lazy[idx] is not None:148 self.__apply(left, right, idx, self.__lazy[idx])149 self.__lazy[idx] = None150 if range_left > right or range_right < left:151 return152 if range_left <= left and right <= range_right:153 self.__apply(left, right, idx, val)154 return155 mid = left + (right-left)2156 self.__updateTree(val, range_left, range_right, left, mid, idx*2 + 1)157 self.__updateTree(val, range_left, range_right, mid+1, right, idx*2 + 2)158 self.__tree[idx] = self.__query_fn(self.__tree[idx*2 + 1],159 self.__tree[idx*2 + 2])160 161 def __queryRange(self, range_left, range_right, left, right, idx):162 if left > right:163 return self.__default_val164 if self.__lazy[idx] is not None:165 self.__apply(left, right, idx, self.__lazy[idx])166 self.__lazy[idx] = None167 if right < range_left or left > range_right:168 return self.__default_val169 if range_left <= left and right <= range_right:170 return self.__tree[idx]171 mid = left + (right-left)2172 return self.__query_fn(self.__queryRange(range_left, range_right, left, mid, idx*2 + 1), 173 self.__queryRange(range_left, range_right, mid + 1, right, idx*2 + 2))174 175 176177178179class Solution2(object):180 def fallingSquares(self, positions):181 index = set()182 for left, size in positions:183 index.add(left)184 index.add(left+size-1)185 index = sorted(list(index))186 tree = SegmentTree(len(index), max, max, 0)187 188 max_height = 0189 result = []190 for left, size in positions:191 L, R = bisect.bisect_left(index, left), bisect.bisect_left(index, left+size-1)192 h = tree.query(L, R) + size193 tree.update(L, R, h)194 max_height = max(max_height, h)195 result.append(max_height)196 return result197 198 199200201class Solution3(object):202 def fallingSquares(self, positions):203 def query(heights, left, right, B, blocks, blocks_read):204 result = 0205 while left % B and left <= right:206 result = max(result, heights[left], blocks[leftB])207 left += 1208 while right % B != B-1 and left <= right:209 result = max(result, heights[right], blocks[rightB])210 right -= 1211 while left <= right:212 result = max(result, blocks[leftB], blocks_read[leftB])213 left += B214 return result215 216 def update(heights, left, right, B, blocks, blocks_read, h):217 while left % B and left <= right:218 heights[left] = max(heights[left], h)219 blocks_read[leftB] = max(blocks_read[leftB], h)220 left += 1221 while right % B != B-1 and left <= right:222 heights[right] = max(heights[right], h)223 blocks_read[rightB] = max(blocks_read[rightB], h)224 right -= 1225 while left <= right:226 blocks[leftB] = max(blocks[leftB], h)227 left += B228 229 index = set()230 for left, size in positions:231 index.add(left)232 index.add(left+size-1)233 index = sorted(list(index))234 W = len(index)235 B = int(W**.5)236 heights = [0] * W237 blocks = [0] * (B+2)238 blocks_read = [0] * (B+2)239 240 max_height = 0241 result = []242 for left, size in positions:243 L, R = bisect.bisect_left(index, left), bisect.bisect_left(index, left+size-1)244 h = query(heights, L, R, B, blocks, blocks_read) + size245 update(heights, L, R, B, blocks, blocks_read, h)246 max_height = max(max_height, h)247 result.append(max_height)248 return result249 250 251252253class Solution4(object):254 def fallingSquares(self, positions):255 """256 :type positions: List[List[int]]257 :rtype: List[int]258 """259 heights = [0] * len(positions)260 for i in xrange(len(positions)):261 left_i, size_i = positions[i]262 right_i = left_i + size_i263 heights[i] += size_i264 for j in xrange(i+1, len(positions)):265 left_j, size_j = positions[j]266 right_j = left_j + size_j267 if left_j < right_i and left_i < right_j: 268 heights[j] = max(heights[j], heights[i])269 270 result = []271 for height in heights:272 result.append(max(result[-1], height) if result else height)273 return result274 275