Cod sursa(job #1775102)

Utilizator depevladVlad Dumitru-Popescu depevlad Data 9 octombrie 2016 20:41:45
Problema Metrou4 Scor 100
Compilator cpp Status done
Runda Arhiva ICPC Marime 3.4 kb
#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;
}