Tìm khoảng cách lớn nhất, nhỏ nhất giữa hai cặp điểm

Tìm khoảng cách lớn nhất giữa hai cặp điểm

Bài toán: Trên mặt phẳng tọa độ cho \(N\) điểm tọa độ nguyên \((X_i, Y_i)\) \((2 \le N \le 10^5; \lvert X_i \rvert, \lvert Y_i \rvert \le 10^9)\), tìm bình phương khoảng cách lớn nhất của hai cặp điểm bất kì trong tập điểm đã cho.

Độ phức tạp: \(O(Nlog(N))\)

#include <bits/stdc++.h>

using namespace std;

#define Point Vector
struct Vector {
    int x, y;
    Vector() {}
    Vector(int _x, int _y) {
        x = _x; y = _y;
    }
    Vector operator - (const Vector &v) const {
        return Vector(x - v.x, y - v.y);
    }
    long long sqrLen() const {
        return 1LL * x * x + 1LL * y * y;
    }
    long long operator % (const Vector &v) const {
        return 1LL * x * v.y - 1LL * y * v.x;
    }
    friend long long cross (const Vector &a, const Vector &b, const Vector &c) {
        return (b-a) % (c-b);
    }
    friend bool CCW(const Point &a, const Point &b, const Point &c) {
        return cross(a, b, c) > 0;
    }
    friend bool CW(const Point &a, const Point &b, const Point &c) {
        return cross(a, b, c) < 0;
    }
    friend long long sqrDist(const Point &a, const Point &b) {
        return (a-b).sqrLen();
    }
    bool operator < (const Vector &v) const {
        return make_pair(x, y) < make_pair(v.x, v.y);
    }
    bool operator == (const Vector &v) const {
        return make_pair(x, y) == make_pair(v.x, v.y);
    }
};

int numPoint;
vector<Point> points;

vector<Point> ConvexHull(vector<Point> points) {
    sort(points.begin(),points.end());
    points.resize(unique(points.begin(),points.end()) - points.begin());
    if ((int)points.size() <= 2) return points;
    Point lef = points.front();
    Point rig = points.back();
    vector<Point> up, down;
    for (int i = 0; i < (int)points.size(); ++i) {
        if (i == 0 || i == (int)points.size()-1 || CW(lef, points[i], rig)) {
            while ((int)up.size() > 1 && !CW(up[(int)up.size()-2], up.back(), points[i]))
                up.pop_back();
            up.push_back(points[i]);
        }
        if (i == 0 || i == (int)points.size()-1 || CCW(lef, points[i], rig)) {
            while ((int)down.size() > 1 && !CCW(down[(int)down.size()-2], down.back(), points[i]))
                down.pop_back();
            down.push_back(points[i]);
        }
    }
    for (int i = (int)up.size()-2; i > 0; --i) {
        down.push_back(up[i]);
    }
    return down;
}

long long maximumDistance(vector<Point> points) {
    vector<Point> hull = ConvexHull(points);
    long long res = 0;
    for (int i = 0, j = 0; i < (int)hull.size(); ++i) {
        while (j < (int)hull.size()-1 && sqrDist(hull[i], hull[j]) < sqrDist(hull[i], hull[j+1])) {
            j++;
        }
        res = max(res, sqrDist(hull[i], hull[j]));
    }
    return res;
}

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    cin >> numPoint;
    for (int i = 0; i < numPoint; ++i) {
        int x, y;
        cin >> x >> y;
        points.emplace_back(x, y);
    }   
    cout << maximumDistance(points);
    return 0;
}

Tìm khoảng cách nhỏ nhất giữa hai cặp điểm

Đề bài: https://cses.fi/problemset/task/2194

Độ phức tạp: \(O(Nlog(N))\)

#include <bits/stdc++.h>

using namespace std;

#define Point Vector
struct Vector {
    int x, y;
    Vector() {}
    Vector(int _x, int _y) {
        x = _x; y = _y;
    }
    Vector operator - (const Vector &v) const {
        return Vector(x-v.x,y-v.y);
    }
    long long sqrLen() const {
        return 1LL * x * x + 1LL * y * y;
    }
    friend long long sqrDist(const Point &a, const Point &b) {
        return (a-b).sqrLen();
    }
    bool operator < (const Vector &v) const {
        return make_pair(y, x) < make_pair(v.y, v.x);
    }
};

const long long INFLL = 9e18;
const int INF = 2e9;
int numPoint;
vector<Point> points;

long long mySqr(long long x) {
    return x * x;
}

long long ceilSqrt(long long x) {
    long long i = sqrt(x);
    while (i*i > x) i--;
    while (i*i < x) i++;
    return i;
}

long long minimumDistance(vector<Point> points) {
    set<Point> heap;
    long long cur = INFLL;
    sort(points.begin(), points.end(), [&](const Point &a, const Point &b) {
        return make_pair(a.x, a.y) < make_pair(b.x, b.y);
    });
    for (int i = 0, j = 0; i < (int)points.size(); ++i) {
        while (mySqr(points[i].x-points[j].x) >= cur) {
            heap.erase(points[j]);
            j++;
        }
        if (!heap.empty()) {
            long long tmp = ceilSqrt(cur);
            auto down = heap.upper_bound(Point(points[i].x, max(-1LL * INF, points[i].y - tmp)));
            auto up = heap.upper_bound(Point(points[i].x, min(1LL * INF, points[i].y + tmp)));
            for (auto it = down; it != up; ++it) {
                if (sqrDist(points[i], *it) < cur) {
                    cur = sqrDist(points[i], *it);
                }
            }
        }
        heap.insert(points[i]);
    }
    return cur;
}

int main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    cin >> numPoint;
    for (int i = 0; i < numPoint; ++i) {
        int x, y;
        cin >> x >> y;
        points.emplace_back(x, y);
    }   
    cout << minimumDistance(points);
    return 0;
}

Nguồn tham khảo