Cod sursa(job #2719167)

Utilizator NicolaalexandraNicola Alexandra Mihaela Nicolaalexandra Data 9 martie 2021 17:16:03
Problema Metrou4 Scor 0
Compilator cpp-64 Status done
Runda Arhiva ICPC Marime 4.9 kb
#include <bits/stdc++.h>
#define DIM 200000
#define INF 2000000000
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];

struct muchie{
    int x,y,cost;
};
vector <muchie> mch;
int t[DIM],w[DIM];

int T,n,i,j,maxi,sol_poz;

pair <int,int> aint[DIM];

inline int cmp (muchie a, muchie b){
    return a.cost < b.cost;
}
inline int cmp2 (punct a, punct b){
    if (a.x == b.x)
        return a.y < b.y;
    return a.x < b.x;
}

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;
    }
}

void build (int nod, int st, int dr){
    if (st == dr){
        aint[nod] = make_pair (-INF,0);
        return;
    }
    int mid = (st+dr)>>1;
    build (nod<<1,st,mid);
    build ((nod<<1)|1,mid+1,dr);
    aint[nod] = make_pair (-INF,0);
}

void update (int nod, int st, int dr, int poz, pair<int,int> val){
    if (st == dr){
        if (val.first > aint[nod].first)
            aint[nod] = val;
        return;
    }
    int mid = (st+dr)>>1;
    if (poz <= mid)
        update (nod<<1,st,mid,poz,val);
    else update ((nod<<1)|1,mid+1,dr,poz,val);

    if (aint[nod<<1].first > aint[(nod<<1)||1].first)
        aint[nod] = aint[nod<<1];
    else aint[nod] = aint[(nod<<1)|1];
}

void query (int nod, int st, int dr, int x, int y){
    if (x <= st && dr <= y){
        if (aint[nod].first > maxi)
            maxi = aint[nod].first, sol_poz = aint[nod].second;
        return;
    }
    int mid = (st+dr)>>1;
    if (x <= mid)
        query (nod<<1,st,mid,x,y);
    if (y > mid)
        query ((nod<<1)|1,mid+1,dr,x,y);
}

void solve(){

    int i;
    for (i=1;i<=n;++i)
        w[i] = v[i].y - v[i].x;

    sort (w+1,w+n+1);
    int k = 1;
    for (i=2;i<=n;++i)
        if (w[i] != w[i-1])
            w[++k] = w[i];

    //memset (aint,0,sizeof aint);
    //build (1,1,k);
    for (i=1;i<=4*k;i++)
        aint[i] = make_pair(-INF,0);

    sort (v+1,v+n+1,cmp2);
    for (i=1;i<=n;++i){
        int poz = cautare_binara (w,k,v[i].y - v[i].x);

        maxi = -INF, sol_poz = 0;
        query (1,1,k,poz+1,k);

        if (sol_poz){
            mch.push_back({v[i].poz,sol_poz,v[i].x-v[i].y - maxi});
            //cout<<v[i].poz<<" "<<sol_poz<<" "<<v[i].x-v[i].y - maxi<<"\n";
        }

        update (1,1,k,poz,make_pair(v[i].x - v[i].y,v[i].poz));
    }
}


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;
        }

        /// trb sa rotesc punctele ca sa reduc la un singur cadran din 8
        for (int pas=1;pas<=2;++pas){
            for (int pas2=1;pas2<=4;++pas2){
                solve();

                for (i=1;i<=n;++i){
                    int x = -v[i].y, y = v[i].x;
                    v[i].x = x, v[i].y = y;
                }

            }

            for (i=1;i<=n;++i)
                v[i].x = -v[i].x;
        }



        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;
} /// :(