code: def union_rectangles(R):
      
      if R == []:
          return 0
      X = []
      Y = []
      for j in range(len(R)):
          (x1, y1, x2, y2) = R[j]
          assert x1 <= x2 and y1 <= y2
          X.append(x1)
          X.append(x2)
          Y.append((y1, +1, j))    # generate events
          Y.append((y2, -1, j))
      X.sort()
      Y.sort()
      X2i = {X[i]: i for i in range(len(X))}
      L = [X[i + 1] - X[i] for i in range(len(X) - 1)]
      C = Cover_query(L)
      area = 0
      last = 0
      for (y, delta, j) in Y:
          area += (y - last) * C.cover()
          last = y
          (x1, y1, x2, y2) = R[j]
          i = X2i[x1]
          k = X2i[x2]
          C.change(i, k, delta)
      return area
docs: Area of union of rectangles
  
      :param R: list of rectangles defined by (x1, y1, x2, y2)
         where (x1, y1) is top left corner and (x2, y2) bottom right corner
      :returns: area
      :complexity: :math:`O(n^2)`