← Home
```go
package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
)

// event represents a vertical line sweep event.
// type_: 1 for adding a segment, -1 for removing.
type event struct {
	x, type_, y1, y2 int
}

// node represents a segment tree node.
// cnt: number of active rectangles covering this range completely.
// len: length of the covered Y-interval within this node's range.
type node struct {
	cnt, len int
}

var (
	tree []node
	ys   []int
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	writer := bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	var n int
	fmt.Fscan(reader, &n)

	events := make([]event, 0, 2*n)
	ys = make([]int, 0, 2*n)

	for i := 0; i < n; i++ {
		var x1, y1, x2, y2 int
		fmt.Fscan(reader, &x1, &y1, &x2, &y2)
		
		// Normalize coordinates so x1 <= x2 and y1 <= y2
		if x1 > x2 {
			x1, x2 = x2, x1
		}
		if y1 > y2 {
			y1, y2 = y2, y1
		}
		
		// The problem defines segments of width 1 square.
		// A segment from x1 to x2 covers cells [x1, x2].
		// In continuous coordinates, this corresponds to the interval [x1, x2 + 1).
		// Same for y.
		x2++
		y2++
		
		events = append(events, event{x: x1, type_: 1, y1: y1, y2: y2})
		events = append(events, event{x: x2, type_: -1, y1: y1, y2: y2})
		ys = append(ys, y1, y2)
	}

	// Coordinate compression for Y values
	sort.Ints(ys)
	uniqueYs := 0
	if len(ys) > 0 {
		uniqueYs = 1
		for i := 1; i < len(ys); i++ {
			if ys[i] != ys[i-1] {
				ys[uniqueYs] = ys[i]
				uniqueYs++
			}
		}
		ys = ys[:uniqueYs]
	}

	// Sort events by x coordinate
	sort.Slice(events, func(i, j int) bool {
		return events[i].x < events[j].x
	})

	if len(ys) < 2 {
		fmt.Fprintln(writer, 0)
		return
	}

	// Initialize segment tree
	// The tree manages intervals between sorted unique Y coordinates.
	// There are len(ys)-1 elementary intervals.
	tree = make([]node, 4*len(ys))
	
	var ans int64
	prevX := events[0].x

	for _, e := range events {
		width := e.x - prevX
		
		// Add area covered in the strip [prevX, e.x)
		if width > 0 {
			ans += int64(width) * int64(tree[1].len)
		}

		// Update the active intervals in the segment tree
		idx1 := sort.SearchInts(ys, e.y1)
		idx2 := sort.SearchInts(ys, e.y2)

		// We want to update the range of elementary intervals [idx1, idx2-1]
		if idx1 < idx2 {
			update(1, 0, len(ys)-2, idx1, idx2-1, e.type_)
		}
		prevX = e.x
	}

	fmt.Fprintln(writer, ans)
}

// update modifies the coverage count in the segment tree
// v: current node index
// tl, tr: current node's range of leaf indices (elementary intervals)
// l, r: target range of leaf indices to update
// add: +1 or -1
func update(v, tl, tr, l, r, add int) {
	if l > r {
		return
	}
	if l == tl && r == tr {
		tree[v].cnt += add
	} else {
		tm := (tl + tr) / 2
		update(2*v, tl, tm, l, min(r, tm), add)
		update(2*v+1, tm+1, tr, max(l, tm+1), r, add)
	}
	pushUp(v, tl, tr)
}

// pushUp recalculates the covered length of the node based on its children and count
func pushUp(v, tl, tr int) {
	if tree[v].cnt > 0 {
		// If this node is fully covered, its length is the full Y range it spans
		tree[v].len = ys[tr+1] - ys[tl]
	} else {
		// If not fully covered, length is sum of children's lengths (if not leaf)
		if tl != tr {
			tree[v].len = tree[2*v].len + tree[2*v+1].len
		} else {
			tree[v].len = 0
		}
	}
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}
```