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<bits/stdc++.h>
#define For(i,x,y) for (register int i=(x);i<=(y);i++)
#define FOR(i,x,y) for (register int i=(x);i<(y);i++)
#define Dow(i,x,y) for (register int i=(x);i>=(y);i--)
#define mp make_pair
#define fi first
#define se second
#define pb push_back
#define siz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define fil(a,b) memset((a),(b),sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pa;
typedef double db;
inline ll read(){
    ll x=0,f=1;char c=getchar();
    while ((c<'0'||c>'9')&&(c!='-')) c=getchar();
    if (c=='-') f=-1,c=getchar();
    while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    return x*f;
}

namespace Geometry{
	const db eps = 1e-9;
	struct point{
		db x,y;
		inline point operator + (const point &p){return (point){x+p.x,y+p.y};}
		inline point operator - (const point &p){return (point){x-p.x,y-p.y};}
		inline db operator * (const point &p){return x*p.x+y*p.y;}
		inline point operator / (const db &v){return (point){x/v,y/v};}
		inline point operator * (const db &v){return (point){x*v,y*v};}
		inline db len(){return sqrt(x*x+y*y);}
	};
	typedef point vec;
	inline db dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
	inline db sqr(db x){return x*x;}
	inline db dis(point a,point b){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}
	inline db dis2(point a,point b){return sqr(a.x-b.x)+sqr(a.y-b.y);}
	inline db cross(vec a,vec b){return a.x*b.y-a.y*b.x;}
	struct line{
		point a,b;
		inline db len(){return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));}
	};
	inline point projection(point A,line b){
		point B=b.a,C=b.b;
		vec BA=A-B,BC=C-B,BD=BC*(BA*BC/dis2(B,C));
		return B+BD;
	}
	inline point reflection(point A,line b){
		point D=projection(A,b);
		return (point){D.x*2-A.x,D.y*2-A.y};
	}
	inline int Counter_Clockwise(point A,line b){
		point B=b.a,C=b.b;
		db f1=cross(C-B,A-B);
		if (fabs(f1)>eps) return (f1<0?2:1);
		db f2=(C-B)*(A-B);
		if (f2<0) return 3;
		return dis(B,C)<dis(A,B)?4:5;
	}
	inline int checkline(line a,line b){
		vec A=a.b-a.a,B=b.b-b.a;
		db f1=A*B;
		if (fabs(f1)<=eps) return 1;
		return fabs(cross(A,B))<=eps?2:0;
	}
	inline bool checkseg(line a,line b){
		point A=a.a,B=a.b,C=b.a,D=b.b;
		if (max(A.x,B.x)<min(C.x,D.x)) return 0;
		if (min(A.x,B.x)>max(C.x,D.x)) return 0;
		if (max(A.y,B.y)<min(C.y,D.y)) return 0;
		if (min(A.y,B.y)>max(C.y,D.y)) return 0;
		db s=cross(B-A,C-A),h=cross(B-A,D-A);
		if (s*h>=eps) return 0;
		db i=cross(D-C,A-C),t=cross(D-C,B-C);
		return i*t<=eps;
	}
	inline point crosspoint(line a,line b){
		point A=a.a,B=a.b,C=b.a,D=b.b;
		db s1=fabs(cross(B-A,C-A)),s2=fabs(cross(B-A,D-A));
		vec CO=(D-C)*(s1/(s1+s2));
		return C+CO;
	}
	inline db dis(point	A,line b){
		point B=b.a,C=b.b,D=projection(A,b);
		int tmp=Counter_Clockwise(D,b);
		if (tmp==3) return dis(B,A);
		if (tmp==4) return dis(C,A);
		if (tmp==5) return dis(D,A);
	}
	inline db dis(line a,line b){
		if (checkseg(a,b)) return 0;
		db s=dis(a.a,b),h=dis(a.b,b),i=dis(b.a,a),t=dis(b.b,a);
		return min({s,h,i,t});
	}
	typedef vector<point> polygon;
	inline db S(polygon v){
		db s=cross(v.back(),v[0]);
		For(i,0,siz(v)-2) s+=cross(v[i],v[i+1]);
		return s/2;
	}
	inline bool check(polygon v){
		int n=siz(v),f=(cross(v[n-1]-v[n-2],v[0]-v[n-1])>=-eps);
		For(i,1,n-2) if ((cross(v[i]-v[i-1],v[i+1]-v[i])>=-eps)!=f) return 0;
		return 1;
	}
	inline int check(point a,polygon v){
		db k=sqrt(23);point b=(point){a.x+1000000000,a.y+k*1000000000};
		int n=siz(v);bool f=0;
		FOR(i,0,n){
			if (Counter_Clockwise(a,(line){v[i],v[(i+1)%n]})==5) return 1;
			if (checkseg((line){v[i],v[(i+1)%n]},(line){a,b})) f^=1;
		}
		return !f?0:2;
	}
	int top;
	vector<int>stk;
	inline polygon Convex_Hull(polygon v){
		sort(all(v),[](point a,point b){
			return a.y<b.y||(a.y==b.y&&a.x<b.x);
		});
		int n=siz(v);point o=v[0];
		Dow(i,n-1,0) v[i]=v[i]-o;
		sort(all(v),[](point a,point b){
			db tmp=cross(a,b);
			return tmp>0||(fabs(tmp)<=eps&&a.len()<b.len());
		});
		top=0,stk.resize(n+1);
		FOR(i,0,n){
			while (top>=2&&cross(v[i]-v[stk[top-1]],v[stk[top]]-v[stk[top-1]])>=0) --top;
			stk[++top]=i;
		}
		polygon ret;
		For(i,1,top) ret.pb(v[stk[i]]+o);
		return ret;
	}
	inline db D(polygon v){
		auto dis=[](point a,line b) -> db{
			return cross(b.a-a,b.b-a)/b.len();
		};
		int h=0,n=siz(v);db ans=0;
		FOR(i,0,n-1){
			while (dis(v[h],(line){v[i],v[i+1]})<=dis(v[(h+1)%n],(line){v[i],v[i+1]})) h=(h+1)%n;
			ans=max({ans,(v[i]-v[h]).len(),(v[i+1]-v[h]).len()});
		}
		return ans;
	}
};
using namespace Geometry;

int main(){
//	freopen("data.in","r",stdin);
	int n=read();polygon v(n);
	FOR(i,0,n) scanf("%lf%lf",&v[i].x,&v[i].y);
	printf("%0.10lf",D(v));
}