Problem: Find the diameter of a convex polygon g. In other words, find a pair of points that have maximum distance between them.

Constraints

* 3 ≤ n ≤ 80000
* -100 ≤ xi, yi ≤ 100
* No point in the g will occur more than once.

Input


n
x1 y1
x2 y2
:
xn yn


The first integer n is the number of points in g.

In the following lines, the coordinate of the i-th point pi is given by two real numbers xi and yi. The coordinates of points are given in the order of counter-clockwise visit of them. Each value is a real number with at most 6 digits after the decimal point.

Output

Print the diameter of g in a line. The output values should be in a decimal fraction with an error less than 0.000001.

Examples

Input

3
0.0 0.0
4.0 0.0
2.0 2.0


Output

4.00


Input

4
0.0 0.0
1.0 0.0
1.0 1.0
0.0 1.0


Output

1.414213562373

Solution (in CPP):

Solution:
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <vector>

using namespace std;

const double EPS = 1e-9;
const double PI = acos(-1);

int sign(double x) {
    if (fabs(x) < EPS) {
        return 0;
    } else if (x > 0) {
        return 1;
    } else {
        return -1;
    }
}

int dcmp(double x, double y) {
    return sign(x - y);
}

struct Vector;
typedef Vector Point;

struct Vector {
    double x;
    double y;

    explicit Vector(double x = 0, double y = 0);

    Vector operator+(const Vector &rhs) const;
    Vector operator-() const;
    Vector operator-(const Vector &rhs) const;
    Vector operator*(double d) const;
    Vector operator/(double d) const;
    double operator*(const Vector &rhs) const;
    double operator^(const Vector &rhs) const;

    bool operator==(const Vector &rhs) const;
    bool operator!=(const Vector &rhs) const;
    bool operator<(const Vector &rhs) const;
    bool operator>(const Vector &rhs) const;
    bool operator<=(const Vector &rhs) const;
    bool operator>=(const Vector &rhs) const;

    friend std::ostream &operator<<(std::ostream &os, const Vector &vector);

    double dot(const Vector &rhs) const;
    double cross(const Vector &rhs) const;
    double length() const;
    double length2() const;
    double angle() const;
    double angle(const Vector &rhs) const;
    Vector rotate(double rad) const;
    Vector rotate90() const;
    Vector rotate90R() const;
    Vector normal() const;
    Vector truncate(double d) const;
    double getDistanceTo(const Point &p) const;

    static bool cmpByAngle(const Vector &a, const Vector &b);
};

Vector::Vector(double x, double y) : x(x), y(y) {}

Vector Vector::operator+(const Vector &rhs) const {
    return Vector(x + rhs.x, y + rhs.y);
}

Vector Vector::operator-() const {
    return Vector(-x, -y);
}

Vector Vector::operator-(const Vector &rhs) const {
    return *this + -rhs;
}

Vector Vector::operator*(double d) const {
    return Vector(x * d, y * d);
}

Vector Vector::operator/(double d) const {
    return *this * (1 / d);
}

double Vector::operator*(const Vector &rhs) const {
    return x * rhs.x + y * rhs.y;
}

double Vector::operator^(const Vector &rhs) const {
    return x * rhs.y - rhs.x * y;
}

bool Vector::operator==(const Vector &rhs) const {
    return dcmp(x, rhs.x) == 0 && dcmp(y, rhs.y) == 0;
}

bool Vector::operator!=(const Vector &rhs) const {
    return !(rhs == *this);
}

bool Vector::operator<(const Vector &rhs) const {
    if (dcmp(x, rhs.x) != 0) {
        return dcmp(x, rhs.x) < 0;
    } else {
        return dcmp(y, rhs.y) < 0;
    }
}

bool Vector::operator>(const Vector &rhs) const {
    return rhs < *this;
}

bool Vector::operator<=(const Vector &rhs) const {
    return !(rhs < *this);
}

bool Vector::operator>=(const Vector &rhs) const {
    return !(*this < rhs);
}

std::ostream &operator<<(std::ostream &os, const Vector &vector) {
    os << "(" << vector.x << "," << vector.y << ")";
    return os;
}

double Vector::dot(const Vector &rhs) const {
    return *this * rhs;
}

double Vector::cross(const Vector &rhs) const {
    return *this ^ rhs;
}

double Vector::length() const {
    return sqrt(*this * *this);
}

double Vector::length2() const {
    return *this * *this;
}

double Vector::angle() const {
    return atan2(y, x);
}

double Vector::angle(const Vector &rhs) const {
    return acos((*this * rhs) / length() / rhs.length());
}

Vector Vector::rotate(double rad) const {
    // Rotate counter-clockwise
    return Vector(x * cos(rad) - y * sin(rad), x * sin(rad) + y * cos(rad));
}

Vector Vector::rotate90() const {
    return Vector(-y, x);
}

Vector Vector::rotate90R() const {
    return Vector(y, -x);
}

Vector Vector::normal() const {
    double l = length();
    return Vector(-y / l, x / l);
}

double Vector::getDistanceTo(const Point &p) const {
    return sqrt(pow(x - p.x, 2) + pow(y - p.y, 2));
}

bool Vector::cmpByAngle(const Vector &a, const Vector &b) {
    return dcmp(a.angle(), b.angle()) < 0;
}

Vector Vector::truncate(double d) const {
    double l = length();
    if (sign(l) == 0) {
        return *this;
    }
    d /= l;
    return Vector(x * d, y * d);
}

std::vector<Point> convexHullAndrew(std::vector<Point> &points) {
    int n = points.size();
    sort(points.begin(), points.end());
    std::vector<int> stk(n + 2);
    std::vector<bool> used(n + 2, false);
    int top = 0;
    stk[++top] = 0;
    for (int i = 1; i < n; i++) {
        while (top >= 2 && sign((points[stk[top]] - points[stk[top - 1]]) ^ (points[i] - points[stk[top]])) <= 0) {
            used[stk[top--]] = false;
        }
        used[i] = true;
        stk[++top] = i;
    }

    int tmp = top;
    for (int i = n - 2; i >= 0; i--) {
        if (!used[i]) {
            while (top > tmp && sign((points[stk[top]] - points[stk[top - 1]]) ^ (points[i] - points[stk[top]])) <= 0) {
                used[stk[top--]] = false;
            }
            used[i] = true;
            stk[++top] = i;
        }
    }

    std::vector<Point> res;
    res.reserve(top);
    for (int i = 1; i < top; i++) {
        res.push_back(points[stk[i]]);
    }
    return res;
}

double rotatingCalipers(std::vector<Point> &points) {
    if (points.size() <= 1) {
        return 0;
    } else if (points.size() == 2) {
        return points.front().getDistanceTo(points.back());
    }

    double res = 0;
    int n = points.size();
    points.push_back(points.front());
    for (int i = 0, j = 2; i < n; i++) {
        while (dcmp((points[i + 1] - points[i]) ^ (points[j] - points[i]), (points[i + 1] - points[i]) ^ (points[j + 1] - points[i])) < 0) {
            j = (j + 1) % n;
        }
        res = std::max(res, std::max(points[j].getDistanceTo(points[i]), points[j].getDistanceTo(points[i + 1])));
    }
    points.pop_back();
    return res;
}

int main() {
//    freopen("data.in", "r", stdin);

    int n;
    while (~scanf("%d", &n)) {
        vector<Point> points;
        points.reserve(n);
        for (int i = 0; i < n; i++) {
            double x, y;
            scanf("%lf%lf", &x, &y);
            points.emplace_back(x, y);
        }

        vector<Point> convexHull = convexHullAndrew(points);
        double res = rotatingCalipers(convexHull);
        printf("%.10lf\n", res);
    }
    return 0;
}