<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 segment_tree {
  int start, end;
  int height;
  segment_tree *left_tree, *right_tree;
 public:
  segment_tree(int start, int end, int height): start(start), end(end), height(height), left_tree(nullptr), right_tree(nullptr) {}
  int max_height(int left, int right) const {
    if (end == start + 1) {
      return height;
    }
    int mid = (start + end) / 2;
    if (left >= mid) { // right only
      if (right_tree) {
        return right_tree->max_height(left, right);
      }
      return height;
    } else if (right <= mid) { // left only
      if (left_tree) {
        return left_tree->max_height(left, right);
      }
      return height;
    } else {
      int a = height;
      if (left_tree) {
        a = max(a, left_tree->max_height(left, mid));
      }
      if (right_tree) {
        a = max(a, right_tree->max_height(mid, right));
      }
      return a;
    }
  }
  void raise_to(int left, int right, int height) {
    left = max(left, start);
    right = min(right, end);
    if (start == left && end == right || end - start == 1) {
      this->height = height;
      if (this->left_tree) {
        this->left_tree = nullptr;
      }
      if (this->right_tree) {
        this->right_tree = nullptr;
      }
      return;
    }
    int mid = (start + end) / 2;
    if (right > mid) {
      if (!right_tree) {
        right_tree = new segment_tree(mid, end, this->height);
      }
      right_tree->raise_to(left, right, height);
    }
    if (left < mid) {
      if (!left_tree) {
        left_tree = new segment_tree(start, mid, this->height);
      }
      left_tree->raise_to(left, right, height);
    }
  }
};


class Solution {
public:
    vector<int> fallingSquares(vector<vector<int>>& positions) {
        set<int> xs;
        for (const auto& p: positions) {
            xs.insert(p[0]);
            xs.insert(p[0] + p[1]);
        }
        int n = xs.size();
        unordered_map<int, int> xmap;
        int i = 0;
        for (int x: xs) {
            xmap[x] = i++;
        }
        segment_tree tree(0, n, 0);
        vector<int> result;
        int max_height = 0;
        for (const auto& p: positions) {
            int max = tree.max_height(xmap[p[0]], xmap[p[0] + p[1]]) + p[1];
            if (max > max_height) {
                max_height = max;
            }
            tree.raise_to(xmap[p[0]], xmap[p[0] + p[1]], max);
            result.push_back(max_height);
        }
        return result;
    }
};
21585