Search lands in PR-5.1 (Pagefind).

How-to Advanced

Chapter 2 Updated

Rectangle Area II

Sweep x-events; at each x compute active y-coverage × x-delta.

  • Full 7m
  • Revision
  • Flow

Problem Statement

Given a list of axis-aligned rectangles as [x1, y1, x2, y2] (bottom-left and top-right corners), compute the total area covered by their union. The answer must be returned modulo 10⁹ + 7.

Input

An array of rectangles.

Example input
[[0,0,2,2],[1,0,2,3],[1,0,3,1]]

Output

A single integer — the total covered area modulo 10⁹ + 7.

Expected output
6

Constraints

  • 1 ≤ rectangles.length ≤ 200
  • rectanglesᵢ.length == 4
  • 0 ≤ x1ᵢ, y1ᵢ, x2ᵢ, y2ᵢ ≤ 10⁹
  • x1ᵢ < x2ᵢ, y1ᵢ < y2ᵢ.

Intuition

Extend 1-D sweep line into 2-D. Generate open / close events sorted by x. As you sweep:

  1. At each event, compute the merged y-coverage of currently active rectangles.
  2. Multiply y_coverage × (x − prev_x) and add to the running area.
  3. Then add or remove the event’s rectangle from the active set.

Merging the active y-intervals is another pass of the “merge intervals” primitive, so the inner loop runs in O(n) worst case per event.

Anatomy of one x-delta slice
At a given x, suppose active y-intervals are [0,2], [1,3].
Merged y-coverage: [0,3] → length 3.
Next event at x'.
Area contribution: 3 × (x' − x).

Solution

rectangle_area_ii.py
def rectangleArea(rectangles: list[list[int]]) -> int:
    MOD = 10**9 + 7
    events = []
    for x1, y1, x2, y2 in rectangles:
        events.append((x1, 0, y1, y2))   # open
        events.append((x2, 1, y1, y2))   # close
    events.sort()
 
    active, area, prev_x = [], 0, events[0][0]
    for x, typ, y1, y2 in events:
        # Merge active y-intervals and compute covered length
        y_cover = cur = 0
        for ay1, ay2 in sorted(active):
            cur = max(cur, ay1)
            y_cover += max(0, ay2 - cur)
            cur = max(cur, ay2)
 
        area += y_cover * (x - prev_x)
        prev_x = x
 
        if typ == 0:
            active.append((y1, y2))
        else:
            active.remove((y1, y2))
 
    return area % MOD

Complexity

MetricValueReason
TimeO(n²)Inner merge-and-scan over active list per event
SpaceO(n)Events list + active set

Edge Case Thinking

ScenarioHandling
Single rectangleOne slice — area = (x2 − x1) × (y2 − y1).
Two disjoint rectanglesActive set grows and shrinks; y-coverage correctly sums them separately.
Fully contained rectangleAdding it doesn’t change the merged y-coverage.
Rectangles sharing an edgeEvents sorted with opens before closes at the same x keeps the coverage continuous.
Huge coordinates10⁹ inputs don’t overflow because multiplications stay within int64; MOD is applied once per slice.

Comments

Comments are disabled in this environment. Set PUBLIC_GISCUS_REPO, PUBLIC_GISCUS_REPO_ID, and PUBLIC_GISCUS_CATEGORY_ID to enable.