// TrungNotChung
#include <bits/stdc++.h>
#define pii pair<int, int>
#define fi first
#define se second
#define BIT(x, i) (1 & ((x) >> (i)))
#define MASK(x) (1LL << (x))
#define CNT(x) __builtin_popcountll(x)
#define task "area"
using namespace std;
const int N = (int)2e5 + 228;
const int INF = (int)1e9 + 7;
struct Point {
int x, y;
};
struct Segment {
Point p1, p2;
};
struct Event {
int x, l, r, tp, id;
Event(int _x = 0, int _l = 0, int _r = 0, int _tp = 0) {
x = _x, l = _l, r = _r, tp = _tp;
}
bool operator < (const Event& other) const {
return (x == other.x ? tp < other.tp : x < other.x);
}
}e[N];
int len[N];
namespace Area {
struct SegmentTree {
vector<int> cnt;
vector<int> sum;
int n;
SegmentTree(int _n = 0) {
n = _n;
cnt.assign(4 * n + 7, 0);
sum.assign(4 * n + 7, 0);
}
void update(int id, int l, int r, int u, int v, int tp) {
if(l > v || r < u) {
return;
}
if(u <= l && r <= v) {
cnt[id] += tp;
if(cnt[id] == 0) {
if(l != r) {
sum[id] = sum[id * 2] + sum[id * 2 + 1];
} else {
sum[id] = 0;
}
} else {
sum[id] = len[r] - (l == 0 ? 0 : len[l-1]);
}
// cout << l << " " << r << " " << sum[id] << "\n";
return;
}
int mid = (l + r) / 2;
update(id * 2, l, mid, u, v, tp);
update(id * 2 + 1, mid + 1, r, u, v, tp);
if(cnt[id] == 0) {
sum[id] = sum[id * 2] + sum[id * 2 + 1];
} else {
sum[id] = len[r] - (l == 0 ? 0 : len[l-1]);
}
}
};
long long calc(vector<Segment> candidates) {
vector<int> py;
int m = 0;
for(int i = 0; i < (int)candidates.size(); ++i) {
py.push_back(candidates[i].p1.y);
py.push_back(candidates[i].p2.y + 1);
e[++m] = Event(candidates[i].p1.x, candidates[i].p1.y, candidates[i].p2.y, 1);
e[++m] = Event(candidates[i].p2.x + 1, candidates[i].p1.y, candidates[i].p2.y, -1);
}
py.push_back(-INF);
sort(py.begin(), py.end());
py.erase(unique(py.begin(), py.end()), py.end());
int sz = (int)py.size() - 1;
for(int i = 1; i < sz; ++i) {
len[i] = len[i-1] + py[i+1] - py[i];
}
SegmentTree it = SegmentTree(sz);
sort(e + 1, e + m + 1);
long long ans = 0;
for(int i = 1; i <= m; ++i) {
if(i > 1) {
ans += 1LL * (e[i].x - e[i-1].x) * it.sum[1];
}
// cout << it.sum[1] << "\n";
int l = lower_bound(py.begin(), py.end(), e[i].l) - py.begin();
int r = lower_bound(py.begin(), py.end(), e[i].r + 1) - py.begin() - 1;
// cout << e[i].x << " " << l << " " << r << " " << len[r] - len[l-1] << " " << e[i].tp << "\n";
it.update(1, 1, sz, l, r, e[i].tp);
}
return ans;
}
}
namespace Component {
bool isEnd[N];
int endTime[N];
struct DisjointSet
{
vector<int> lab;
int n;
DisjointSet(int _n = 0)
{
n = _n;
lab.assign(n+7, -1);
}
int Find(int u)
{
if(lab[u] < 0)
return u;
return lab[u] = Find(lab[u]);
}
bool join(int u, int v)
{
u = Find(u), v = Find(v);
if(u == v)
return false;
if(lab[u] < lab[v])
swap(u, v);
lab[v] += lab[u], lab[u] = v;
return true;
}
}dsu;
struct SegmentTree
{
vector<int> cnt;
vector<vector<int> > node1, node2;
int n;
SegmentTree(int _n = 0)
{
n = _n;
cnt.assign(4 * n + 7, 0);
node1.assign(4 * n + 7, vector<int>());
node2.assign(4 * n + 7, vector<int>());
}
void join(vector<int> &a, int node) {
int best = -1;
for(int x : a) {
if(isEnd[x]) {
continue;
}
// cout << "Join: " << node << " " << x << '\n';
if(best == -1 || endTime[x] > endTime[best]) {
best = x;
}
dsu.join(x, node);
}
a.clear();
if(best != -1) {
a.push_back(best);
}
}
void update(int id, int l, int r, int u, int v, int node)
{
if(l > v || r < u) {
return;
}
join(node1[id], node);
if(u <= l && r <= v) {
// node2[id].push_back(node);
// node1[id].push_back(node);
join(node2[id], node);
return;
}
// node2[id].push_back(node);
int mid = (l + r) / 2;
update(id * 2, l, mid, u, v, node);
update(id * 2 + 1, mid + 1, r, u, v, node);
}
void add(int id, int l, int r, int u, int v, int node)
{
if(l > v || r < u) {
return;
}
if(u <= l && r <= v) {
node2[id].push_back(node);
node1[id].push_back(node);
return;
}
node2[id].push_back(node);
int mid = (l + r) / 2;
add(id * 2, l, mid, u, v, node);
add(id * 2 + 1, mid + 1, r, u, v, node);
}
};
vector<int> calc(vector<Segment> candidates) {
int n = (int)candidates.size();
vector<int> py;
int m = 0;
for(int i = 0; i < (int)candidates.size(); ++i) {
py.push_back(candidates[i].p1.y-1);
py.push_back(candidates[i].p1.y);
py.push_back(candidates[i].p2.y);
py.push_back(candidates[i].p2.y + 1);
e[++m] = Event(candidates[i].p1.x, candidates[i].p1.y - 1, candidates[i].p2.y + 1, 1);
e[m].id = i + 1;
endTime[i+1] = candidates[i].p2.x;
e[++m] = Event(candidates[i].p2.x + 1, candidates[i].p1.y, candidates[i].p2.y, -1);
e[m].id = i + 1 + n;
endTime[i+1+n] = candidates[i].p2.x + 1;
}
dsu = DisjointSet(n * 2);
for(int i = 1; i <= n; ++i) {
dsu.join(i, i + n);
}
py.push_back(-INF);
sort(py.begin(), py.end());
py.erase(unique(py.begin(), py.end()), py.end());
int sz = (int)py.size();
SegmentTree it = SegmentTree(sz);
sort(e + 1, e + m + 1);
priority_queue<pii, vector<pii>, greater<pii> > pq;
for(int i = 1; i <= m; ++i) {
while(pq.size() && pq.top().fi < e[i].x) {
int id = pq.top().se;
// cout << i << " " << id << '\n';
pq.pop();
isEnd[id] = true;
}
int id = e[i].id;
int l = lower_bound(py.begin(), py.end(), e[i].l) - py.begin();
int r = lower_bound(py.begin(), py.end(), e[i].r) - py.begin();
// cout << e[i].x << " " << id << " " << l << " " << r << '\n';
if(id <= n) {
int x = lower_bound(py.begin(), py.end(), e[i].l + 1) - py.begin();
int y = lower_bound(py.begin(), py.end(), e[i].r - 1) - py.begin();
// cout << x << " " << y << '\n';
it.update(1, 1, sz, x, y, id);
}
// cout << "Add:\n";
it.add(1, 1, sz, l, r, id);
pq.push({endTime[id], id});
}
vector<int> ans;
for(int i = 1; i <= n; ++i) {
ans.push_back(dsu.Find(i));
}
return ans;
}
}
int n;
Segment segs[N];
void solve() {
cin >> n;
for(int i = 1; i <= n; ++i) {
int x, y, u, v;
cin >> x >> y >> u >> v;
segs[i].p1 = {x, y};
segs[i].p2 = {u, v};
}
vector<Segment> candidates;
for(int i = 1; i <= n; ++i) {
if(segs[i].p1.x > segs[i].p2.x) {
continue;
}
if(segs[i].p1.y > segs[i].p2.y) {
continue;
}
candidates.push_back(segs[i]);
}
vector<int> comp = Component::calc(candidates);
// for(int x : comp) {
// cout << x << " ";
// }
// cout << '\n';
vector<int> perm;
for(int i = 1; i <= n; ++i) {
perm.push_back(i);
}
sort(perm.begin(), perm.end(), [&](int u, int v) {
return comp[u-1] < comp[v-1];
});
long long ans = 0;
int cur = 0;
while(cur < n) {
int nxt = cur;
while(nxt < n && comp[perm[nxt] - 1] == comp[perm[cur] - 1]) {
++nxt;
}
vector<Segment> tmp;
for(int i = cur; i < nxt; ++i) {
tmp.push_back(segs[perm[i]]);
}
ans = max(ans, Area::calc(tmp));
cur = nxt;
}
cout << ans;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
freopen(task ".inp", "r", stdin);
freopen(task ".out", "w", stdout);
solve();
// cerr << "\nTime elapsed: " << 1000 * clock() / CLOCKS_PER_SEC << "ms\n";
return 0;
}
Ly8gVHJ1bmdOb3RDaHVuZwojaW5jbHVkZSA8Yml0cy9zdGRjKysuaD4KI2RlZmluZSBwaWkgcGFpcjxpbnQsIGludD4KI2RlZmluZSBmaSBmaXJzdAojZGVmaW5lIHNlIHNlY29uZAojZGVmaW5lIEJJVCh4LCBpKSAoMSAmICgoeCkgPj4gKGkpKSkKI2RlZmluZSBNQVNLKHgpICgxTEwgPDwgKHgpKQojZGVmaW5lIENOVCh4KSBfX2J1aWx0aW5fcG9wY291bnRsbCh4KQojZGVmaW5lIHRhc2sgImFyZWEiCiAKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKY29uc3QgaW50IE4gPSAoaW50KTJlNSArIDIyODsKY29uc3QgaW50IElORiA9ICAoaW50KTFlOSArIDc7CgpzdHJ1Y3QgUG9pbnQgewogICAgaW50IHgsIHk7Cn07CgpzdHJ1Y3QgU2VnbWVudCB7CiAgICBQb2ludCBwMSwgcDI7Cn07CgpzdHJ1Y3QgRXZlbnQgewogICAgaW50IHgsIGwsIHIsIHRwLCBpZDsKICAgIEV2ZW50KGludCBfeCA9IDAsIGludCBfbCA9IDAsIGludCBfciA9IDAsIGludCBfdHAgPSAwKSB7CiAgICAgICAgeCA9IF94LCBsID0gX2wsIHIgPSBfciwgdHAgPSBfdHA7CiAgICB9CiAgICBib29sIG9wZXJhdG9yIDwgKGNvbnN0IEV2ZW50JiBvdGhlcikgY29uc3QgewogICAgICAgIHJldHVybiAoeCA9PSBvdGhlci54ID8gdHAgPCBvdGhlci50cCA6IHggPCBvdGhlci54KTsKICAgIH0KfWVbTl07CgppbnQgbGVuW05dOwoKbmFtZXNwYWNlIEFyZWEgewogICAgc3RydWN0IFNlZ21lbnRUcmVlIHsKICAgICAgICB2ZWN0b3I8aW50PiBjbnQ7CiAgICAgICAgdmVjdG9yPGludD4gc3VtOwogICAgICAgIGludCBuOwoKICAgICAgICBTZWdtZW50VHJlZShpbnQgX24gPSAwKSB7CiAgICAgICAgICAgIG4gPSBfbjsKICAgICAgICAgICAgY250LmFzc2lnbig0ICogbiArIDcsIDApOwogICAgICAgICAgICBzdW0uYXNzaWduKDQgKiBuICsgNywgMCk7CiAgICAgICAgfQoKICAgICAgICB2b2lkIHVwZGF0ZShpbnQgaWQsIGludCBsLCBpbnQgciwgaW50IHUsIGludCB2LCBpbnQgdHApIHsKICAgICAgICAgICAgaWYobCA+IHYgfHwgciA8IHUpIHsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZih1IDw9IGwgJiYgciA8PSB2KSB7CiAgICAgICAgICAgICAgICBjbnRbaWRdICs9IHRwOwogICAgICAgICAgICAgICAgaWYoY250W2lkXSA9PSAwKSB7CiAgICAgICAgICAgICAgICAgICAgaWYobCAhPSByKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHN1bVtpZF0gPSBzdW1baWQgKiAyXSArIHN1bVtpZCAqIDIgKyAxXTsKICAgICAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgICAgICBzdW1baWRdID0gMDsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIHN1bVtpZF0gPSBsZW5bcl0gLSAobCA9PSAwID8gMCA6IGxlbltsLTFdKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIC8vIGNvdXQgPDwgbCA8PCAiICIgPDwgciA8PCAiICIgPDwgc3VtW2lkXSA8PCAiXG4iOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGludCBtaWQgPSAobCArIHIpIC8gMjsKICAgICAgICAgICAgdXBkYXRlKGlkICogMiwgbCwgbWlkLCB1LCB2LCB0cCk7CiAgICAgICAgICAgIHVwZGF0ZShpZCAqIDIgKyAxLCBtaWQgKyAxLCByLCB1LCB2LCB0cCk7CiAgICAgICAgICAgIGlmKGNudFtpZF0gPT0gMCkgewogICAgICAgICAgICAgICAgc3VtW2lkXSA9IHN1bVtpZCAqIDJdICsgc3VtW2lkICogMiArIDFdOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgc3VtW2lkXSA9IGxlbltyXSAtIChsID09IDAgPyAwIDogbGVuW2wtMV0pOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfTsKCiAgICBsb25nIGxvbmcgY2FsYyh2ZWN0b3I8U2VnbWVudD4gY2FuZGlkYXRlcykgewogICAgICAgIHZlY3RvcjxpbnQ+IHB5OwogICAgICAgIGludCBtID0gMDsKICAgICAgICBmb3IoaW50IGkgPSAwOyBpIDwgKGludCljYW5kaWRhdGVzLnNpemUoKTsgKytpKSB7CiAgICAgICAgICAgIHB5LnB1c2hfYmFjayhjYW5kaWRhdGVzW2ldLnAxLnkpOwogICAgICAgICAgICBweS5wdXNoX2JhY2soY2FuZGlkYXRlc1tpXS5wMi55ICsgMSk7CiAgICAgICAgICAgIGVbKyttXSA9IEV2ZW50KGNhbmRpZGF0ZXNbaV0ucDEueCwgY2FuZGlkYXRlc1tpXS5wMS55LCBjYW5kaWRhdGVzW2ldLnAyLnksIDEpOwogICAgICAgICAgICBlWysrbV0gPSBFdmVudChjYW5kaWRhdGVzW2ldLnAyLnggKyAxLCBjYW5kaWRhdGVzW2ldLnAxLnksIGNhbmRpZGF0ZXNbaV0ucDIueSwgLTEpOwogICAgICAgIH0KCiAgICAgICAgcHkucHVzaF9iYWNrKC1JTkYpOwogICAgICAgIHNvcnQocHkuYmVnaW4oKSwgcHkuZW5kKCkpOwogICAgICAgIHB5LmVyYXNlKHVuaXF1ZShweS5iZWdpbigpLCBweS5lbmQoKSksIHB5LmVuZCgpKTsKICAgICAgICBpbnQgc3ogPSAoaW50KXB5LnNpemUoKSAtIDE7CiAgICAgICAgZm9yKGludCBpID0gMTsgaSA8IHN6OyArK2kpIHsKICAgICAgICAgICAgbGVuW2ldID0gbGVuW2ktMV0gKyBweVtpKzFdIC0gcHlbaV07CiAgICAgICAgfQogICAgICAgIFNlZ21lbnRUcmVlIGl0ID0gU2VnbWVudFRyZWUoc3opOwoKICAgICAgICBzb3J0KGUgKyAxLCBlICsgbSArIDEpOwogICAgICAgIGxvbmcgbG9uZyBhbnMgPSAwOwogICAgICAgIGZvcihpbnQgaSA9IDE7IGkgPD0gbTsgKytpKSB7CiAgICAgICAgICAgIGlmKGkgPiAxKSB7CiAgICAgICAgICAgICAgICBhbnMgKz0gMUxMICogKGVbaV0ueCAtIGVbaS0xXS54KSAqIGl0LnN1bVsxXTsKICAgICAgICAgICAgfQogICAgICAgICAgICAvLyBjb3V0IDw8IGl0LnN1bVsxXSA8PCAiXG4iOwogICAgICAgICAgICBpbnQgbCA9IGxvd2VyX2JvdW5kKHB5LmJlZ2luKCksIHB5LmVuZCgpLCBlW2ldLmwpIC0gcHkuYmVnaW4oKTsKICAgICAgICAgICAgaW50IHIgPSBsb3dlcl9ib3VuZChweS5iZWdpbigpLCBweS5lbmQoKSwgZVtpXS5yICsgMSkgLSBweS5iZWdpbigpIC0gMTsKICAgICAgICAgICAgLy8gY291dCA8PCBlW2ldLnggPDwgIiAiIDw8IGwgPDwgIiAiIDw8IHIgPDwgIiAiIDw8IGxlbltyXSAtIGxlbltsLTFdIDw8ICIgIiA8PCBlW2ldLnRwIDw8ICJcbiI7CiAgICAgICAgICAgIGl0LnVwZGF0ZSgxLCAxLCBzeiwgbCwgciwgZVtpXS50cCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBhbnM7CiAgICB9Cn0KCm5hbWVzcGFjZSBDb21wb25lbnQgewogICAgYm9vbCBpc0VuZFtOXTsKICAgIGludCBlbmRUaW1lW05dOwoKICAgIHN0cnVjdCBEaXNqb2ludFNldAogICAgewogICAgICAgIHZlY3RvcjxpbnQ+IGxhYjsKICAgICAgICBpbnQgbjsKICAgICAgICBEaXNqb2ludFNldChpbnQgX24gPSAwKQogICAgICAgIHsKICAgICAgICAgICAgbiA9IF9uOwogICAgICAgICAgICBsYWIuYXNzaWduKG4rNywgLTEpOwogICAgICAgIH0KICAgICAgICBpbnQgRmluZChpbnQgdSkKICAgICAgICB7CiAgICAgICAgICAgIGlmKGxhYlt1XSA8IDApCiAgICAgICAgICAgICAgICByZXR1cm4gdTsKICAgICAgICAgICAgcmV0dXJuIGxhYlt1XSA9IEZpbmQobGFiW3VdKTsKICAgICAgICB9CiAgICAgICAgYm9vbCBqb2luKGludCB1LCBpbnQgdikKICAgICAgICB7CiAgICAgICAgICAgIHUgPSBGaW5kKHUpLCB2ID0gRmluZCh2KTsKICAgICAgICAgICAgaWYodSA9PSB2KQogICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICBpZihsYWJbdV0gPCBsYWJbdl0pIAogICAgICAgICAgICAgICAgc3dhcCh1LCB2KTsKICAgICAgICAgICAgbGFiW3ZdICs9IGxhYlt1XSwgbGFiW3VdID0gdjsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgfWRzdTsKCiAgICBzdHJ1Y3QgU2VnbWVudFRyZWUKICAgIHsKICAgICAgICB2ZWN0b3I8aW50PiBjbnQ7CiAgICAgICAgdmVjdG9yPHZlY3RvcjxpbnQ+ID4gbm9kZTEsIG5vZGUyOwogICAgICAgIGludCBuOwogICAgICAgIFNlZ21lbnRUcmVlKGludCBfbiA9IDApCiAgICAgICAgewogICAgICAgICAgICBuID0gX247CiAgICAgICAgICAgIGNudC5hc3NpZ24oNCAqIG4gKyA3LCAwKTsKICAgICAgICAgICAgbm9kZTEuYXNzaWduKDQgKiBuICsgNywgdmVjdG9yPGludD4oKSk7CiAgICAgICAgICAgIG5vZGUyLmFzc2lnbig0ICogbiArIDcsIHZlY3RvcjxpbnQ+KCkpOwogICAgICAgIH0KCiAgICAgICAgdm9pZCBqb2luKHZlY3RvcjxpbnQ+ICZhLCBpbnQgbm9kZSkgewogICAgICAgICAgICBpbnQgYmVzdCA9IC0xOwogICAgICAgICAgICBmb3IoaW50IHggOiBhKSB7CiAgICAgICAgICAgICAgICBpZihpc0VuZFt4XSkgewogICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgLy8gY291dCA8PCAiSm9pbjogIiA8PCBub2RlIDw8ICIgIiA8PCB4IDw8ICdcbic7CiAgICAgICAgICAgICAgICBpZihiZXN0ID09IC0xIHx8IGVuZFRpbWVbeF0gPiBlbmRUaW1lW2Jlc3RdKSB7CiAgICAgICAgICAgICAgICAgICAgYmVzdCA9IHg7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBkc3Uuam9pbih4LCBub2RlKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBhLmNsZWFyKCk7CiAgICAgICAgICAgIGlmKGJlc3QgIT0gLTEpIHsKICAgICAgICAgICAgICAgIGEucHVzaF9iYWNrKGJlc3QpOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICB2b2lkIHVwZGF0ZShpbnQgaWQsIGludCBsLCBpbnQgciwgaW50IHUsIGludCB2LCBpbnQgbm9kZSkKICAgICAgICB7CiAgICAgICAgICAgIGlmKGwgPiB2IHx8IHIgPCB1KSB7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgam9pbihub2RlMVtpZF0sIG5vZGUpOwoKICAgICAgICAgICAgaWYodSA8PSBsICYmIHIgPD0gdikgewogICAgICAgICAgICAgICAgLy8gbm9kZTJbaWRdLnB1c2hfYmFjayhub2RlKTsKICAgICAgICAgICAgICAgIC8vIG5vZGUxW2lkXS5wdXNoX2JhY2sobm9kZSk7CiAgICAgICAgICAgICAgICBqb2luKG5vZGUyW2lkXSwgbm9kZSk7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy8gbm9kZTJbaWRdLnB1c2hfYmFjayhub2RlKTsKICAgICAgICAgICAgaW50IG1pZCA9IChsICsgcikgLyAyOwogICAgICAgICAgICB1cGRhdGUoaWQgKiAyLCBsLCBtaWQsIHUsIHYsIG5vZGUpOwogICAgICAgICAgICB1cGRhdGUoaWQgKiAyICsgMSwgbWlkICsgMSwgciwgdSwgdiwgbm9kZSk7CiAgICAgICAgfQoKICAgICAgICB2b2lkIGFkZChpbnQgaWQsIGludCBsLCBpbnQgciwgaW50IHUsIGludCB2LCBpbnQgbm9kZSkKICAgICAgICB7CiAgICAgICAgICAgIGlmKGwgPiB2IHx8IHIgPCB1KSB7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmKHUgPD0gbCAmJiByIDw9IHYpIHsKICAgICAgICAgICAgICAgIG5vZGUyW2lkXS5wdXNoX2JhY2sobm9kZSk7CiAgICAgICAgICAgICAgICBub2RlMVtpZF0ucHVzaF9iYWNrKG5vZGUpOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIG5vZGUyW2lkXS5wdXNoX2JhY2sobm9kZSk7CgogICAgICAgICAgICBpbnQgbWlkID0gKGwgKyByKSAvIDI7CiAgICAgICAgICAgIGFkZChpZCAqIDIsIGwsIG1pZCwgdSwgdiwgbm9kZSk7CiAgICAgICAgICAgIGFkZChpZCAqIDIgKyAxLCBtaWQgKyAxLCByLCB1LCB2LCBub2RlKTsKICAgICAgICB9CiAgICB9OwoKICAgIHZlY3RvcjxpbnQ+IGNhbGModmVjdG9yPFNlZ21lbnQ+IGNhbmRpZGF0ZXMpIHsKICAgICAgICBpbnQgbiA9IChpbnQpY2FuZGlkYXRlcy5zaXplKCk7CiAgICAgICAgdmVjdG9yPGludD4gcHk7CiAgICAgICAgaW50IG0gPSAwOwogICAgICAgIGZvcihpbnQgaSA9IDA7IGkgPCAoaW50KWNhbmRpZGF0ZXMuc2l6ZSgpOyArK2kpIHsKICAgICAgICAgICAgcHkucHVzaF9iYWNrKGNhbmRpZGF0ZXNbaV0ucDEueS0xKTsKICAgICAgICAgICAgcHkucHVzaF9iYWNrKGNhbmRpZGF0ZXNbaV0ucDEueSk7CiAgICAgICAgICAgIHB5LnB1c2hfYmFjayhjYW5kaWRhdGVzW2ldLnAyLnkpOwogICAgICAgICAgICBweS5wdXNoX2JhY2soY2FuZGlkYXRlc1tpXS5wMi55ICsgMSk7CiAgICAgICAgICAgIGVbKyttXSA9IEV2ZW50KGNhbmRpZGF0ZXNbaV0ucDEueCwgY2FuZGlkYXRlc1tpXS5wMS55IC0gMSwgY2FuZGlkYXRlc1tpXS5wMi55ICsgMSwgMSk7CiAgICAgICAgICAgIGVbbV0uaWQgPSBpICsgMTsKICAgICAgICAgICAgZW5kVGltZVtpKzFdID0gY2FuZGlkYXRlc1tpXS5wMi54OwogICAgICAgICAgICBlWysrbV0gPSBFdmVudChjYW5kaWRhdGVzW2ldLnAyLnggKyAxLCBjYW5kaWRhdGVzW2ldLnAxLnksIGNhbmRpZGF0ZXNbaV0ucDIueSwgLTEpOwogICAgICAgICAgICBlW21dLmlkID0gaSArIDEgKyBuOwogICAgICAgICAgICBlbmRUaW1lW2krMStuXSA9IGNhbmRpZGF0ZXNbaV0ucDIueCArIDE7CiAgICAgICAgfQoKICAgICAgICBkc3UgPSBEaXNqb2ludFNldChuICogMik7CiAgICAgICAgZm9yKGludCBpID0gMTsgaSA8PSBuOyArK2kpIHsKICAgICAgICAgICAgZHN1LmpvaW4oaSwgaSArIG4pOwogICAgICAgIH0KICAgICAgICBweS5wdXNoX2JhY2soLUlORik7CiAgICAgICAgc29ydChweS5iZWdpbigpLCBweS5lbmQoKSk7CiAgICAgICAgcHkuZXJhc2UodW5pcXVlKHB5LmJlZ2luKCksIHB5LmVuZCgpKSwgcHkuZW5kKCkpOwogICAgICAgIGludCBzeiA9IChpbnQpcHkuc2l6ZSgpOwogICAgICAgIFNlZ21lbnRUcmVlIGl0ID0gU2VnbWVudFRyZWUoc3opOwoKICAgICAgICBzb3J0KGUgKyAxLCBlICsgbSArIDEpOwogICAgICAgIHByaW9yaXR5X3F1ZXVlPHBpaSwgdmVjdG9yPHBpaT4sIGdyZWF0ZXI8cGlpPiA+IHBxOwogICAgICAgIGZvcihpbnQgaSA9IDE7IGkgPD0gbTsgKytpKSB7CiAgICAgICAgICAgIHdoaWxlKHBxLnNpemUoKSAmJiBwcS50b3AoKS5maSA8IGVbaV0ueCkgewogICAgICAgICAgICAgICAgaW50IGlkID0gcHEudG9wKCkuc2U7CiAgICAgICAgICAgICAgICAvLyBjb3V0IDw8IGkgPDwgIiAiIDw8IGlkIDw8ICdcbic7CiAgICAgICAgICAgICAgICBwcS5wb3AoKTsKICAgICAgICAgICAgICAgIGlzRW5kW2lkXSA9IHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaW50IGlkID0gZVtpXS5pZDsKICAgICAgICAgICAgaW50IGwgPSBsb3dlcl9ib3VuZChweS5iZWdpbigpLCBweS5lbmQoKSwgZVtpXS5sKSAtIHB5LmJlZ2luKCk7CiAgICAgICAgICAgIGludCByID0gbG93ZXJfYm91bmQocHkuYmVnaW4oKSwgcHkuZW5kKCksIGVbaV0ucikgLSBweS5iZWdpbigpOwogICAgICAgICAgICAvLyBjb3V0IDw8IGVbaV0ueCA8PCAiICIgPDwgaWQgPDwgIiAiIDw8IGwgPDwgIiAiIDw8IHIgPDwgJ1xuJzsKICAgICAgICAgICAgaWYoaWQgPD0gbikgewogICAgICAgICAgICAgICAgaW50IHggPSBsb3dlcl9ib3VuZChweS5iZWdpbigpLCBweS5lbmQoKSwgZVtpXS5sICsgMSkgLSBweS5iZWdpbigpOwogICAgICAgICAgICAgICAgaW50IHkgPSBsb3dlcl9ib3VuZChweS5iZWdpbigpLCBweS5lbmQoKSwgZVtpXS5yIC0gMSkgLSBweS5iZWdpbigpOwogICAgICAgICAgICAgICAgLy8gY291dCA8PCB4IDw8ICIgIiA8PCB5IDw8ICdcbic7CiAgICAgICAgICAgICAgICBpdC51cGRhdGUoMSwgMSwgc3osIHgsIHksIGlkKTsKICAgICAgICAgICAgfQogICAgICAgICAgICAvLyBjb3V0IDw8ICJBZGQ6XG4iOwogICAgICAgICAgICBpdC5hZGQoMSwgMSwgc3osIGwsIHIsIGlkKTsKICAgICAgICAgICAgcHEucHVzaCh7ZW5kVGltZVtpZF0sIGlkfSk7CiAgICAgICAgfQoKICAgICAgICB2ZWN0b3I8aW50PiBhbnM7CiAgICAgICAgZm9yKGludCBpID0gMTsgaSA8PSBuOyArK2kpIHsKICAgICAgICAgICAgYW5zLnB1c2hfYmFjayhkc3UuRmluZChpKSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBhbnM7CiAgICB9Cn0KCmludCBuOwpTZWdtZW50IHNlZ3NbTl07CiAKdm9pZCBzb2x2ZSgpIHsKICAgIGNpbiA+PiBuOwogICAgZm9yKGludCBpID0gMTsgaSA8PSBuOyArK2kpIHsKICAgICAgICBpbnQgeCwgeSwgdSwgdjsKICAgICAgICBjaW4gPj4geCA+PiB5ID4+IHUgPj4gdjsKICAgICAgICBzZWdzW2ldLnAxID0ge3gsIHl9OwogICAgICAgIHNlZ3NbaV0ucDIgPSB7dSwgdn07CiAgICB9CiAgICAKICAgIHZlY3RvcjxTZWdtZW50PiBjYW5kaWRhdGVzOwogICAgZm9yKGludCBpID0gMTsgaSA8PSBuOyArK2kpIHsKICAgICAgICBpZihzZWdzW2ldLnAxLnggPiBzZWdzW2ldLnAyLngpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGlmKHNlZ3NbaV0ucDEueSA+IHNlZ3NbaV0ucDIueSkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgY2FuZGlkYXRlcy5wdXNoX2JhY2soc2Vnc1tpXSk7CiAgICB9CgogICAgdmVjdG9yPGludD4gY29tcCA9IENvbXBvbmVudDo6Y2FsYyhjYW5kaWRhdGVzKTsKICAgIC8vIGZvcihpbnQgeCA6IGNvbXApIHsKICAgIC8vICAgICBjb3V0IDw8IHggPDwgIiAiOwogICAgLy8gfQogICAgLy8gY291dCA8PCAnXG4nOwogICAgdmVjdG9yPGludD4gcGVybTsKICAgIGZvcihpbnQgaSA9IDE7IGkgPD0gbjsgKytpKSB7CiAgICAgICAgcGVybS5wdXNoX2JhY2soaSk7CiAgICB9CiAgICBzb3J0KHBlcm0uYmVnaW4oKSwgcGVybS5lbmQoKSwgWyZdKGludCB1LCBpbnQgdikgewogICAgICAgIHJldHVybiBjb21wW3UtMV0gPCBjb21wW3YtMV07CiAgICB9KTsKCiAgICBsb25nIGxvbmcgYW5zID0gMDsKICAgIGludCBjdXIgPSAwOwogICAgd2hpbGUoY3VyIDwgbikgewogICAgICAgIGludCBueHQgPSBjdXI7CiAgICAgICAgd2hpbGUobnh0IDwgbiAmJiBjb21wW3Blcm1bbnh0XSAtIDFdID09IGNvbXBbcGVybVtjdXJdIC0gMV0pIHsKICAgICAgICAgICAgKytueHQ7CiAgICAgICAgfQogICAgICAgIHZlY3RvcjxTZWdtZW50PiB0bXA7CiAgICAgICAgZm9yKGludCBpID0gY3VyOyBpIDwgbnh0OyArK2kpIHsKICAgICAgICAgICAgdG1wLnB1c2hfYmFjayhzZWdzW3Blcm1baV1dKTsKICAgICAgICB9CiAgICAgICAgYW5zID0gbWF4KGFucywgQXJlYTo6Y2FsYyh0bXApKTsKICAgICAgICBjdXIgPSBueHQ7CiAgICB9CgogICAgY291dCA8PCBhbnM7Cn0KIAppbnQgbWFpbigpCnsKICAgIGlvc19iYXNlOjpzeW5jX3dpdGhfc3RkaW8oZmFsc2UpOwogICAgY2luLnRpZSgwKTsKICAgIGNvdXQudGllKDApOwogICAgZnJlb3Blbih0YXNrICIuaW5wIiwgInIiLCBzdGRpbik7CiAgICBmcmVvcGVuKHRhc2sgIi5vdXQiLCAidyIsIHN0ZG91dCk7CiAgICBzb2x2ZSgpOwogICAgLy8gY2VyciA8PCAiXG5UaW1lIGVsYXBzZWQ6ICIgPDwgMTAwMCAqIGNsb2NrKCkgLyBDTE9DS1NfUEVSX1NFQyA8PCAibXNcbiI7CiAgICByZXR1cm4gMDsKfQo=