<p>There are several squares being dropped onto the X-axis of a 2D plane.</p>

<p>You are given a 2D integer array <code>positions</code> where <code>positions[i] = [left<sub>i</sub>, sideLength<sub>i</sub>]</code> represents the <code>i<sup>th</sup></code> square with a side length of <code>sideLength<sub>i</sub></code> that is dropped with its left edge aligned with X-coordinate <code>left<sub>i</sub></code>.</p>

<p>Each square is dropped one at a time from a height above any landed squares. It then falls downward (negative Y direction) until it either lands <strong>on the top side of another square</strong> or <strong>on the X-axis</strong>. A square brushing the left/right side of another square does not count as landing on it. Once it lands, it freezes in place and cannot be moved.</p>

<p>After each square is dropped, you must record the <strong>height of the current tallest stack of squares</strong>.</p>

<p>Return <em>an integer array </em><code>ans</code><em> where </em><code>ans[i]</code><em> represents the height described above after dropping the </em><code>i<sup>th</sup></code><em> square</em>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2021/04/28/fallingsq1-plane.jpg" style="width: 500px; height: 505px;" />
<pre>
<strong>Input:</strong> positions = [[1,2],[2,3],[6,1]]
<strong>Output:</strong> [2,5,5]
<strong>Explanation:</strong>
After the first drop, the tallest stack is square 1 with a height of 2.
After the second drop, the tallest stack is squares 1 and 2 with a height of 5.
After the third drop, the tallest stack is still squares 1 and 2 with a height of 5.
Thus, we return an answer of [2, 5, 5].
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> positions = [[100,100],[200,100]]
<strong>Output:</strong> [100,100]
<strong>Explanation:</strong>
After the first drop, the tallest stack is square 1 with a height of 100.
After the second drop, the tallest stack is either square 1 or square 2, both with heights of 100.
Thus, we return an answer of [100, 100].
Note that square 2 only brushes the right side of square 1, which does not count as landing on it.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= positions.length &lt;= 1000</code></li>
	<li><code>1 &lt;= left<sub>i</sub> &lt;= 10<sup>8</sup></code></li>
	<li><code>1 &lt;= sideLength<sub>i</sub> &lt;= 10<sup>6</sup></code></li>
</ul>

class Solution:
    def fallingSquares(self, positions):
        # Coordinates compression
        coordinates = set()
        for left, side in positions:
            coordinates.add(left)
            coordinates.add(left + side - 1)
        index = {x: i for i, x in enumerate(sorted(coordinates))}

        # Segment Tree implementation
        class SegmentTree:
            def __init__(self, n):
                self.max_height = [0] * (4 * n)
                self.lazy = [0] * (4 * n)
                self.n = n

            def update(self, left, right, val, node=0, node_left=0, node_right=None):
                if node_right is None:
                    node_right = self.n - 1
                if node_right < node_left:
                    return
                if self.lazy[node] != 0:
                    self.max_height[node] = max(self.max_height[node], self.lazy[node])
                    if node_left != node_right:
                        self.lazy[2 * node + 1] = max(self.lazy[2 * node + 1], self.lazy[node])
                        self.lazy[2 * node + 2] = max(self.lazy[2 * node + 2], self.lazy[node])
                    self.lazy[node] = 0
                if right < node_left or node_right < left:
                    return
                if left <= node_left and node_right <= right:
                    self.max_height[node] = max(self.max_height[node], val)
                    if node_left != node_right:
                        self.lazy[2 * node + 1] = max(self.lazy[2 * node + 1], val)
                        self.lazy[2 * node + 2] = max(self.lazy[2 * node + 2], val)
                    return
                mid = (node_left + node_right) // 2
                self.update(left, right, val, 2 * node + 1, node_left, mid)
                self.update(left, right, val, 2 * node + 2, mid + 1, node_right)
                self.max_height[node] = max(self.max_height[2 * node + 1], self.max_height[2 * node + 2])

            def query(self, left, right, node=0, node_left=0, node_right=None):
                if node_right is None:
                    node_right = self.n - 1
                if right < node_left or node_right < left:
                    return 0
                if self.lazy[node] != 0:
                    self.max_height[node] = max(self.max_height[node], self.lazy[node])
                    if node_left != node_right:
                        self.lazy[2 * node + 1] = max(self.lazy[2 * node + 1], self.lazy[node])
                        self.lazy[2 * node + 2] = max(self.lazy[2 * node + 2], self.lazy[node])
                    self.lazy[node] = 0
                if left <= node_left and node_right <= right:
                    return self.max_height[node]
                mid = (node_left + node_right) // 2
                return max(self.query(left, right, 2 * node + 1, node_left, mid),
                           self.query(left, right, 2 * node + 2, mid + 1, node_right))

        n = len(index)
        segment_tree = SegmentTree(n)
        max_height = 0
        ans = []

        for left, side in positions:
            i = index[left]
            j = index[left + side - 1]
            pre_height = segment_tree.query(i, j)
            new_height = pre_height + side
            segment_tree.update(i, j, new_height)
            max_height = max(max_height, new_height)
            ans.append(max_height)

        return ans

# Example usage:
solution = Solution()
positions = [[1, 2], [2, 3], [6, 1]]
print(solution.fallingSquares(positions))  # Output: [2, 5, 5]

positions = [[100, 100], [200, 100]]
print(solution.fallingSquares(positions))  # Output: [100, 100]
17700