#include <bits/stdc++.h>
using namespace std;
 
// Template Headers {{{
using pii = pair<int, int>; using vpii = vector<pii>;
using vi = vector<int>; using vvi = vector<vi>;
using ll = long long; using vll = vector<long long>;
template <class T> using min_queue = priority_queue<T, vector<T>, greater<T>>;
template <class T> istream &operator>>(istream &, vector<T> &);
template <class T> ostream &operator<<(ostream &, const vector<T> &);
template <class T, class U> istream &operator>>(istream &, pair<T, U> &);
template <class T, class U> ostream &operator<<(ostream &, const pair<T, U> &);
template <class T> struct Inf { static constexpr T inf() { return std::numeric_limits<T>::has_infinity() ? std::numeric_limits<T>::infinty() : std::numeric_limits<T>::max(); } };
template <> struct Inf<int> { static constexpr int inf() { return 0x3f3f3f3f; } };
template <> struct Inf<long long> { static constexpr long long inf() { return 0x3f3f3f3f3f3f3f3fLL; } };
constexpr int INF = Inf<int>::inf(); constexpr ll BINF = Inf<ll>::inf();
// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
// }}}
 
// Lazy Segment Tree {{{
template <class T, class U, class LazyOp>
class LazySegmentTree {
private:
	LazyOp op;
	int n, h;
	std::vector<T> tree;
	std::vector<U> lazy;
	std::vector<bool> tag;
 
	void calc(int p, int len) {
		tree[p] = op(tree[p << 1], tree[p << 1 | 1]);
		if (tag[p]) op.upd(tree[p], lazy[p], len);
	}
 
	void apply(int p, const U &val, int len) {
		op.upd(tree[p], val, len);
		if (p < n) op.upLazy(lazy[p], val), tag[p] = true;
	}
 
	void build(int p) {
		int len = 2;
		for (p += n; p >>= 1; len <<= 1) calc(p, len);
	}
 
	void push(int p) {
		int s = h, len = 1 << (h - 1);
		for (p += n; s > 0; s--, len >>= 1) {
			int i = p >> s;
			if (tag[i]) {
				apply(i << 1, lazy[i], len);
				apply(i << 1 | 1, lazy[i], len);
				lazy[i] = op.udef(), tag[i] = false;
			}
		}
	}
 
public:
	LazySegmentTree(const std::vector<T> &init) : n(init.size()), h(0), tree(n), lazy(n + n, op.udef()), tag(n + n) {
		for (const T &x : init) tree.push_back(x);
		while ((1 << h) <= n) h++;
		for (int i = n - 1; i > 0; i--) tree[i] = op(tree[i << 1], tree[i << 1 | 1]);
	}
	LazySegmentTree(int n, const T &init) : LazySegmentTree(std::vector<T>(n, init)) {}
	LazySegmentTree(int n) : LazySegmentTree(n, op.def()) {}
 
	void modify(int l, int r, const U &val) {
		push(l); push(r);
		int l0 = l, r0 = r, len = 1;
		for (l += n, r += n + 1; l < r; l >>= 1, r >>= 1, len <<= 1) {
			if (l & 1) apply(l++, val, len);
			if (r & 1) apply(--r, val, len);
		}
		build(l0); build(r0);
	}
 
	T query(int l, int r) {
		push(l); push(r);
		T res = op.def();
		for (l += n, r += n + 1; l < r; l >>= 1, r >>= 1) {
			if (l & 1) res = op(res, tree[l++]);
			if (r & 1) res = op(tree[--r], res);
		}
		return res;
	}
 
};
// }}}
 
// Segment Tree Operators {{{
template <class T, class U> struct SegOpTemp {
	constexpr T operator()(const T &lhs, const T &rhs); // query (e.g. range max/sum)
	constexpr T &upd(T &lhs, const U &rhs, int len = 1); // update (e.g. range add/assign)
	constexpr U &upLazy(U &lhs, const U &rhs); // update for lazy nodes (e.g. sum update accumulate)
	constexpr const T def(); // default value for result (e.g. INF for min query)
	constexpr const U udef(); // default value for update (e.g. 0 for add updates)
};
 
template <class T, class U> struct MinAdd {
	constexpr T operator()(const T &lhs, const T &rhs) { return min(lhs, rhs); }
	constexpr T &upd(T &lhs, const U &rhs, int = 1) { return lhs += rhs; }
	constexpr U &upLazy(U &lhs, const U &rhs) { return lhs += rhs; }
	constexpr const T def() { return Inf<T>::inf(); }
	constexpr const U udef() { return 0; }
};
 
 
struct MinAddFreq : MinAdd<pii, int> {
	using T = pii; using U = int;
	constexpr T operator()(const T &lhs, const T &rhs) {
		if (lhs.first == rhs.first) return T{lhs.first, lhs.second + rhs.second};
		return min(lhs, rhs);
	}
	constexpr T &upd(T &lhs, const U &rhs, int = 1) {
		lhs.first += rhs;
		return lhs;
	}
	constexpr U &upLazy(U &lhs, const U &rhs) { return lhs += rhs; }
	constexpr const T def() { return T{Inf<U>::inf(), 0}; }
	constexpr const U udef() { return 0; }
};
 
 
// }}}
 
// Coordinate Compression Vector {{{
template <class T>
class CVector : public std::vector<T> {
	public:
		template <class... U> CVector<T> (U &&... args) : std::vector<T>(std::forward<U>(args)...) {}
 
		void compress() {
			std::sort(this->begin(), this->end());
			this->erase(std::unique(this->begin(), this->end()), this->end());
		}
 
		auto getlb(const T &v) {
			return std::distance(this->begin(), std::lower_bound(this->begin(), this->end(), v));
		}
 
		auto getub(const T &v) {
			return std::distance(this->begin(), std::upper_bound(this->begin(), this->end(), v));
		}
 
		T getSegLen(int i) {
			T rt = this->at(i);
			if (i > 0) rt -= this->at(i - 1);
			return rt;
		}
};
// }}}
 
int solve() {
	int n; cin >> n;
	CVector<int> xCords, yCords;
	using qry = tuple<int, int, int, int>;
	vector<qry> qries;
	for (int i = 0; i < n; i++) {
		int lx, ly, rx, ry; cin >> lx >> ly >> rx >> ry;
		qries.emplace_back(lx, ly, rx, ry);
		xCords.push_back(lx); xCords.push_back(rx);
		yCords.push_back(ly); yCords.push_back(ry);
	}
	xCords.compress();
	yCords.compress();
	int nc = xCords.size();
	int mc = yCords.size();
	vector<vector<pii>> adds(nc + 1), rems(nc + 1);
	for (auto tup : qries) {
	    int lx, ly, rx, ry;
	    tie(lx, ly, rx, ry) = tup;
		lx = xCords.getub(lx); rx = xCords.getlb(rx);
		ly = yCords.getub(ly); ry = yCords.getlb(ry);
		adds[lx].emplace_back(ly, ry);
		rems[rx + 1].emplace_back(ly, ry);
	}
	vpii init(mc);
	for (int i = 0; i < mc; i++) init[i] = {0, yCords.getSegLen(i)};
	ll ans = 0;
	int totLen = yCords.back() - yCords.front();
	LazySegmentTree<pii, int, MinAddFreq> st(init);
	for (int i = 0; i < nc; i++) {
		for (auto pr : adds[i]) st.modify(pr.first, pr.second, 1);
		for (auto pr : rems[i]) st.modify(pr.first, pr.second, -1);
		ans += 1LL * totLen * xCords.getSegLen(i);
		auto pr = st.query(1, mc - 1);
		if (pr.first == 0) ans -= 1LL * pr.second * xCords.getSegLen(i);
	}
	cout << ans << endl;
	return 0;
}
 
// Template Main {{{
int main() {
	ios::sync_with_stdio(0);
	// precompute();
	// int t; cin >> t; for (int i=1;i<=t;i++)
	solve();
	// cout << "Case #" << i << ": ", solve();
	return 0;
}
 
template <class T> istream &operator>>(istream &is, vector<T> &v) {
	for (auto it=v.begin();it!=v.end();++it) is >> *it;
	return is;
}
 
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
	for (auto it=v.begin();it!=v.end();) os << *it, os << " \n"[++it==v.end()];
	return os;
}
 
template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) {
	return is >> p.first >> p.second;
}
 
template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) {
	return os << p.first << ' ' << p.second;
}
// }}}
 
// vim: fdm=marker


Measured memory_bytes: 3644