<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>

struct Node {
    Node(int l, int r) : l(l), r(r) {}
    Node* left {nullptr};
    Node* right {nullptr};
    int l {0};
    int r {0};
    int val {0};
    bool lazy {false};
};

class Solution {
public:
    vector<int> fallingSquares(vector<vector<int>>& positions) {
        int n = positions.size(), mx = 0;
        for(const auto& pos : positions) {
            mx = max(mx, pos[0] + pos[1]);
        }
        Node *root = new Node(0, mx - 1);
        
        auto query = [&] (auto&& query, Node* cur, int L, int R) {
            if(L <= cur->l && cur->r <= R) {
                return cur->val;
            }
            int mid = cur->l + (cur->r - cur->l) / 2;
            if(!cur->left) {
                cur->left = new Node(cur->l, mid);
            }
            if(!cur->right) {
                cur->right = new Node(mid + 1, cur->r);
            }
            if(cur->lazy) {
                cur->left->val = cur->val;
                cur->right->val = cur->val;
                cur->left->lazy = true;
                cur->right->lazy = true;
                cur->lazy = false;
            }
            int mx = 0;
            if(L <= mid) {
                mx = max(mx, query(query, cur->left, L, R));
            }
            if(R > mid) {
                mx = max(mx, query(query, cur->right, L, R));
            }
            return mx;
        };
        auto update = [&] (auto&& update, Node* cur, int L, int R, int d) {
            if(L <= cur->l && cur->r <= R) {
                cur->lazy = true;
                cur->val = d;
                return;
            }
            int mid = cur->l + (cur->r - cur->l) / 2;
            if(!cur->left) {
                cur->left = new Node(cur->l, mid);
            }
            if(!cur->right) {
                cur->right = new Node(mid + 1, cur->r);
            }
            if(cur->lazy) {
                cur->left->val = cur->val;
                cur->right->val = cur->val;
                cur->left->lazy = true;
                cur->right->lazy = true;
                cur->lazy = false;
            }
            if(L <= mid) {
                update(update, cur->left, L, R, d);
            }
            if(R > mid) {
                update(update, cur->right, L, R, d);
            }
            cur->val = max(cur->left->val, cur->right->val);
        };

        vector<int> ans(n);
        for(int i=0; i<n; i++) {
            int l = positions[i][0], w = positions[i][1];
            int h = query(query, root, l, l + w - 1) + w;
            update(update, root, l, l + w - 1, h);
            ans[i] = root->val;
        }
        return ans;
    }
};
31965