Cod sursa(job #1771185)

Utilizator alexpetrescuAlexandru Petrescu alexpetrescu Data 5 octombrie 2016 12:37:00
Problema Metrou4 Scor 100
Compilator cpp Status done
Runda Arhiva ICPC Marime 3.78 kb
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <utility>
#include <cctype>

#define x first
#define y second
#define mycreation std::pair <int, int>

#define MAXN 150000
#define MAXP 530000

#define BUF_SIZE 1<<17

int pos=BUF_SIZE;
char buf[BUF_SIZE];
FILE *fin;

inline char nextch(){
    if(pos==BUF_SIZE) fread(buf, BUF_SIZE, 1, fin), pos=0;
    return buf[pos++];
}

inline int read(){
    int x=0;
    char ch=nextch();
    while(!isdigit(ch)) ch=nextch();
    while(isdigit(ch)){
        x=10*x+ch-'0';
        ch=nextch();
    }
    return x;
}

int k, n, m, left, right, sef, poz, rez, val;
int t[MAXN+1], a[MAXN+1], ind[MAXN+1];
int aint[MAXP], cine[MAXP];
mycreation v[MAXN+1];

struct godscreation{
    int x, y, z;
    bool operator<(const godscreation &u) const{
        return z<u.z;
    }
}sol[8*MAXN];

inline int myabs(int x){
    if(x<0) return -x;
    else return x;
}

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

inline void reflect(){
    for(int i=1; i<=n; i++)
        v[i].x*=-1;
}

int find(int x){
    if(x==t[x]) return x;
    else return t[x]=find(t[x]);
}

bool cmp(const int &a, const int &b){
    return v[a]<v[b];
}

inline int cautbin(int x){
    int rez=0;
    for(int pas=1<<29; pas; pas>>=1)
        if((rez+pas<=k)&&(a[rez+pas]<=x))
            rez+=pas;
    return rez;
}

void update(int p, int st, int dr){
    if(st==dr){
        aint[p]=val;
        cine[p]=sef;
    }else{
        int m=(st+dr)/2;
        if(poz<=m) update(2*p, st, m);
        else update(2*p+1, m+1, dr);
        aint[p]=aint[2*p];
        cine[p]=cine[2*p];
        if((cine[p]==0)||((cine[2*p+1]!=0)&&(aint[2*p+1]<aint[p]))){
            aint[p]=aint[2*p+1];
            cine[p]=cine[2*p+1];
        }
    }
}

void query(int p, int st, int dr){
    if((left<=st)&&(dr<=right)){
        if((sef==0)||((cine[p]!=0)&&(aint[p]<rez))){
            rez=aint[p];
            sef=cine[p];
        }
    }else{
        int m=(st+dr)/2;
        if(left<=m) query(2*p, st, m);
        if(m+1<=right) query(2*p+1, m+1, dr);
    }
}

inline void muchii(){
    for(int i=1; i<=n; i++)
        ind[i]=i;
    std::sort(ind+1, ind+n+1, cmp);
    for(int i=1; i<=n; i++)
        a[i]=v[i].x-v[i].y;
    std::sort(a+1, a+n+1);
    k=1;
    for(int i=2; i<=n; i++)
        if(a[i]!=a[k])
            a[++k]=a[i];
    memset(cine, 0, sizeof cine);
    for(int i=n; i>0; i--){
        poz=cautbin(v[ind[i]].x-v[ind[i]].y);
        rez=0;
        sef=0;
        left=1;
        right=poz;
        query(1, 1, k);
        if(sef!=0){
            sol[m].x=ind[i];
            sol[m].y=sef;
            sol[m].z=rez-v[ind[i]].x-v[ind[i]].y;
            m++;
        }
        val=v[ind[i]].x+v[ind[i]].y;
        sef=ind[i];
        update(1, 1, k);
    }
}

int main(){
    long long ans;
    FILE *fout;
    fin=fopen("metrou4.in", "r");
    fout=fopen("metrou4.out", "w");
    for(int h=read(); h; h--){
        m=0;
        n=read();
        for(int i=1; i<=n; i++){
            v[i].x=read();
            v[i].y=read();
        }
        for(int i=0; i<2; i++){
            for(int j=0; j<4; j++){
                muchii();
                rot90();
            }
            reflect();
        }
        std::sort(sol, sol+m);
        for(int i=1; i<=n; i++)
            t[i]=i;
        ans=0;
        for(int i=0; i<m; i++){
            if(find(sol[i].x)!=find(sol[i].y)){
                ans+=sol[i].z;
                t[find(sol[i].x)]=find(sol[i].y);
            }
        }
        fprintf(fout, "%lld\n", ans);
    }
    fclose(fin);
    fclose(fout);
    return 0;
}