<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 {
public:
    class segNode {
    public:
        segNode* left;
        segNode* right;
        int val, lazy;
        
        segNode(int v) {
            left = right = NULL;
            val = lazy = v;  // Initialize both value and lazy
        }

        // Push lazy values to children if needed
        void push(segNode* node, int nl, int nr) {
            if (node->lazy != 0) {
                if (!node->left) {
                    int mid = (nl + nr) / 2;
                    node->left = new segNode(node->lazy);
                    node->right = new segNode(node->lazy);
                } else {
                    node->left->lazy = max(node->left->lazy, node->lazy);
                    node->right->lazy = max(node->right->lazy, node->lazy);
                    node->left->val = max(node->left->val, node->lazy);
                    node->right->val = max(node->right->val, node->lazy);
                }
                node->lazy = 0;
            }
        }

        // Update the range with lazy propagation
        void update(segNode* node, int v, int l, int r, int nl, int nr) {
            if (r < nl || l > nr) {
                return;  // No overlap
            }
            if (l <= nl && nr <= r) {  // Complete overlap
                node->val = max(node->val, v);
                node->lazy = max(node->lazy, v);  // Mark lazy value for propagation
                return;
            }

            push(node, nl, nr);  // Push lazy values to children before further updating

            int mid = (nl + nr) / 2;
            if (!node->left) {
                node->left = new segNode(node->val);
                node->right = new segNode(node->val);
            }
            update(node->left, v, l, r, nl, mid);    // Update left child
            update(node->right, v, l, r, mid + 1, nr);  // Update right child

            node->val = max(node->left->val, node->right->val);  // Recalculate the value
        }

        // Query the range with lazy propagation
        int query(segNode* node, int l, int r, int nl, int nr) {
            if (r < nl || l > nr) return 0;  // No overlap
            if (l <= nl && r >= nr) return node->val;  // Complete overlap

            push(node, nl, nr);  // Push lazy values to children before querying

            int mid = (nl + nr) / 2;
            if (!node->left) {
                node->left = new segNode(node->val);
                node->right = new segNode(node->val);
            }
            return max(query(node->left, l, r, nl, mid), 
                       query(node->right, l, r, mid + 1, nr));  // Query both children
        }
    };
    
    segNode* root;

    vector<int> fallingSquares(vector<vector<int>>& positions) {
        vector<int> ans;
        root = new segNode(0);  // Initialize the root node with value 0
        int maxHeight = 0;

        for (auto& p : positions) {
            int left = p[0];
            int side = p[1];
            int right = left + side - 1;

            // Query the maximum height in the range [left, right]
            int mx = root->query(root, left, right, 1, 200000000);

            // Update the range [left, right] with the new height
            root->update(root, mx + side, left, right, 1, 200000000);

            // Track the overall maximum height after this square lands
            maxHeight = max(maxHeight, mx + side);
            ans.push_back(maxHeight);
        }

        return ans;
    }
};

35425