Pagini recente » Cod sursa (job #2406377) | Cod sursa (job #143988) | Cod sursa (job #2979146) | Cod sursa (job #2923532) | Cod sursa (job #1775102)
#include <bits/stdc++.h>
using namespace std;
const int kMaxN = 150005;
const int kInf = 0x7fffffff;
struct Point {
int x;
int y;
int i;
};
int n;
int f[kMaxN];
int bst[kMaxN];
int dst[kMaxN];
Point p[kMaxN];
Point pi[kMaxN];
vector <Point> solveOctant(const int id, const int lef, const int rig) {
if (lef < rig) {
const int mid = (lef + rig) >> 1;
vector <Point> d = solveOctant(id, lef, mid);
vector <Point> u = solveOctant(id, mid + 1, rig);
if (u.size() > 0) {
int bestDist = kInf;
int bestId = 0;
for (int i = 0, j = 0; i < (int)d.size(); i++) {
while (j < (int)u.size() && u[j].x + u[j].y <= d[i].x + d[i].y) {
if (bestDist > u[j].y - u[j].x) {
bestDist = u[j].y - u[j].x;
bestId = u[j].i;
}
j++;
}
if (dst[d[i].i] > bestDist) {
dst[d[i].i] = bestDist;
bst[d[i].i] = bestId;
}
}
}
vector <Point> s(d.size() + u.size());
merge(d.begin(), d.end(), u.begin(), u.end(), s.begin(), [] (const Point &u, const Point &v) { return u.x + u.y < v.x + v.y; });
return s;
}
else {
if (lef == rig) return { p[lef] };
else return { };
}
}
vector <pair <int, pair <int, int>>> findEdges() {
vector <pair <int, pair <int, int>>> mstEdges;
for (int i = 0; i < 8; i++) {
sort(p + 1, p + n + 1, [] (const Point &u, const Point &v) { return ((u.y == v.y) ? (u.x + u.y > v.x + v.y) : (u.y < v.y)); });
fill(dst, dst + n + 1, kInf);
fill(bst, bst + n + 1, -1);
solveOctant(i, 1, n);
for (int j = 1; j <= n; j++) {
if (bst[j] > 0) {
const int dx = abs(pi[j].x - pi[bst[j]].x);
const int dy = abs(pi[j].y - pi[bst[j]].y);
mstEdges.emplace_back(dx + dy, make_pair(j, bst[j]));
}
if (i & 1) {
p[j].x *= -1;
}
else {
swap(p[j].x, p[j].y);
}
}
}
return mstEdges;
}
void setStart() {
srand(time(NULL));
for (int i = 1; i <= n; i++) {
f[i] = i;
}
}
int setFind(const int u) {
return (u == f[u] ? u: (f[u] = setFind(f[u])));
}
bool setMerge(const int u, const int v) {
int fu = setFind(u);
int fv = setFind(v);
if (fu != fv) {
if (rand() & 1) {
swap(fu, fv);
}
f[fu] = fv;
return true;
}
else return false;
}
int64_t getMst() {
vector <pair <int, pair <int, int>>> mstEdges = findEdges();
sort(mstEdges.begin(), mstEdges.end());
setStart();
int64_t mstCost = 0;
for (const auto &e: mstEdges) {
mstCost += e.first * setMerge(e.second.first, e.second.second);
}
return mstCost;
}
int main() {
freopen("metrou4.in", "r", stdin);
freopen("metrou4.out", "w", stdout);
int T;
for (scanf("%d", &T); T; T--) {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d %d", &p[i].x, &p[i].y);
p[i].i = i;
pi[i] = p[i];
}
printf("%lld\n", getMst());
}
return 0;
}