Cod sursa(job #2718445)

Utilizator NicolaalexandraNicola Alexandra Mihaela Nicolaalexandra Data 8 martie 2021 19:09:47
Problema Metrou4 Scor 0
Compilator cpp-64 Status done
Runda Arhiva ICPC Marime 5.12 kb
#include <bits/stdc++.h>
#pragma GCC optimize("O3")
#define DIM 200000
using namespace std;
class InParser {
private:
	FILE *fin;
	char *buff;
	int sp;

	char read_ch() {
		++sp;
		if (sp == 4096) {
			sp = 0;
			fread(buff, 1, 4096, fin);
		}
		return buff[sp];
	}

public:
	InParser(const char* nume) {
		fin = fopen(nume, "r");
		buff = new char[4096]();
		sp = 4095;
	}

	InParser& operator >> (int &n) {
		char c;
		while (!isdigit(c = read_ch()) && c != '-');
		int sgn = 1;
		if (c == '-') {
			n = 0;
			sgn = -1;
		} else {
			n = c - '0';
		}
		while (isdigit(c = read_ch())) {
			n = 10 * n + c - '0';
		}
		n *= sgn;
		return *this;
	}

	InParser& operator >> (long long &n) {
		char c;
		n = 0;
		while (!isdigit(c = read_ch()) && c != '-');
		long long sgn = 1;
		if (c == '-') {
			n = 0;
			sgn = -1;
		} else {
			n = c - '0';
		}
		while (isdigit(c = read_ch())) {
			n = 10 * n + c - '0';
		}
		n *= sgn;
		return *this;
	}
};


struct punct{
    int x,y,poz;
} v[DIM];

vector <pair<int,int> > X[DIM],Y[DIM];

struct muchie{
    int x,y,cost;
};
vector <muchie> mch;
int t[DIM],wx[DIM],wy[DIM];
pair <int,int> d[DIM];
int T,n,i,j;

inline int cmp (muchie a, muchie b){
    return a.cost < b.cost;
}

int get_rad (int x){
    int nr = x;
    while (t[x] > 0)
        x = t[x];
    while (t[nr] > 0){
        int aux = t[nr];
        t[nr] = x;
        nr = aux;
    }
    return x;
}

int cautare_binara (int v[], int n, int val){
    int st = 1, dr = n;
    while (st <= dr){
        int mid = (st+dr)>>1;
        if (v[mid] == val)
            return mid;
        if (v[mid] < val)
            st = mid+1;
        else dr = mid-1;
    }
}

int cautare_binara2 (vector <pair<int,int> > v, int val){
    int st = 0, dr = v.size()-1, sol = v.size()-1;
    while (st <= dr){
        int mid = (st+dr)>>1;
        if (v[mid].first >= val){
            sol = mid;
            dr = mid-1;
        } else st = mid+1;
    }
    return sol;
}

int modul (int n){
    return max (n,-n);
}

int get_dist (int i, int j){
    return modul (v[i].x - v[j].x) + modul (v[i].y - v[j].y);
}


int main (){

    ios_base::sync_with_stdio(false);

    InParser cin ("metrou4.in");
    ofstream cout ("metrou4.out");

    cin>>T;
    for (;T--;){
        cin>>n;

        for (i=1;i<=n;++i)
            t[i] = -1;
        mch.clear();

        int el = 0, el2 = 0;
        for (i=1;i<=n;++i){
            cin>>v[i].x>>v[i].y;
            v[i].poz = i;
            wx[++el] = v[i].x;
            wy[++el2] = v[i].y;
        }

        sort (wx+1,wx+el+1);
        int nr = 1;
        for (i=2;i<=el;++i){
            if (wx[i] != wx[i-1])
                wx[++nr] = wx[i];
        }
        el = nr;

        sort (wy+1,wy+el2+1);
        nr = 1;
        for (i=2;i<=el2;++i){
            if (wy[i] != wy[i-1])
                wy[++nr] = wy[i];
        }
        el2 = nr;


        for (i=1;i<=max(el,el2);++i)
            X[i].clear(), Y[i].clear();


        for (i=1;i<=n;++i){
            int val = cautare_binara (wx,el,v[i].x);
            X[val].push_back(make_pair(v[i].y,i));
            d[i].first = val;

            val = cautare_binara (wy,el2,v[i].y);
            Y[val].push_back(make_pair(v[i].x,i));
            d[i].second = val;
        }

        for (i=1;i<=el;++i){
            sort (X[i].begin(),X[i].end());
            for (j=0;j<X[i].size()-1;++j)
                mch.push_back({X[i][j].second,X[i][j+1].second,get_dist(X[i][j].second,X[i][j+1].second)});
        }
        for (i=1;i<=el2;++i){
            sort (Y[i].begin(),Y[i].end());
            for (j=0;j<Y[i].size()-1;++j)
                mch.push_back({Y[i][j].second,Y[i][j+1].second,get_dist(Y[i][j].second,Y[i][j+1].second)});
        }

        for (i=1;i<=n;++i){

            int poz = d[i].first;
            if (poz > 1){
                int idx = cautare_binara2 (X[poz-1],v[i].y);
                int j = X[poz-1][idx].second;
                mch.push_back({i,j,get_dist(i,j)});
                if (idx){
                    j = X[poz-1][idx-1].second;
                    mch.push_back({i,j,get_dist(i,j)});
                }
            }

            /// pe orizontala

            poz = d[i].second;
            if (poz > 1){
                int idx = cautare_binara2 (Y[poz-1],v[i].x);
                int j = Y[poz-1][idx].second;
                mch.push_back({i,j,get_dist(i,j)});
                if (idx){
                    j = Y[poz-1][idx-1].second;
                    mch.push_back({i,j,get_dist(i,j)});
                }}}

        sort (mch.begin(),mch.end(),cmp);

        long long sol = 0;
        for (auto it : mch){
            int x = it.x, y = it.y;
            int radx = get_rad(x), rady = get_rad(y);
            if (radx != rady){
                sol += it.cost;
                if (t[radx] > t[rady])
                    swap (radx,rady);
                t[radx] += t[rady];
                t[rady] = radx;
            }
        }

        cout<<sol<<"\n";

    }



    return 0;
}