Editorial for Mini Multiverse


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.

Submitting an official solution before solving the problem yourself is a bannable offence.
#include <iostream>
#include <algorithm>    //using sort
#include <vector>
#include <cstdio>
#include <cmath>

using namespace std;



#define ll long long

struct Point{
    ll x,y;
    void input(){
        cin>>x>>y;
        x=abs(x);
        y=abs(y);
    }
};

Point arr[1000000];






bool compareX(Point a, Point b){
    return a.x<b.x;
}

bool compareY(Point a, Point b){
    return a.y<b.y;
}

ll dist(Point a,Point b){
    return abs(a.x-b.x)+abs(a.y-b.y);
}

// only takes n=2 or n=3
ll base_case(Point *points, int n){
    ll minDist=dist(points[0],points[1]);
    if(n==3){
        ll dist2=dist(points[0],points[2]);
        ll dist3=dist(points[2],points[1]);
        minDist=min(minDist,min(dist2,dist3));
    }
    return minDist;
}

ll recursive_solve(Point *points, int n){
    if (n < 4)             //since 3 would 
        return base_case(points, n);

    int mid            = n / 2;
    ll minLeft         = recursive_solve(points,     mid);
    ll minRight        = recursive_solve(points+mid, n-mid);
    ll minDist = min(minLeft, minRight);
    //O(n) here             could be more optimal (by checking from mid to edges) but its already under bounding complexity and worst case doesn't change
        //O(nlogn) in total
    vector<Point> additional;
    for (int i=0; i < n; i++){
        if (abs(points[i].x - points[mid].x) < minDist)
            additional.push_back(points[i]);
    }

    // O(nlogn) here
        //O(nlognlogn) in total

    sort(additional.begin(), additional.end(), compareY);               
    // O(n) because inner loop is actually constant
        // O(nlogn) in total
    for (int i=0;i<additional.size();i++) {

        //this looks like O(n) but it comes up to constant(at most 5)
        for (int j=i+1;j<additional.size() && (additional[j].y-additional[i].y)<minDist; j++){
            minDist = min(minDist, dist(additional[i], additional[j]));
        }
    }
    return minDist;
}


// Complexity Calculation

// nlogn                       = nlogn
// 2*n/2log(n/2)               = nlogn-n
// 4*n/4log(n/4)               = nlogn-2n
// 8*n/8log(n/8)               = nlogn-3n
// ...
// ...
// ...
// (n/2)*n/(n/2)log(n/(n/2))   = nlogn-logn*n

// nlogn*logn-n*logn*(logn-1)/2
// nlogn*(logn+1)/2

// O(nlognlogn)


int main(){
    ll n;
    cin>>n;
    for(int i=0;i<n;i++)arr[i].input();
    sort(arr,arr+n,compareX);

    cout<<recursive_solve(arr,n)<<endl;
}