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 <iostream>
#include <cmath>
#include <complex>
#include <tuple>
#include <vector>
#include <algorithm>
using namespace std;

using vec = complex<double>;
using line = pair<vec,vec>;
using polygon = vector<vec>;
const double eps = 0.0000001;

double inner_product(vec u,vec v){
    return real(u*conj(v));
}
double cross_product(vec u,vec v){
    return imag(conj(u)*v);
}

vec projection(line l,vec p){//p???l???????°???±
    vec s=l.first, t=l.second;
    double k = inner_product(t-s,p-s)/inner_product(t-s,t-s);
    return (1.0-k)*s+k*t;
}

vec reflection(line l,vec p){
    return 2.0*projection(l,p)-p;
}

int ccw(vec& a, vec& b, vec& c){
    vec ab = b-a, ac = c-a;
    double o = cross_product(ab,ac);
    if(o>0) return 1; //CCW
    if(o<0) return -1; //CW
    if(inner_product(ab,ac)<0){
        return 2; //C-A-B
    }else{
        if(inner_product(ab,ab)<inner_product(ac,ac)){
            return -2; //A-B-C
        }else{
            return 0; //A-C-B
        }
    }
}

bool isIntersect(line l0, line l1){
    int s = ccw(l0.first,l0.second,l1.first)*ccw(l0.first,l0.second,l1.second);
    if(s!=0&&s!=-1&&s!=-4) return false;
    s=ccw(l1.first,l1.second,l0.first)*ccw(l1.first,l1.second,l0.second);
    if(s!=0&&s!=-1&&s!=-4) return false;
    else return true;
}

vec interSection(line l0, line l1){
    vec s0, t0, s1, t1;
    tie(s0,t0)=l0; tie(s1,t1)=l1;
    double k = cross_product(t1-s1,s1-s0)/cross_product(t1-s1,t0-s0);
    return s0+(t0-s0)*k;
}

double segLength(line l){
    return abs(l.first-l.second);
}

double distLine2point(line l, vec p){
    return abs(cross_product(l.second-l.first,p-l.first))/abs(l.second-l.first);
}

double distSeg2Point(line l, vec p){
    vec x = projection(l,p);
    double L = segLength(l);
    if(abs(x-l.first)<L&&abs(x-l.second)<L){
        return abs(x-p);
    }else{
        return min(abs(l.first-p),abs(l.second-p));
    }
}

double distSeg2Seg(line l1, line l2){
    if(isIntersect(l1,l2)) return 0;
    double ret = 1e20;
    ret = min(ret,distSeg2Point(l1,l2.first));
    ret = min(ret,distSeg2Point(l1,l2.second));
    swap(l1,l2);
    ret = min(ret,distSeg2Point(l1,l2.first));
    ret = min(ret,distSeg2Point(l1,l2.second));
    return ret;
}

double area(polygon& g){
    double S=0;
    for(auto i = g.begin()+1; i!=g.end();++i){
        S += cross_product(*(i-1),*i);
    }
    S/=2;
    return S;
}

bool isConvex(polygon& g){
    int n=g.size()-2;
    for(int i=0;i<n;i++){
        if(!~ccw(g[i],g[i+1],g[i+2]))return false;
    }
    return true;
}

bool isOnEdge(polygon& g,vec& p){
    int n=g.size()-1;
    for(int i=0;i<n;i++){
        if(!ccw(g[i],g[i+1],p)) return true;
    }
    return false;
}

bool isInside(polygon& g,vec& p){
    int n=g.size()-1,c=0;
    vec O = vec(114514,123456);
    for(int i=0;i<n;i++){
        c+=isIntersect(line(O,p),line(g[i],g[i+1]));
    }
    if(c%2) return true;
    else return false;
}

polygon convex_hull(polygon& V){
    polygon C;
    sort(V.begin(),V.end(),[](const vec& a, const vec& b){return a.imag()==b.imag() ? a.real() < b.real() : a.imag()< b.imag();});
    //?????´
    for(int i=0; i<V.size(); i++){
        vec v = V[i];
        while(C.size()>=2&&cross_product(v-C[C.size()-2],C.back()-C[C.size()-2])>0) C.pop_back();
        C.push_back(v);
    }
    //?????´
    for(int i=V.size()-2; i>=0; i--){
        vec v = V[i];
        while(C.size()>=2&&cross_product(v-C[C.size()-2],C.back()-C[C.size()-2])>0) C.pop_back();
        C.push_back(v);
    }
    C.pop_back();
    return C;
}

double diameter(polygon &C){
    int n=C.size();
    int i=0,j=0;
    for(int k=0;k<n;k++){
        if(C[k].real()<C[i].real())i=k;
        if(C[k].real()>C[j].real())j=k;
    }
    int i0=i,j0=j;
    double R=0;
    while(i!=j0||j!=i0){
        R=max(R,abs(C[i]-C[j]));
        if(cross_product(C[(i+1)%n]-C[i],C[(j+1)%n]-C[j])<0){
            i=(i+1)%n;
        }else{
            j=(j+1)%n;
        }
    }
    return R;
}

//???????????§???????????????

int main(){
    int n;
    cin >> n;
    vector<vec> V,C;
    while(n--){
        double x,y;
        cin>>x>>y;
        V.emplace_back(x,y);
    }
    C=convex_hull(V);
    cout.precision(6);
    cout << fixed;
    cout << diameter(C) << endl;
    return 0;
}