#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define det(x1, y1, x2, y2) ((x1) * (y2) - (x2) * (y1))
#define distance(x, y) (sqrt(pow(x, 2) + pow(y, 2)))
#define max(x, y) ((x) > (y) ? (x) : (y))

typedef struct {
        double x;
        double y;
} Point;

int compare(Point, Point);
void qsort1(int, int, Point*);
int convex_hull(Point*, Point*, int);
double caliper(Point*, int);
main()
{
        int i, size, qsize;
        Point *ps, *qs;
        scanf("%d", &size);
        ps = (Point*)malloc(sizeof(Point) * size);
        qs = (Point*)malloc(sizeof(Point) * size * 2);
        for (i = 0; i < size; i++) {
                scanf("%lf %lf", &ps[i].x, &ps[i].y);
        }
        qsize = convex_hull(qs, ps, size);
        printf("%.7f\n", caliper(qs, qsize));
        free(ps);
        free(qs);
}

int compare(Point arg1, Point arg2)
{
        double p1 = arg1.x - arg2.x, p2 = arg1.y - arg2.y;
        if (p1 > 0 || (p1 == 0 && p2 > 0)) {
                return 1;
        } else if (p1 < 0 || (p1 == 0 && p2 < 0)) {
                return -1;
        } else {
                return 0;
        }
}

void qsort1(int left, int right, Point *p)
{
    int i = left, j = right;
        Point pivot = p[(left + right) / 2];
    if(left >= right) return;
    do {
        while (compare(pivot, p[i]) == 1) i++;
        while (compare(pivot, p[j]) == -1) j--;
        if (i <= j) {
            Point temp = p[i];
                        p[i] = p[j];
                        p[j] = temp;
            i++;
            j--;
        }
    } while (i <= j);
    qsort1(left, j, p);
    qsort1(i, right, p);
}

int convex_hull(Point *qs, Point *ps, int size)
{
        int i, t, k = 0;
        qsort1(0, size - 1, ps);
        for (i = 0; i < size; i++) {
                while (k > 1 && det(qs[k-1].x - qs[k-2].x, qs[k-1].y - qs[k-2].y,
                                                        ps[i].x - qs[k-1].x, ps[i].y - qs[k-1].y) <= 0) {
                        k--;
                }
                qs[k++] = ps[i];
        }
        for (i = size - 2, t = k; i >= 0; i--) {
        while (k > t && det(qs[k-1].x - qs[k-2].x, qs[k-1].y - qs[k-2].y,
                            ps[i].x - qs[k-1].x, ps[i].y - qs[k-1].y) <= 0) {
            k--;
        }
        qs[k++] = ps[i];
    }
        qs = (Point*)realloc(qs, sizeof(Point) * (k - 1));
        return (k - 1);
}

double caliper(Point *qs, int qsize)
{
        int i, j, k, si, sj;
        double result = 0;
        if (qsize == 2) {
                return distance(qs[0].x - qs[1].x, qs[0].y - qs[1].y);
        }
        for (i = j = k = 0; k < qsize; k++) {
                if (compare(qs[i], qs[k]) == -1) i = k;
                if (compare(qs[j], qs[k]) == 1) j = k;
        }
        si = i;
        sj = j;
        while (i != sj || j != si) {
                result = max(result, distance(qs[i].x - qs[j].x, qs[i].y - qs[j].y));
                if (det(qs[(i+1)%qsize].x - qs[i].x, qs[(i+1)%qsize].y - qs[i].y,
                                qs[(j+1)%qsize].x - qs[j].x, qs[(j+1)%qsize].y - qs[j].y) < 0){
                        i = (i + 1) % qsize;
                } else {
                        j = (j + 1) % qsize;
                }
        }
                return result;
}

Measured memory_bytes: 2880