Description
You are given a 2D integer array squares. Each squares[i] = [xi, yi, li] represents the coordinates of the bottom-left point and the side length of a square parallel to the x-axis.
Find the minimum y-coordinate value of a horizontal line such that the total area covered by squares above the line equals the total area covered by squares below the line.
Answers within 10-5 of the actual answer will be accepted.
Note: Squares may overlap. Overlapping areas should be counted only once in this version.
Example 1:
Input: squares = [[0,0,1],[2,2,1]]
Output: 1.00000
Explanation:

Any horizontal line between y = 1 and y = 2 results in an equal split, with 1 square unit above and 1 square unit below. The minimum y-value is 1.
Example 2:
Input: squares = [[0,0,2],[1,1,1]]
Output: 1.00000
Explanation:

Since the blue square overlaps with the red square, it will not be counted again. Thus, the line y = 1 splits the squares into two equal parts.
Constraints:
1 <= squares.length <= 5 * 104squares[i] = [xi, yi, li]squares[i].length == 30 <= xi, yi <= 1091 <= li <= 109- The total area of all the squares will not exceed
1015.
Solutions
This solution uses a segment tree combined with a sweep line algorithm to find the optimal horizontal line that splits a collection of squares into two regions with equal (or nearly equal) total area. The SegmentTree class efficiently tracks which x-coordinate ranges are currently covered as the algorithm sweeps vertically through y-coordinates. For each square, two events are generated: one when the sweep enters the square (at y) and one when it exits (at y + length). As the sweep progresses, the algorithm accumulates the total area covered and records the covered width at each event. Finally, it uses binary search to find the y-coordinate where the cumulative area reaches half the total, then calculates the exact y-value through linear interpolation within the final segment.
/**
* @param {number[][]} squares
* @return {number}
*/
class SegmentTree {
constructor(xs) {
this.xs = xs; // sorted x coordinates
this.n = xs.length - 1;
this.count = new Array(4 * this.n).fill(0);
this.covered = new Array(4 * this.n).fill(0);
}
update(qleft, qright, qval, left, right, pos) {
if (this.xs[right + 1] <= qleft || this.xs[left] >= qright) {
return; // no overlap
}
if (qleft <= this.xs[left] && this.xs[right + 1] <= qright) {
this.count[pos] += qval;
} else {
const mid = Math.floor((left + right) / 2);
this.update(qleft, qright, qval, left, mid, pos * 2 + 1);
this.update(qleft, qright, qval, mid + 1, right, pos * 2 + 2);
}
if (this.count[pos] > 0) {
this.covered[pos] = this.xs[right + 1] - this.xs[left];
} else {
if (left === right) {
this.covered[pos] = 0;
} else {
this.covered[pos] =
this.covered[pos * 2 + 1] + this.covered[pos * 2 + 2];
}
}
}
query() {
return this.covered[0];
}
}
var separateSquares = function (squares) {
// save events: [y-coordinate, type, left boundary, right boundary]
const events = [];
const xsSet = new Set();
for (const sq of squares) {
const [x, y, l] = sq;
const xr = x + l;
events.push([y, 1, x, xr]);
events.push([y + l, -1, x, xr]);
xsSet.add(x);
xsSet.add(xr);
}
// sort events by y-coordinate
events.sort((a, b) => a[0] - b[0]);
// discrete coordinates
const xs = Array.from(xsSet).sort((a, b) => a - b);
// initialize the segment tree
const segTree = new SegmentTree(xs);
const psum = [];
const widths = [];
let total_area = 0;
let prev = events[0][0];
// scan: calculate total area and record intermediate states
for (const event of events) {
const [y, delta, xl, xr] = event;
const length = segTree.query();
total_area += length * (y - prev);
segTree.update(xl, xr, delta, 0, segTree.n - 1, 0);
// record prefix sums and widths
psum.push(total_area);
widths.push(segTree.query());
prev = y;
}
// calculate the target area (half rounded up)
const target = Math.floor((total_area + 1) / 2);
// find the first position greater than or equal to target using binary search
let left = 0,
right = psum.length - 1;
let i = 0;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (psum[mid] < target) {
i = mid;
left = mid + 1;
} else {
right = mid - 1;
}
}
// get the corresponding area, width, and height
const area = psum[i];
const width = widths[i];
const height = events[i][0];
return height + (total_area - area * 2) / (width * 2.0);
};