<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 segmentTreeNode{
        public:
        int start, end, info, tag;
        segmentTreeNode *left, *right;
        segmentTreeNode(int a, int b): start(a), end(b), info(0), tag(0), left(NULL), right(NULL){}
    };

    void init(segmentTreeNode* node, int a, int b){
        if(a==b){
            node->info = 0;
            return;
        }
        int mid = (a+b)/2;
        if(node->left==NULL){
            node->left = new segmentTreeNode(a, mid);
            node->right = new segmentTreeNode(mid+1, b);
        }
        init(node->left, a, mid);
        init(node->right, mid+1, b);
        node->info = 0;
    }

    void pushdown(segmentTreeNode* node){
        if(node->tag==1){
            node->left->info = node->info;
            node->right->info = node->info;
            node->left->tag = 1;
            node->right->tag = 1;
            node->tag = 0;
        }
    }

    int queryRange(segmentTreeNode* node, int a, int b){
        if(b<node->start||a>node->end){
            return 0;
        }
        if(node->start>=a&&node->end<=b){
            return node->info;
        }

        pushdown(node);
        return max(queryRange(node->left, a, b), queryRange(node->right, a, b));
    }

    void updateRange(segmentTreeNode* node, int a, int b, int val){
        if(b<node->start||a>node->end){return;}

        if(node->start>=a&&node->end<=b){
            node->info = val;
            node->tag = 1;
            return;
        }

        pushdown(node);
        updateRange(node->left, a, b, val);
        updateRange(node->right, a, b, val);
        node->info = max(node->left->info, node->right->info);
    }

    segmentTreeNode *root;
    vector<int> fallingSquares(vector<vector<int>>& positions) {
        set<int> Set;

        for(auto p: positions){
            Set.insert(p[0]);
            Set.insert(p[0]+p[1]);
        }

        int n=0;
        map<int ,int> pos2idx;
        for(int i: Set){
            pos2idx[i] = n++;
        }

        root = new segmentTreeNode(0, n-1);
        init(root, 0, n-1);

        vector<int> res;
        int cur=0;
        for(auto p: positions){
            int left = pos2idx[p[0]], right = pos2idx[p[0]+p[1]]-1;
            int h=queryRange(root, left, right);
            updateRange(root, left, right, h+p[1]);
            cur = max(cur, h+p[1]);
            res.push_back(cur);
        }
        return res;
    }
};
25045