#include <bits/stdc++.h>   using namespace std;   vector<vector<int> > adj(2001);   int match[2001 + 1], dis[2001 + 1];   bool visited[2001 + 1], minimumVertexCover[2001], maximumIndependentSet[2001];   const int inf = 1E9;   void ResetVisited() {     for (int i = 0; i <= 2001; ++i) {       visited[i] = 0;     }   }   bool BFS(vector<int> &U) {     queue<int> Q;     for (auto u : U) {       if (match[u] == 2001) {         dis[u] = 0;         Q.push(u);       } else {         dis[u] = inf;       }     }     dis[2001] = inf;     while (!Q.empty()) {       int u = Q.front();       Q.pop();       visited[u] = 1;       if (dis[u] < dis[2001]) {         for (auto v : adj[u]) {           if (dis[match[v]] == inf) {             visited[v] = 1;             dis[match[v]] = 1 + dis[u];             Q.push(match[v]);           }         }       }     }     return (dis[2001] != inf);   }   bool DFS(int u) {     if (u == 2001) {       return true;     }     for (auto v : adj[u]) {       if (dis[match[v]] == 1 + dis[u]) {         if (DFS(match[v])) {           match[v] = u;           match[u] = v;           return true;         }       }     }     dis[u] = inf;     return false;   }   int HopcroftKarpMaximumMatching(vector<int> &U, vector<int> &V) {     for (auto u : U) {       match[u] = 2001;     }     for (auto v : V) {       match[v] = 2001;     }     int matching = 0;     for (ResetVisited(); BFS(U); ResetVisited()) {       for (auto u : U) {         if (match[u] == 2001) {           matching += DFS(u);         }       }     }     return matching;   }   void FillMinimumVertexCover(vector<int> &U, vector<int> &V) {     for (auto u : U) {       minimumVertexCover[u] = (match[u] != 2001 && visited[u] == 0);     }     for (auto v : V) {       minimumVertexCover[v] = (match[v] != 2001 && visited[v] == 1);     }   }   void FillMaximumIndependentSet(vector<int> &U, vector<int> &V) {     for (auto u : U) {       maximumIndependentSet[u] = (match[u] == 2001 || visited[u] == 1);     }     for (auto v : V) {       maximumIndependentSet[v] = (match[v] == 2001 || visited[v] == 0);     }   }   vector<tuple<int, int, int> > segments;   vector<int> AddSegments(vector<pair<int, int> > v) {     vector<int> V;     sort(v.begin(), v.end());     for (int i = 0; i < v.size() - 1; ++i) {       if (v[i + 1].first == v[i].first) {         V.push_back(segments.size());         segments.push_back(make_tuple(v[i].first, v[i].second, v[i + 1].second));       }     }     return V;   }   bool DoSegmentsIntersect(int i, int j) {     int x, y1, y2, y, x1, x2;     tie(x, y1, y2) = segments[i];     tie(y, x1, x2) = segments[j];     return (x1 < x && x < x2 && y1 < y && y < y2);   }   vector<tuple<int, int, int, int> > MakeAnswerSegments(       vector<int> &V, vector<pair<int, int> > &P, bool isHorizontal) {     vector<tuple<int, int, int> > v;     for (auto i : V) {       if (maximumIndependentSet[i]) {         v.push_back(segments[i]);       }     }     for (auto p : P) {       v.push_back(make_tuple(p.first, p.second, p.second));     }     sort(v.begin(), v.end());     vector<tuple<int, int, int, int> > ans;     for (int i = 0, j; i < v.size(); i = j) {       int x, y1, y2;       tie(x, y1, y2) = v[i];       for (j = i + 1; j < v.size(); ++j) {         int nx, ny1, ny2;         tie(nx, ny1, ny2) = v[j];         if (nx == x && ny1 == y2) {           y2 = ny2;         } else {           break;         }       }       if (isHorizontal) {         ans.push_back(make_tuple(y1, x, y2, x));       } else {         ans.push_back(make_tuple(x, y1, x, y2));       }     }     return ans;   }   void PrintAnswerSegments(vector<tuple<int, int, int, int> > &ans) {     printf( %lu n , ans.size());     for (auto t : ans) {       int x1, y1, x2, y2;       tie(x1, y1, x2, y2) = t;       printf( %d %d %d %d n , x1, y1, x2, y2);     }   }   int main() {     int n;     vector<pair<int, int> > xyPoints, yxPoints;     cin >> n;     while (n--) {       int x, y;       cin >> x >> y;       xyPoints.push_back(make_pair(x, y));       yxPoints.push_back(make_pair(y, x));     }     vector<int> U = AddSegments(xyPoints);     vector<int> V = AddSegments(yxPoints);     for (auto u : U) {       for (auto v : V) {         if (DoSegmentsIntersect(u, v)) {           adj[u].push_back(v);         }       }     }     HopcroftKarpMaximumMatching(U, V);     FillMaximumIndependentSet(U, V);     vector<tuple<int, int, int, int> > horizontalSegments =         MakeAnswerSegments(V, yxPoints, 1);     vector<tuple<int, int, int, int> > verticalSegments =         MakeAnswerSegments(U, xyPoints, 0);     PrintAnswerSegments(horizontalSegments);     PrintAnswerSegments(verticalSegments);     return 0;   }