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 <vector>
#include <algorithm>

using namespace std;

inline double add(double a, double b){
    return abs(a+b)<(1e-10)*(abs(a)+abs(b)) ? 0.0 : a+b;
}

struct vec{
    double x,y;
    vec operator-(vec b){
        return (vec){add(x,-b.x),add(y,-b.y)};
    }
    vec operator+(vec b){
        return (vec){add(x,b.x),add(y,b.y)};
    }
    vec operator*(double d){
        return (vec){x*d,y*d};
    }
    double dot(vec v){
        return add(x*v.x,y*v.y);
    }
    double cross(vec v){
        return add(x*v.y,-y*v.x);
    }
    double norm(){
        return sqrt(x*x+y*y);
    }
};

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

vector<vec> convex_hull(vector<vec>& V){
    vector<vec> C;
    vector<vec>::iterator ite;
    sort(V.begin(),V.end(),[](const vec& a, const vec& b){return a.y==b.y ? a.x < b.x : a.y< b.y;});
    C.push_back(V[0]),C.push_back(V[1]);
    for(auto i=V.begin()+2; i!=V.end(); ++i){
        C.push_back(*i);        
        while(ite=C.end()-1, C.size()>2&&ccw(*(ite-2),*(ite-1),*ite)==-1){
            C.erase(ite-1);
        }
    }
    sort(V.begin(),V.end(),[](const vec& a, const vec& b){return a.y==b.y ? a.x > b.x : a.y>b.y;});
    for(auto i=V.begin()+1; i!=V.end(); ++i){
        C.push_back(*i);
        while(ite=C.end()-1, C.size()>2&&ccw(*(ite-2),*(ite-1),*ite)==-1){
            C.erase(ite-1);
        }
    }
    C.pop_back();
    return C;
}

int main(){
    int n;
    cin >> n;
    vec v;
    vector<vec> V,C;
    while(n--){
        cin >> v.x >> v.y;
        V.push_back(v);
    }
    C=convex_hull(V);
    n=C.size();
    int i=0,j=0;
    for(int k=0;k<n;k++){
        if(C[k].x<C[i].x)i=k;
        if(C[k].x>C[j].x)j=k;
    }
    int i0=i,j0=j;
    double R=0;
    while(i!=j0||j!=i0){
        R=max(R,(C[i]-C[j]).norm());
        if((C[(i+1)%n]-C[i]).cross(C[(j+1)%n]-C[j])<0){
            i=(i+1)%n;
        }else{
            j=(j+1)%n;
        }
    }
    cout.precision(6);
    cout << fixed;
    cout << R << endl;
    return 0;
}