Falling Squares

hard array segment tree ordered set

Problem

positions[i] = [left, sideLength] means a square with side sideLength drops on the number line so its left edge is at left. Squares stack on top of any blocks under their footprint. After each drop, record the tallest height on the line so far.

Inputpositions = [[1,2], [2,3], [6,1]]
Output[2, 5, 5]
First drop reaches h=2. Second sits on first → top = 2 + 3 = 5. Third lands on the floor at h=1 but max stays 5.

def falling_squares(positions):
    intervals = []  # list of (left, right, height)
    best = 0
    ans = []
    for left, side in positions:
        right = left + side
        base = 0
        for (l, r, h) in intervals:
            if l < right and left < r:
                base = max(base, h)
        top = base + side
        intervals.append((left, right, top))
        best = max(best, top)
        ans.append(best)
    return ans
function fallingSquares(positions) {
  const intervals = [];
  let best = 0;
  const ans = [];
  for (const [left, side] of positions) {
    const right = left + side;
    let base = 0;
    for (const [l, r, h] of intervals) {
      if (l < right && left < r) base = Math.max(base, h);
    }
    const top = base + side;
    intervals.push([left, right, top]);
    if (top > best) best = top;
    ans.push(best);
  }
  return ans;
}
class Solution {
    public List<Integer> fallingSquares(int[][] positions) {
        List<int[]> intervals = new ArrayList<>();
        List<Integer> ans = new ArrayList<>();
        int best = 0;
        for (int[] p : positions) {
            int left = p[0], side = p[1], right = left + side, base = 0;
            for (int[] iv : intervals) if (iv[0] < right && left < iv[1]) base = Math.max(base, iv[2]);
            int top = base + side;
            intervals.add(new int[]{left, right, top});
            best = Math.max(best, top);
            ans.add(best);
        }
        return ans;
    }
}
vector<int> fallingSquares(vector<vector<int>>& positions) {
    vector<tuple<int,int,int>> intervals;
    vector<int> ans;
    int best = 0;
    for (auto& p : positions) {
        int left = p[0], side = p[1], right = left + side, base = 0;
        for (auto& [l, r, h] : intervals) if (l < right && left < r) base = max(base, h);
        int top = base + side;
        intervals.push_back({left, right, top});
        best = max(best, top);
        ans.push_back(best);
    }
    return ans;
}
Time: O(n^2) (segment tree: O(n log n)) Space: O(n)