1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <iostream>
#include <map>
#include <vector>
#include <set>
#include <algorithm>
#define REP(x,n) for(int x=0;x<(n);++x)
#define FOR(a,b,e) for(int a=b;a<=(e);++a)
#define VAR(x,n) __typeof(n) x = (n)
#define FOREACH(x,n) for(VAR(x,(n).begin());x!=(n).end();++x)
using namespace std;

const int ENDING = 0x1<<30;
const int MAX_N = 100001;
struct Point {
	int x;
	int y;
	Point() {}
	Point(int _x, int _y): x(_x), y(_y) {}
} rect[MAX_N*2];
struct Pkt {
	Point p1;
	Point p2;
	Pkt(int x, int y1, int y2): p1(x,y1), p2(x,y2) {}
	Pkt(int nr) {
		if (nr&1) {
			p1 = Point(rect[nr].x, rect[nr-1].y);
			p2 = Point(rect[nr].x, rect[nr].y);
		} else {
			p1 = Point(rect[nr].x, rect[nr].y);
			p2 = Point(rect[nr].x, rect[nr+1].y);
		}
	}
};
ostream& operator<<(ostream& os, Pkt p) {
	cout << "(" << p.p1.x << ", " << p.p1.y<<"-"<<p.p2.y<<")";
	return os;
}
bool inline RectCross(Point p1, Point p2, Point p3, Point p4) {
	return max(p1.x,p3.x)<min(p2.x,p4.x) && max(p1.y,p3.y)<min(p2.y,p4.y);
}
bool operator<(const Pkt& p, const Pkt& q) {
	return p.p1.x==q.p1.x ? (p.p1.y==q.p1.y ? p.p2.y<q.p2.y : p.p1.y<q.p1.y) : p.p1.x<q.p1.x;
}
struct comp {
	bool operator() (int e, int f) {
		return rect[e+e].x<rect[f+f].x;
	}
};
bool comp2(const int& e, const int& f) {
	return rect[e+e].x==rect[f+f].x ? (rect[e+e+1].x==rect[f+f+1].x ? (rect[e+e].y==rect[f+f].y ? rect[e+e+1].y<rect[f+f+1].y : rect[e+e].y<rect[f+f].y) : rect[e+e+1].x<rect[f+f+1].x) : rect[e+e].x<rect[f+f].x;
}
typedef map<int,set<int> > MyMap;
int n;
MyMap mapa;

void synteza(int a, int b) {
//cout<<"synteza "<<a<<" "<<b<<endl;
  mapa[rect[a+a].x].erase(a);
  mapa[rect[a+a+1].x].erase(a|ENDING);
  mapa[rect[b+b].x].erase(b);
  mapa[rect[b+b+1].x].erase(b|ENDING);

	Point p1( min(rect[a+a].x, rect[b+b].x), min(rect[a+a].y, rect[b+b].y)),
				p2( max(rect[a+a+1].x, rect[b+b+1].x), max(rect[a+a+1].y, rect[b+b+1].y));

	rect[a+a]=p1;
	rect[a+a+1]=p2;
	mapa[p1.x].insert(a);
	mapa[p2.x].insert(a|ENDING);
}

int main() {
	ios_base::sync_with_stdio(0);
	cin>>n;
	int x1,x2,y1,y2;
	REP(x,n) {
		cin>>x1>>x2>>y1>>y2;
		rect[x+x] = Point(x1,y1);
		rect[x+x+1] = Point(x2,y2);
		mapa[x1].insert(x);
		mapa[x2].insert(x|ENDING);
	}
	set<int> open; /// teren
	vector<int> open_pos;
	bool synt=false;
	FOREACH(it, mapa) {
		if (synt && !(synt=false))
			--it;
		FOREACH(it2, it->second) { /// obszar #(*it2) na odciętej it->first
//cout<<"iter "<<(*it2&~ENDING)<<(*it2&ENDING ? "K\t" : "\t")<<it->first<<" "<<rect[*it2+*it2].y<<" "<<rect[*it2+*it2+1].y<<endl;
			if (*it2 & ENDING) {
				if (open.find(*it2^ENDING)!=open.end())
					open.erase(*it2 ^ ENDING);
				else {
					int nr = *it2^ENDING,
							nr2=nr;
					FOREACH(it3, open) {
						if (RectCross(rect[*it3+*it3], rect[*it3+*it3+1], rect[nr2+nr2], rect[nr2+nr2+1])) {
							nr = *it3;
							break;
						}
					}
					if (nr!=nr2) { /// tnie sie :)
						synteza(nr, nr2);
						synt=true;
						while(open_pos.back()!=nr) {
							open.erase(open_pos.back());
							open_pos.pop_back();
						}
						open.erase(open_pos.back());
						open_pos.pop_back();
						it=mapa.find(rect[nr+nr].x);
						break;
					}
				}
			} else {
				int nr = *it2;
				FOREACH(it3, open) {
					if (RectCross(rect[*it3+*it3], rect[*it3+*it3+1], rect[*it2+*it2], rect[*it2+*it2+1])) {
						//cout<<" tnie sie z "<<*it3<<endl;
						nr = *it3;
						break;
					}// else cout<<" nie tnie sie z "<<*it3<<endl;
				}
				if (nr==*it2) {/// nie przecina się z nikim
					open.insert(nr);
					open_pos.push_back(nr);
				} else {
					synteza(nr, *it2);
					synt=true;
					while(open_pos.back()!=nr) {
						open.erase(open_pos.back());
						open_pos.pop_back();
					}
					open.erase(open_pos.back());
					open_pos.pop_back();
					it=mapa.find(rect[nr+nr].x);
					break;
				}
			}
		}
	}
	set<int> present;
	vector<int> ans;
	FOREACH(it, mapa)
		FOREACH(itt, it->second)
			if (present.find((*itt&~ENDING))==present.end()) {
				present.insert(*itt);
				ans.push_back(*itt);
			}
	sort(ans.begin(), ans.end(), comp2);
	cout << ans.size() << endl;
	FOREACH(it, ans)
		cout << rect[*it+*it].x << " " << rect[*it+*it+1].x << " " << rect[*it+*it].y << " " << rect[*it+*it+1].y << endl;
	return 0;
}