Problem:
Fair Chocolate-Cutting
You are given a flat piece of chocolate of convex polygon shape. You are to cut it into two pieces of precisely the same amount with a straight knife.
Write a program that computes, for a given convex polygon, the maximum and minimum lengths of the line segments that divide the polygon into two equal areas.
The figures below correspond to first two sample inputs. Two dashed lines in each of them correspond to the equal-area cuts of minimum and maximum lengths.
Figure F.1. Sample Chocolate Pieces and Cut Lines
Input
The input consists of a single test case of the following format.
$n$
$x_1$ $y_1$
...
$x_n$ $y_n$
The first line has an integer $n$, which is the number of vertices of the given polygon. Here, $n$ is between 3 and 5000, inclusive. Each of the following $n$ lines has two integers $x_i$ and $y_i$, which give the coordinates ($x_i, y_i$) of the $i$-th vertex of the polygon, in counterclockwise order. Both $x_i$ and $y_i$ are between 0 and 100 000, inclusive.
The polygon is guaranteed to be simple and convex. In other words, no two edges of the polygon intersect each other and interior angles at all of its vertices are less than $180^\circ$.
Output
Two lines should be output. The first line should have the minimum length of a straight line segment that partitions the polygon into two parts of the equal area. The second line should have the maximum length of such a line segment. The answer will be considered as correct if the values output have an absolute or relative error less than $10^{-6}$.
Sample Input 1
4
0 0
10 0
10 10
0 10
Sample Output 1
10
14.142135623730950488
Sample Input 2
3
0 0
6 0
3 10
Sample Output 2
4.2426406871192851464
10.0
Sample Input 3
5
0 0
99999 20000
100000 70000
33344 63344
1 50000
Sample Output 3
54475.580091580027976
120182.57592539864775
Sample Input 4
6
100 350
101 349
6400 3440
6400 3441
1200 7250
1199 7249
Sample Output 4
4559.2050019027964982
6216.7174287968524227

Submitted solutions:

code_snippet: // AOJ #1394 Fair Chocolate-Cutting
// 2025.4.24

#include <bits/stdc++.h>
using namespace std;
using ld = long double;

#define gc() getchar_unlocked()

int Cin() {
	int n = 0, c = gc();
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

struct P { ld x,y; };
inline P operator+(const P&a,const P&b){ return {a.x+b.x, a.y+b.y}; }
inline P operator-(const P&a,const P&b){ return {a.x-b.x, a.y-b.y}; }
inline P operator*(const P&a,ld t){ return {a.x*t, a.y*t}; }
inline ld cr(const P&a,const P&b){ return a.x*b.y - a.y*b.x; }
inline ld dot(const P&a,const P&b){ return a.x*b.x + a.y*b.y; }
inline ld norm(const P&a){ return sqrt(dot(a,a)); }

ld area_poly(const vector<P>& v){
    int m = v.size();
    ld A = 0;
    for(int i=0;i<m;i++){
        int j=(i+1)%m;
        A += cr(v[i], v[j]);
    }
    return fabsl(A)*0.5;
}

ld area_clipped(const vector<P>& in, const P& nrm, ld c){
    vector<P> out;
    int m=in.size();
    out.reserve(m+2);
    for(int i=0;i<m;i++){
        P A=in[i], B=in[(i+1)%m];
        ld va=dot(nrm,A)-c, vb=dot(nrm,B)-c;
        bool ina = (va<=0), inb=(vb<=0);
        if(ina) out.push_back(A);
        if(ina^inb){
            ld t = va/(va-vb);
            out.push_back(A + (B-A)*t);
        }
    }
    return area_poly(out);
}

ld chord_len(const vector<P>& poly, const vector<ld>& proj,
                 ld halfA, ld lo, ld hi, ld theta){
    int n = poly.size();
    P nrm = {cosl(theta), sinl(theta)};
    ld l=lo, r=hi;
    for(int it=0; it<50; ++it){
        ld mid=(l+r)*0.5;
        if(area_clipped(poly,nrm,mid) < halfA) l=mid;
        else r=mid;
    }
    ld c=(l+r)*0.5;
    vector<P> ip;
    ip.reserve(4);
    for(int i=0;i<n;i++){
        P A=poly[i], B=poly[(i+1)%n];
        ld va=dot(nrm,A)-c, vb=dot(nrm,B)-c;
        if(va==0) ip.push_back(A);
        if(va*vb<0){
            ld t=va/(va-vb);
            ip.push_back(A + (B-A)*t);
        }
        if(vb==0) ip.push_back(B);
    }
    P dir = {-nrm.y, nrm.x};
    ld plo=1e300, phi=-1e300;
    for(auto&p:ip){
        ld d=dot(dir,p);
        plo=min(plo,d); phi=max(phi,d);
    }
    return (phi-plo)/norm(dir);
}

int main(){
    int n = Cin();
    vector<P> a(n);
    for(int i=0;i<n;i++) a[i].x = Cin(), a[i].y = Cin();

    ld A = area_poly(a);
    ld halfA = A*0.5;

    vector<P> b(2*n+1);
    for(int i=0;i<2*n+1;i++) b[i]=a[i%n];
    vector<ld> pr(2*n+1,0);
    for(int i=0;i<2*n;i++) pr[i+1]=pr[i]+cr(b[i],b[i+1]);
    ld tg2 = pr[n]/2;
    ld mx=0, mn=1e300;
    int j=1;
    for(int i=0;i<n;i++){
        if(j<=i) j=i+1;
        while(j+1<i+n && pr[j+1]-pr[i]+cr(b[j+1],b[i]) <= tg2) j++;
        ld Aij = pr[j]-pr[i] + cr(b[j],b[i]);
        P v1={b[j].x-b[i].x, b[j].y-b[i].y};
        P v2={b[j+1].x-b[i].x, b[j+1].y-b[i].y};
        ld dcr = cr(v1,v2);
        ld t = (tg2 - Aij)/dcr;
        P q = { b[j].x + (b[j+1].x-b[j].x)*t,
                b[j].y + (b[j+1].y-b[j].y)*t };
        ld d = norm(a[i]-q);
        mn = min(mn, d);
        mx = max(mx, d);
    }

    vector<ld> proj(n);
    const int M = 200;
    ld bestTh=0;
    for(int k=0;k<M;k++){
        ld th = M_PI * k / M;
        ld loV=1e300, hiV=-1e300;
        for(int i=0;i<n;i++){
            ld v = a[i].x*cosl(th) + a[i].y*sinl(th);
            loV=min(loV,v);
            hiV=max(hiV,v);
        }
        ld len = chord_len(a,proj,halfA, loV, hiV, th);
        if(len < mn) mn = len, bestTh = th;
    }
    ld L = bestTh - M_PI/M, R = bestTh + M_PI/M;
    for(int it=0; it<100; it++){
        ld m1 = L + (R-L)/3, m2 = R - (R-L)/3;
        ld lo1=1e300, hi1=-1e300, lo2=1e300, hi2=-1e300;
        for(int i=0;i<n;i++){
            ld v1=a[i].x*cos(m1)+a[i].y*sin(m1);
            ld v2=a[i].x*cos(m2)+a[i].y*sin(m2);
            lo1=min(lo1,v1); hi1=max(hi1,v1);
            lo2=min(lo2,v2); hi2=max(hi2,v2);
        }
        ld f1 = chord_len(a,proj,halfA,lo1,hi1, m1);
        ld f2 = chord_len(a,proj,halfA,lo2,hi2, m2);
        if(f1 < f2) R = m2;
        else L = m1;
    }
    {
        ld th = 0.5*(L+R);
        ld loV=1e300, hiV=-1e300;
        for(int i=0;i<n;i++){
            ld v = a[i].x*cos(th) + a[i].y*sin(th);
            loV=min(loV,v);
            hiV=max(hiV,v);
        }
        mn = min(mn, chord_len(a,proj,halfA, loV, hiV, th));
    }

    cout << fixed<<setprecision(15)
        << mn << endl
        << mx << endl;
    return 0;
}
accuracy: 0.3291139240506329
time_ms: 530
memory_kb: 3964
final_rank: 19

code_snippet: #include<bits/stdc++.h>
#define rep(i,s,n) for (int i = (int)(s); i < (int)(n); i++)
#define all(v) begin(v),end(v)
using namespace std;
using ll = long long;
bool chmin(auto &a, auto b){ return a > b ? a = b, 1 : 0; }
bool chmax(auto &a, auto b){ return a < b ? a = b, 1 : 0; }

using ld = long double;
using vec = complex<ld>;

ld dot(vec a, vec b) {
    return (conj(a) * b).real();
}

ld cross(vec a, vec b) {
    return (conj(a) * b).imag();
}

// area of triangle * 2
ld tri(vec a, vec b, vec c) {
    return abs(cross(b - a, c - a));
}

ld area(int n, vector<vec> a) {
    ld ans = 0;
    rep(i,2,n) {
        ans += tri(a[i],a[i-1],a[0]);
    }
    return ans;
}

const ld eps = 1e-8;

// le -- v -- ri
// tri(ctr, le, v) == tar
vec findvec(vec ctr, vec le, vec ri, ld tar) {
    ld full = tri(ctr, le, ri);
    // cout << tar << ' ' << full << endl;
    if (tar > full) {
        return vec(1e9,1e9);
    }
    assert(-eps < tar && tar < full + eps);
    return le + (ri - le) * tar / full;
}

ld calcmax(int n, vector<vec> a) {
    ld ans = 0;
    ld half = area(n, a) / 2;
    rep(i,0,n) a.emplace_back(a[i]);
    rep(i,0,n) {
        ld cur = 0;
        int stopj = -1;
        rep(j,i+2,i+n) {
            ld add = tri(a[j],a[j-1],a[i]);
            if (cur + add < half) {
                cur += add;
            }
            else {
                stopj = j;
                break;
            }
        }
        assert(stopj != -1);
        vec farvec = findvec(a[i], a[stopj-1], a[stopj], half - cur);
        chmax(ans, abs(farvec - a[i]));
    }
    return ans;
}

ld calcmin(int n, vector<vec> a) {
    ld ans = 1e18;
    ld half = area(n, a) / 2;
    rep(i,0,n*2) a.emplace_back(a[i]);
    auto proc = [&](int i, int j, ld icur, ld jcur) {
        vec j0 = a[j], j1 = a[j+1];
        if (tri(a[i],a[j],a[j+1]) + icur > half) {
            j0 = findvec(a[i],a[j+1],a[j],half - icur);
        }
        if (tri(a[i+1],a[j],a[j+1]) + jcur > half) {
            j1 = findvec(a[i+1],a[j],a[j+1],half - jcur);
        }
        auto get = [&](vec from) {
            vec to = findvec(from, a[i], a[i+1], half - icur - tri(a[i],from,a[j+1]));
            return abs(from - to);
        };
        int many = 120;
        while (many--) {
            vec m1 = (j0 + j0 + j1) / ld(3);
            vec m2 = (j0 + j1 + j1) / ld(3);
            if (get(m1) < get(m2)) {
                j1 = m2;
            }
            else {
                j0 = m1;
            }
        }
        chmin(ans, get(j1));
    };
    rep(i,0,n) {
        int j = i+1;
        ld sml = 0, smr = half*2 - tri(a[i],a[j],a[j+1]);
        while (j + 1 <= n + i) {
            if (sml <= half && smr <= half) {
                proc(i,j,smr,sml);
            }
            sml += tri(a[i+1],a[j],a[j+1]);
            smr -= tri(a[i],a[j+1],a[j+2]);
            j++;
        }
    }
    return ans;
}

ld calcmin2(int n, vector<vec> a) {
    ld ans = 1e18;
    ld half = area(n, a) / 2;
    rep(i,0,n) a.emplace_back(a[i]);
    rep(i,0,n) {
        ld cur = 0;
        int stopj = -1;
        rep(j,i+2,i+n) {
            ld add = tri(a[j],a[j-1],a[i]);
            if (cur + add < half + eps) {
                cur += add;
            }
            else {
                stopj = j;
                break;
            }
        }
        assert(stopj != -1);
        vec u1 = findvec(a[i], a[stopj-1], a[stopj], half - cur);
        vec u2 = a[stopj];
        vec l1 = a[i];
        vec l2 = a[i+1];
        if (tri(u1,u2,l1) > tri(l1,l2,u1)) {
            swap(u1,l1);
            swap(u2,l2);
        }
        auto get = [&](vec from) {
            return findvec(u1, l1, l2, tri(from, u1, l1));
        };
        vec le = u1, ri = u2;
        int many = 120;
        while (many--) {
            vec m1 = (le + le + ri) / ld(3);
            vec m2 = (le + ri + ri) / ld(3);
            vec v1 = get(m1);
            vec v2 = get(m2);
            ld d1 = abs(v1 - m1);
            ld d2 = abs(v2 - m2);
            if (d1 < d2) {
                ri = m2;
            }
            else {
                le = m1;
            }
        }
        chmin(ans, abs(get(ri) - ri));
    }
    return ans;
}

void solve() {
    int n; cin >> n;
    vector<vec> a(n);
    rep(i,0,n) {
        ld x, y; cin >> x >> y;
        a[i] = {x, y};
    }
    ld maxans = calcmax(n, a);
    ld minans = calcmin(n, a);
    cout << minans << endl;
    cout << maxans << endl;
}

int main() {
    cin.tie(0)->sync_with_stdio(0);
    cout << fixed << setprecision(15);
    solve();
}
accuracy: 1
time_ms: 820
memory_kb: 4620
final_rank: 9

code_snippet: #include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;

struct Point {
	double px, py;
};

Point operator+(const Point& a1, const Point& a2) {
	return Point{ a1.px + a2.px, a1.py + a2.py };
}

Point operator*(const Point& a1, const double a2) {
	return Point{ a1.px * a2, a1.py * a2 };
}

int N;
Point G[10009];
double S[10009], AreaSum;

// P1, P2 の距離を求める
double Distance(Point P1, Point P2) {
	return sqrt((P1.px - P2.px) * (P1.px - P2.px) + (P1.py - P2.py) * (P1.py - P2.py));
}

// 頂点 l, l+1, ..., r のみを含む多角形の面積
double Calculate_Area(int l, int r) {
	if (r - l <= 1) {
		return 0.0;
	}

	// 頂点数 >= 3 の場合
	double val = (G[l].px - G[r].px) * (G[l].py + G[r].py);
	if (l == 0) {
		return abs(S[r] + val);
	}
	return abs(S[r] - S[l] + val);
}

// vector 型で与えられる多角形の面積
double Calculate_Area2(vector<Point> G) {
	double ret = 0;
	for (int i = 0; i < G.size(); i++) {
		Point P1 = G[(i + 1) % G.size()];
		Point P2 = G[i];
		double val = (P1.px - P2.px) * (P1.py + P2.py);
		ret += val;
	}
	return abs(ret);
}

// 面積を判定する
double solve_precise2(int l, int r, double Progress, double cm) {
	Point A1 = G[l] * (1.0 - Progress) + G[l - 1] * Progress;
	Point A2 = G[l];
	Point A3 = G[r - 1];
	Point A4 = G[r - 1] * (1.0 - cm) + G[r] * cm;
	return Calculate_Area2(vector<Point>{A1, A2, A3, A4});
}

// 二分探索で詳細に解く
double solve_precise(int l, int r, double Goal, double Progress) {
	double val1 = solve_precise2(l, r, Progress, 0.0);
	double val2 = solve_precise2(l, r, Progress, 1.0);
	double cm = (Goal - val1) / (val2 - val1);

	// 判定
	if (cm < 0.0) return -1e9;
	else if (cm > 1.0) return 1e9;

	// 距離を求める
	Point A1 = G[l] * (1.0 - Progress) + G[l - 1] * Progress;
	Point A4 = G[r - 1] * (1.0 - cm) + G[r] * cm;
	return Distance(A1, A4);
}

// 選んだ 2 辺が l, r の場合に解く
pair<double, double> solve(int l, int r) {
	double Area1 = Calculate_Area(l, r - 1);
	double Area2 = Calculate_Area(r, l + N - 1);
	if (Area1 > AreaSum) return make_pair(1e9, -1e9);
	if (Area2 > AreaSum) return make_pair(1e9, -1e9);

	// 答えの初期化
	double AnswerMin = 1e9;
	double AnswerMax = -1e9;

	// 最大値を求める [Part1]
	double cl = 0.0, cr = 1.0, cm, c1, c2;
	for (int i = 0; i < 50; i++) {
		cm = (cl + cr) / 2.0;
		double F1 = solve_precise(l, r, AreaSum - Area1, cm);
		if (F1 > 1e8) { cl = cm; }
		else {
			if (F1 > -1e8) AnswerMax = max(AnswerMax, F1);
			cr = cm;
		}
	}

	// 最大値を求める [Part2]
	cl = 0.0; cr = 1.0;
	for (int i = 0; i < 50; i++) {
		cm = (cl + cr) / 2.0;
		double F1 = solve_precise(l, r, AreaSum - Area1, cm);
		if (F1 < -1e8) { cl = cm; }
		else {
			if (F1 < 1e8) AnswerMax = max(AnswerMax, F1);
			cr = cm;
		}
	}

	// 最小値を求める
	cl = 0.0; cr = 1.0;
	for (int i = 0; i < 80; i++) {
		c1 = (cl + cl + cr) / 3.0;
		c2 = (cl + cr + cr) / 3.0;
		double ret1 = solve_precise(l, r, AreaSum - Area1, c1);
		double ret2 = solve_precise(l, r, AreaSum - Area1, c2);
		if (ret1 >= -1e8 && ret1 <= 1e8) AnswerMin = min(AnswerMin, ret1);
		if (ret2 >= -1e8 && ret2 <= 1e8) AnswerMin = min(AnswerMin, ret2);
		if (ret1 > 1e8) { cl = c1; }
		else if (ret2 < -1e8) { cr = c2; }
		else if (ret1 > ret2) { cl = c1; }
		else { cr = c2; }
	}

	// 答えを返す
	return make_pair(AnswerMin, AnswerMax);
}

int main() {
	// Input
	cin >> N;
	for (int i = 0; i < N; i++) cin >> G[i].px >> G[i].py;
	for (int i = N; i <= 2 * N + 1; i++) {
		G[i].px = G[i % N].px;
		G[i].py = G[i % N].py;
	}

	// Calculate Rusekiwa
	S[0] = 0;
	for (int i = 1; i <= 2 * N; i++) {
		double p1 = (G[i].px - G[i - 1].px) * (G[i].py + G[i - 1].py);
		S[i] = S[i - 1] + p1;
	}
	AreaSum = abs(S[N]) / 2.0;

	// Search
	double Answer_Min = 1e9;
	double Answer_Max = -1e9;
	for (int l = 1; l <= N; l++) {
		for (int r = l + 1; r <= l + N - 1; r++) {
			pair<double, double> ret = solve(l, r);
			Answer_Min = min(Answer_Min, ret.first);
			Answer_Max = max(Answer_Max, ret.second);
		}
	}

	// Output
	printf("%.12lf\n", Answer_Min);
	printf("%.12lf\n", Answer_Max);
	return 0;
}
accuracy: 1
time_ms: 340
memory_kb: 3740
final_rank: 4

code_snippet: #include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;

struct Point {
	double px, py;
};

Point operator+(const Point& a1, const Point& a2) {
	return Point{ a1.px + a2.px, a1.py + a2.py };
}

Point operator*(const Point& a1, const double a2) {
	return Point{ a1.px * a2, a1.py * a2 };
}

int N;
Point G[10009];
double S[10009], AreaSum;

// P1, P2 の距離を求める
double Distance(Point P1, Point P2) {
	return sqrt((P1.px - P2.px) * (P1.px - P2.px) + (P1.py - P2.py) * (P1.py - P2.py));
}

// 頂点 l, l+1, ..., r のみを含む多角形の面積
double Calculate_Area(int l, int r) {
	if (r - l <= 1) {
		return 0.0;
	}

	// 頂点数 >= 3 の場合
	double val = (G[l].px - G[r].px) * (G[l].py + G[r].py);
	if (l == 0) {
		return abs(S[r] + val);
	}
	return abs(S[r] - S[l] + val);
}

// vector 型で与えられる多角形の面積
double Calculate_Area2(vector<Point> G) {
	double ret = 0;
	for (int i = 0; i < G.size(); i++) {
		Point P1 = G[(i + 1) % G.size()];
		Point P2 = G[i];
		double val = (P1.px - P2.px) * (P1.py + P2.py);
		ret += val;
	}
	return abs(ret);
}

// 二分探索で詳細に解く
double solve_precise(int l, int r, double Goal, double Progress) {
	Point A1 = G[l] * (1.0 - Progress) + G[l - 1] * Progress;
	Point A2 = G[l];
	Point A3 = G[r - 1];
	Point A4;

	// 二分探索
	double cl = -0.01, cr = 1.01, cm;
	for (int i = 0; i < 28; i++) {
		cm = (cl + cr) / 2.0;
		A4 = G[r - 1] * (1.0 - cm) + G[r] * cm;
		double Area = Calculate_Area2(vector<Point>{A1, A2, A3, A4});
		if (Area < Goal) {
			cl = cm;
		}
		else {
			cr = cm;
		}
	}

	// 判定
	if (cm < 0.0) return -1e9;
	else if (cm > 1.0) return 1e9;
	return Distance(A1, A4);
}

// 選んだ 2 辺が l, r の場合に解く
pair<double, double> solve(int l, int r) {
	double Area1 = Calculate_Area(l, r - 1);
	double Area2 = Calculate_Area(r, l + N - 1);
	if (Area1 > AreaSum) return make_pair(1e9, -1e9);
	if (Area2 > AreaSum) return make_pair(1e9, -1e9);

	// 答えの初期化
	double AnswerMin = 1e9;
	double AnswerMax = -1e9;

	// 最大値を求める [Part1]
	double cl = 0.0, cr = 1.0, cm, c1, c2;
	for (int i = 0; i < 28; i++) {
		cm = (cl + cr) / 2.0;
		double F1 = solve_precise(l, r, AreaSum - Area1, cm);
		if (F1 > 1e8) { cl = cm; }
		else {
			if (F1 > -1e8) AnswerMax = max(AnswerMax, F1);
			cr = cm;
		}
	}

	// 最大値を求める [Part2]
	cl = 0.0; cr = 1.0;
	for (int i = 0; i < 28; i++) {
		cm = (cl + cr) / 2.0;
		double F1 = solve_precise(l, r, AreaSum - Area1, cm);
		if (F1 < -1e8) { cl = cm; }
		else {
			if (F1 < 1e8) AnswerMax = max(AnswerMax, F1);
			cr = cm;
		}
	}

	// 最小値を求める
	cl = 0.0; cr = 1.0;
	for (int i = 0; i < 48; i++) {
		c1 = (cl + cl + cr) / 3.0;
		c2 = (cl + cr + cr) / 3.0;
		double ret1 = solve_precise(l, r, AreaSum - Area1, c1);
		double ret2 = solve_precise(l, r, AreaSum - Area1, c2);
		if (ret1 >= -1e8 && ret1 <= 1e8) AnswerMin = min(AnswerMin, ret1);
		if (ret2 >= -1e8 && ret2 <= 1e8) AnswerMin = min(AnswerMin, ret2);
		if (ret1 > 1e8) { cl = c1; }
		else if (ret2 < -1e8) { cr = c2; }
		else if (ret1 > ret2) { cl = c1; }
		else { cr = c2; }
	}

	// 答えを返す
	return make_pair(AnswerMin, AnswerMax);
}

int main() {
	// Input
	cin >> N;
	for (int i = 0; i < N; i++) cin >> G[i].px >> G[i].py;
	for (int i = N; i <= 2 * N + 1; i++) {
		G[i].px = G[i % N].px;
		G[i].py = G[i % N].py;
	}

	// Calculate Rusekiwa
	S[0] = 0;
	for (int i = 1; i <= 2 * N; i++) {
		double p1 = (G[i].px - G[i - 1].px) * (G[i].py + G[i - 1].py);
		S[i] = S[i - 1] + p1;
	}
	AreaSum = abs(S[N]) / 2.0;

	// Search
	double Answer_Min = 1e9;
	double Answer_Max = -1e9;
	for (int l = 1; l <= N; l++) {
		for (int r = l + 1; r <= l + N - 1; r++) {
			pair<double, double> ret = solve(l, r);
			Answer_Min = min(Answer_Min, ret.first);
			Answer_Max = max(Answer_Max, ret.second);
		}
	}

	// Output
	printf("%.12lf\n", Answer_Min);
	printf("%.12lf\n", Answer_Max);
	return 0;
}
accuracy: 0.10126582278481013
time_ms: 40
memory_kb: 3524
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;
const long double eps = 0.000001;
const long double INF = 100000;
struct point{
  long double x, y;
  point(){
  }
  point(long double x, long double y): x(x), y(y){
  }
  point operator +(point P){
    return point(x + P.x, y + P.y);
  }
  point operator -(point P){
    return point(x - P.x, y - P.y);
  }
  point operator *(long double k){
    return point(x * k, y * k);
  }
  point operator /(long double k){
    return point(x / k, y / k);
  }
};
long double abs(point P){
  return sqrt(P.x * P.x + P.y * P.y);
}
long double dist(point P, point Q){
  return abs(Q - P);
}
point unit(point P){
  return P / abs(P);
}
long double dot(point P, point Q){
  return P.x * Q.x + P.y * Q.y;
}
long double cross(point P, point Q){
  return P.x * Q.y - P.y * Q.x;
}
long double angle_cosine(point P, point Q){
  return dot(P, Q) / (abs(P) * abs(Q));
}
long double angle_sine(point P, point Q){
  return abs(cross(P, Q)) / (abs(P) * abs(Q));
}
long double angle_one_minus_cosine(point P, point Q){
  return 1 - angle_cosine(P, Q);
}
long double area(point A, point B, point C){
  return abs(cross(B - A, C - A)) / 2;
}
struct line{
  point A, B;
  line(){
  }
  line(point A, point B): A(A), B(B){
  }
};
point vec(line L){
  return L.B - L.A;
}
double point_line_distance(point P, line L){
  return abs(cross(P - L.A, vec(L))) / abs(vec(L));
}
point line_intersection(line L1, line L2){
  return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2));
}
long double get_dist(long double a, long double b, long double one_minus_cost){
  return sqrt(max(pow(a - b, 2) + 2 * a * b * one_minus_cost, (long double) 0));
}
int main(){
  cout << fixed << setprecision(20);
  int n;
  cin >> n;
  vector<point> P(n + 1);
  for (int i = 0; i < n; i++){
    cin >> P[i].x >> P[i].y;
  }
  P[n] = P[0];
  long double S = 0;
  for (int i = 0; i < n; i++){
    S += cross(P[i], P[i + 1]) / 2;
  }
  long double mn = INF, mx = 0;
  for (int i = 0; i < n; i++){
    long double S1 = 0, S2 = S;
    for (int p = 1; p < n; p++){
      int j = (i + p) % n;
      S2 -= area(P[i], P[j], P[j + 1]);
      if (p >= 3){
        int j2 = (j - 1 + n) % n;
        S1 += area(P[j], P[j2], P[i + 1]);
      }
      if (S1 <= S / 2 + eps && S2 <= S / 2 + eps){
        long double C = cross(P[j + 1] - P[j], P[i] - P[i + 1]);
        if (C > eps){
          long double sint = angle_sine(P[j + 1] - P[j], P[i] - P[i + 1]);
          long double one_minus_cost = angle_one_minus_cosine(P[j + 1] - P[j], P[i] - P[i + 1]);
          point A = line_intersection(line(P[i], P[i + 1]), line(P[j], P[j + 1]));
          long double a1 = dist(A, P[i + 1]);
          long double a2 = dist(A, P[i]);
          long double b1 = dist(A, P[j]);
          long double b2 = dist(A, P[j + 1]);
          long double pr = a1 * b1 + (S - S1 * 2) / sint;
          long double xmn = max(a1, pr / max(b2, eps));
          long double xmx = min(a2, pr / max(b1, eps));
          if (xmn <= xmx + eps){
            long double d1 = get_dist(xmn, pr / xmn, one_minus_cost);
            mn = min(mn, d1);
            mx = max(mx, d1);
            long double d2 = get_dist(xmx, pr / xmx, one_minus_cost);
            mn = min(mn, d2);
            mx = max(mx, d2);
            long double x = sqrt(pr);
            if (xmn - eps <= x && x <= xmx + eps){
              long double d3 = get_dist(x, x, one_minus_cost);
              mn = min(mn, d3);
            }
          }
        } else if (C > -eps){
          long double a = dist(P[i], P[i + 1]);
          long double b = dist(P[j], P[j + 1]);
          long double h = point_line_distance(P[i + 1], line(P[j], P[j + 1]));
          long double s = (S - S1 * 2) / h;
          if (-eps <= s && s <= a + b + eps){
            long double xmn = max((long double) 0, s - b);
            long double xmx = min(a, s);
            point P1 = P[i + 1] + unit(P[i] - P[i + 1]) * xmn;
            point Q1 = P[j] + unit(P[j + 1] - P[j]) * (s - xmn);
            long double d1 = dist(P1, Q1);
            mn = min(mn, d1);
            mx = max(mx, d1);
            point P2 = P[i + 1] + unit(P[i] - P[i + 1]) * xmx;
            point Q2 = P[j] + unit(P[j + 1] - P[j]) * (s - xmx);
            long double d2 = dist(P2, Q2);
            mn = min(mn, d2);
            mx = max(mx, d2);
            if (dot(P[i] - P1, Q1 - P1) > -eps && dot(P[i] - P2, Q2 - P2) < eps){
              mn = min(mn, h);
            }
          }
        }
      }
    }
  }
  cout << mn << endl;
  cout << mx << endl;
}
accuracy: 1
time_ms: 370
memory_kb: 3612
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
const long double eps = 0.000001;
const long double INF = 100000;
struct point{
  long double x, y;
  point(){
  }
  point(long double x, long double y): x(x), y(y){
  }
  point operator +(point P){
    return point(x + P.x, y + P.y);
  }
  point operator -(point P){
    return point(x - P.x, y - P.y);
  }
  point operator *(long double k){
    return point(x * k, y * k);
  }
  point operator /(long double k){
    return point(x / k, y / k);
  }
};
long double abs(point P){
  return sqrt(P.x * P.x + P.y * P.y);
}
long double dist(point P, point Q){
  return abs(Q - P);
}
point unit(point P){
  return P / abs(P);
}
long double dot(point P, point Q){
  return P.x * Q.x + P.y * Q.y;
}
long double cross(point P, point Q){
  return P.x * Q.y - P.y * Q.x;
}
long double angle_cosine(point P, point Q){
  return dot(P, Q) / (abs(P) * abs(Q));
}
long double angle_sine(point P, point Q){
  return sqrt(max(1 - pow(angle_cosine(P, Q), 2), (long double) 0));
}
long double angle_one_minus_cosine(point P, point Q){
  return 1 - angle_cosine(P, Q);
}
long double area(point A, point B, point C){
  return abs(cross(B - A, C - A)) / 2;
}
struct line{
  point A, B;
  line(){
  }
  line(point A, point B): A(A), B(B){
  }
};
point vec(line L){
  return L.B - L.A;
}
double point_line_distance(point P, line L){
  return abs(cross(P - L.A, vec(L))) / abs(vec(L));
}
point line_intersection(line L1, line L2){
  return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2));
}
long double get_dist(long double a, long double b, long double one_minus_cost){
  return sqrt(max(pow(a - b, 2) + 2 * a * b * one_minus_cost, (long double) 0));
}
int main(){
  cout << fixed << setprecision(20);
  int n;
  cin >> n;
  vector<point> P(n + 1);
  for (int i = 0; i < n; i++){
    cin >> P[i].x >> P[i].y;
  }
  P[n] = P[0];
  long double S = 0;
  for (int i = 0; i < n; i++){
    S += cross(P[i], P[i + 1]) / 2;
  }
  long double mn = INF, mx = 0;
  for (int i = 0; i < n; i++){
    long double S1 = 0, S2 = S;
    for (int p = 1; p < n; p++){
      int j = (i + p) % n;
      S2 -= area(P[i], P[j], P[j + 1]);
      if (p >= 3){
        int j2 = (j - 1 + n) % n;
        S1 += area(P[j], P[j2], P[i + 1]);
      }
      if (S1 <= S / 2 + eps && S2 <= S / 2 + eps){
        long double C = cross(P[j + 1] - P[j], P[i] - P[i + 1]);
        if (C > eps){
          long double sint = angle_sine(P[j + 1] - P[j], P[i] - P[i + 1]);
          long double one_minus_cost = angle_one_minus_cosine(P[j + 1] - P[j], P[i] - P[i + 1]);
          point A = line_intersection(line(P[i], P[i + 1]), line(P[j], P[j + 1]));
          long double a1 = dist(A, P[i + 1]);
          long double a2 = dist(A, P[i]);
          long double b1 = dist(A, P[j]);
          long double b2 = dist(A, P[j + 1]);
          long double pr = a1 * b1 + (S - S1 * 2) / sint;
          long double xmn = max(a1, pr / max(b2, eps));
          long double xmx = min(a2, pr / max(b1, eps));
          if (xmn <= xmx + eps){
            long double d1 = get_dist(xmn, pr / xmn, one_minus_cost);
            mn = min(mn, d1);
            mx = max(mx, d1);
            long double d2 = get_dist(xmx, pr / xmx, one_minus_cost);
            mn = min(mn, d2);
            mx = max(mx, d2);
            long double x = sqrt(pr);
            if (xmn - eps <= x && x <= xmx + eps){
              long double d3 = get_dist(x, x, one_minus_cost);
              mn = min(mn, d3);
            }
          }
        } else if (C > -eps){
          long double a = dist(P[i], P[i + 1]);
          long double b = dist(P[j], P[j + 1]);
          long double h = point_line_distance(P[i + 1], line(P[j], P[j + 1]));
          long double s = (S - S1 * 2) / h;
          if (-eps <= s && s <= a + b + eps){
            long double xmn = max((long double) 0, s - b);
            long double xmx = min(a, s);
            point P1 = P[i + 1] + unit(P[i] - P[i + 1]) * xmn;
            point Q1 = P[j] + unit(P[j + 1] - P[j]) * (s - xmn);
            long double d1 = dist(P1, Q1);
            mn = min(mn, d1);
            mx = max(mx, d1);
            point P2 = P[i + 1] + unit(P[i] - P[i + 1]) * xmx;
            point Q2 = P[j] + unit(P[j + 1] - P[j]) * (s - xmx);
            long double d2 = dist(P2, Q2);
            mn = min(mn, d2);
            mx = max(mx, d2);
            if (dot(P[i] - P1, Q1 - P1) > -eps && dot(P[i] - P2, Q2 - P2) < eps){
              mn = min(mn, h);
            }
          }
        }
      }
    }
  }
  cout << mn << endl;
  cout << mx << endl;
}
accuracy: 0.4936708860759494
time_ms: 70
memory_kb: 3584
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
const long double eps = 0.000001;
const long double INF = 100000;
struct point{
  long double x, y;
  point(){
  }
  point(long double x, long double y): x(x), y(y){
  }
  point operator +(point P){
    return point(x + P.x, y + P.y);
  }
  point operator -(point P){
    return point(x - P.x, y - P.y);
  }
  point operator *(long double k){
    return point(x * k, y * k);
  }
  point operator /(long double k){
    return point(x / k, y / k);
  }
};
long double abs(point P){
  return sqrt(P.x * P.x + P.y * P.y);
}
long double dist(point P, point Q){
  return abs(Q - P);
}
point unit(point P){
  return P / abs(P);
}
long double dot(point P, point Q){
  return P.x * Q.x + P.y * Q.y;
}
long double cross(point P, point Q){
  return P.x * Q.y - P.y * Q.x;
}
long double angle(point P, point Q){
  return acos(dot(P, Q) / (abs(P) * abs(Q)));
}
long double area(point A, point B, point C){
  return abs(cross(B - A, C - A)) / 2;
}
struct line{
  point A, B;
  line(){
  }
  line(point A, point B): A(A), B(B){
  }
};
point vec(line L){
  return L.B - L.A;
}
double point_line_distance(point P, line L){
  return abs(cross(P - L.A, vec(L))) / abs(vec(L));
}
point line_intersection(line L1, line L2){
  return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2));
}
long double get_dist(long double a, long double b, long double t){
  return sqrt(pow(a - b, 2) + 4 * a * b * pow(sin(t / 2), 2));
}
int main(){
  cout << fixed << setprecision(20);
  int n;
  cin >> n;
  vector<point> P(n + 1);
  for (int i = 0; i < n; i++){
    cin >> P[i].x >> P[i].y;
  }
  P[n] = P[0];
  long double S = 0;
  for (int i = 0; i < n; i++){
    S += cross(P[i], P[i + 1]) / 2;
  }
  long double mn = INF, mx = 0;
  for (int i = 0; i < n; i++){
    long double S1 = 0, S2 = S;
    for (int p = 1; p < n; p++){
      int j = (i + p) % n;
      S2 -= area(P[i], P[j], P[j + 1]);
      if (p >= 3){
        int j2 = (j - 1 + n) % n;
        S1 += area(P[j], P[j2], P[i + 1]);
      }
      if (S1 <= S / 2 + eps && S2 <= S / 2 + eps){
        long double C = cross(P[j + 1] - P[j], P[i] - P[i + 1]);
        if (C > eps){
          long double t = angle(P[j + 1] - P[j], P[i] - P[i + 1]);
          point A = line_intersection(line(P[i], P[i + 1]), line(P[j], P[j + 1]));
          long double a1 = dist(A, P[i + 1]);
          long double a2 = dist(A, P[i]);
          long double b1 = dist(A, P[j]);
          long double b2 = dist(A, P[j + 1]);
          long double pr = a1 * b1 + (S - S1 * 2) / sin(t);
          long double xmn = max(a1, pr / max(b2, eps));
          long double xmx = min(a2, pr / max(b1, eps));
          if (xmn <= xmx + eps){
            long double d1 = get_dist(xmn, pr / xmn, t);
            mn = min(mn, d1);
            mx = max(mx, d1);
            long double d2 = get_dist(xmx, pr / xmx, t);
            mn = min(mn, d2);
            mx = max(mx, d2);
            long double x = sqrt(pr);
            if (xmn - eps <= x && x <= xmx + eps){
              long double d3 = get_dist(x, x, t);
              mn = min(mn, d3);
            }
          }
        } else if (C > -eps){
          long double a = dist(P[i], P[i + 1]);
          long double b = dist(P[j], P[j + 1]);
          long double h = point_line_distance(P[i + 1], line(P[j], P[j + 1]));
          long double s = (S - S1 * 2) / h;
          if (-eps <= s && s <= a + b + eps){
            long double xmn = max((long double) 0, s - b);
            long double xmx = min(a, s);
            point P1 = P[i + 1] + unit(P[i] - P[i + 1]) * xmn;
            point Q1 = P[j] + unit(P[j + 1] - P[j]) * (s - xmn);
            long double d1 = dist(P1, Q1);
            mn = min(mn, d1);
            mx = max(mx, d1);
            point P2 = P[i + 1] + unit(P[i] - P[i + 1]) * xmx;
            point Q2 = P[j] + unit(P[j + 1] - P[j]) * (s - xmx);
            long double d2 = dist(P2, Q2);
            mn = min(mn, d2);
            mx = max(mx, d2);
            if (dot(P[i] - P1, Q1 - P1) > -eps && dot(P[i] - P2, Q2 - P2) < eps){
              mn = min(mn, h);
            }
          }
        }
      }
    }
  }
  cout << mn << endl;
  cout << mx << endl;
}
accuracy: 0.4936708860759494
time_ms: 70
memory_kb: 3964
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
const long double eps = 0.000001;
const long double INF = 100000;
struct point{
  long double x, y;
  point(){
  }
  point(long double x, long double y): x(x), y(y){
  }
  point operator +(point P){
    return point(x + P.x, y + P.y);
  }
  point operator -(point P){
    return point(x - P.x, y - P.y);
  }
  point operator *(long double k){
    return point(x * k, y * k);
  }
  point operator /(long double k){
    return point(x / k, y / k);
  }
};
long double abs(point P){
  return sqrt(P.x * P.x + P.y * P.y);
}
long double dist(point P, point Q){
  return abs(Q - P);
}
point unit(point P){
  return P / abs(P);
}
long double dot(point P, point Q){
  return P.x * Q.x + P.y * Q.y;
}
long double cross(point P, point Q){
  return P.x * Q.y - P.y * Q.x;
}
long double angle(point P, point Q){
  return acos(dot(P, Q) / (abs(P) * abs(Q)));
}
long double area(point A, point B, point C){
  return abs(cross(B - A, C - A)) / 2;
}
struct line{
  point A, B;
  line(){
  }
  line(point A, point B): A(A), B(B){
  }
};
point vec(line L){
  return L.B - L.A;
}
double point_line_distance(point P, line L){
  return abs(cross(P - L.A, vec(L))) / abs(vec(L));
}
point line_intersection(line L1, line L2){
  return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2));
}
long double get_dist(long double a, long double b, long double t){
  return sqrt(pow(a - b, 2) + 4 * a * b * pow(sin(t / 2), 2));
}
int main(){
  cout << fixed << setprecision(20);
  int n;
  cin >> n;
  vector<point> P(n + 1);
  for (int i = 0; i < n; i++){
    cin >> P[i].x >> P[i].y;
  }
  P[n] = P[0];
  long double S = 0;
  for (int i = 0; i < n; i++){
    S += cross(P[i], P[i + 1]) / 2;
  }
  long double mn = INF, mx = 0;
  for (int i = 0; i < n; i++){
    long double S1 = 0, S2 = S;
    for (int p = 1; p < n; p++){
      int j = (i + p) % n;
      S2 -= area(P[i], P[j], P[j + 1]);
      if (p >= 3){
        int j2 = (j - 1 + n) % n;
        S1 += area(P[j], P[j2], P[i + 1]);
      }
      if (S1 <= S / 2 + eps && S2 <= S / 2 + eps){
        long double C = cross(P[j + 1] - P[j], P[i] - P[i + 1]);
        if (C > eps){
          long double t = angle(P[j + 1] - P[j], P[i] - P[i + 1]);
          point A = line_intersection(line(P[i], P[i + 1]), line(P[j], P[j + 1]));
          long double a1 = dist(A, P[i + 1]);
          long double a2 = dist(A, P[i]);
          long double b1 = dist(A, P[j]);
          long double b2 = dist(A, P[j + 1]);
          long double pr = a1 * b1 + (S - S1 * 2) / sin(t);
          long double xmn = max(a1, pr / (b2 + eps));
          long double xmx = min(a2, pr / (b1 + eps));
          if (xmn <= xmx + eps){
            long double d1 = get_dist(xmn, pr / xmn, t);
            mn = min(mn, d1);
            mx = max(mx, d1);
            long double d2 = get_dist(xmx, pr / xmx, t);
            mn = min(mn, d2);
            mx = max(mx, d2);
            long double x = sqrt(pr);
            if (xmn - eps <= x && x <= xmx + eps){
              long double d3 = get_dist(x, x, t);
              mn = min(mn, d3);
            }
          }
        } else if (C > -eps){
          long double a = dist(P[i], P[i + 1]);
          long double b = dist(P[j], P[j + 1]);
          long double h = point_line_distance(P[i + 1], line(P[j], P[j + 1]));
          long double s = (S - S1 * 2) / h;
          if (-eps <= s && s <= a + b + eps){
            long double xmn = max((long double) 0, s - b);
            long double xmx = min(a, s);
            point P1 = P[i + 1] + unit(P[i] - P[i + 1]) * xmn;
            point Q1 = P[j] + unit(P[j + 1] - P[j]) * (s - xmn);
            long double d1 = dist(P1, Q1);
            mn = min(mn, d1);
            mx = max(mx, d1);
            point P2 = P[i + 1] + unit(P[i] - P[i + 1]) * xmx;
            point Q2 = P[j] + unit(P[j + 1] - P[j]) * (s - xmx);
            long double d2 = dist(P2, Q2);
            mn = min(mn, d2);
            mx = max(mx, d2);
            if (dot(P[i] - P1, Q1 - P1) > -eps && dot(P[i] - P2, Q2 - P2) < eps){
              mn = min(mn, h);
            }
          }
        }
      }
    }
  }
  cout << mn << endl;
  cout << mx << endl;
}
accuracy: 0.4936708860759494
time_ms: 70
memory_kb: 3964
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
const long double eps = 0.00000001;
const long double INF = 100000;
struct point{
  long double x, y;
  point(){
  }
  point(long double x, long double y): x(x), y(y){
  }
  point operator +(point P){
    return point(x + P.x, y + P.y);
  }
  point operator -(point P){
    return point(x - P.x, y - P.y);
  }
  point operator *(long double k){
    return point(x * k, y * k);
  }
  point operator /(long double k){
    return point(x / k, y / k);
  }
};
long double abs(point P){
  return sqrt(P.x * P.x + P.y * P.y);
}
long double dist(point P, point Q){
  return abs(Q - P);
}
point unit(point P){
  return P / abs(P);
}
long double dot(point P, point Q){
  return P.x * Q.x + P.y * Q.y;
}
long double cross(point P, point Q){
  return P.x * Q.y - P.y * Q.x;
}
long double angle(point P, point Q){
  return acos(dot(P, Q) / (abs(P) * abs(Q)));
}
long double area(point A, point B, point C){
  return abs(cross(B - A, C - A)) / 2;
}
struct line{
  point A, B;
  line(){
  }
  line(point A, point B): A(A), B(B){
  }
};
point vec(line L){
  return L.B - L.A;
}
point projection(point P, line L){
  return L.A + unit(vec(L)) * dot(P - L.A, vec(L)) / abs(vec(L));
}
point line_intersection(line L1, line L2){
  return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2));
}
long double get_dist(long double a, long double b, long double t){
  return sqrt(pow(a - b, 2) + 4 * a * b * pow(sin(t / 2), 2));
}
int main(){
  cout << fixed << setprecision(20);
  int n;
  cin >> n;
  vector<point> P(n + 1);
  for (int i = 0; i < n; i++){
    cin >> P[i].x >> P[i].y;
  }
  P[n] = P[0];
  long double S = 0;
  for (int i = 0; i < n; i++){
    S += cross(P[i], P[i + 1]) / 2;
  }
  long double mn = INF, mx = 0;
  for (int i = 0; i < n; i++){
    long double S1 = 0, S2 = S;
    for (int p = 1; p < n; p++){
      int j = (i + p) % n;
      S2 -= area(P[i], P[j], P[j + 1]);
      if (p >= 3){
        int j2 = (j - 1 + n) % n;
        S1 += area(P[j], P[j2], P[i + 1]);
      }
      if (S1 <= S / 2 + eps && S2 <= S / 2 + eps){
        long double C = cross(P[j + 1] - P[j], P[i] - P[i + 1]);
        if (C > eps){
          long double t = angle(P[j + 1] - P[j], P[i] - P[i + 1]);
          point A = line_intersection(line(P[i], P[i + 1]), line(P[j], P[j + 1]));
          long double a1 = dist(A, P[i + 1]);
          long double a2 = dist(A, P[i]);
          long double b1 = dist(A, P[j]);
          long double b2 = dist(A, P[j + 1]);
          long double pr = a1 * b1 + (S - S1 * 2) / sin(t);
          long double xmn = max(a1, pr / (b2 + eps));
          long double xmx = min(a2, pr / (b1 + eps));
          if (xmn <= xmx + eps){
            long double d1 = get_dist(xmn, pr / xmn, t);
            mn = min(mn, d1);
            mx = max(mx, d1);
            long double d2 = get_dist(xmx, pr / xmx, t);
            mn = min(mn, d2);
            mx = max(mx, d2);
            long double x = sqrt(pr);
            if (xmn - eps <= x && x <= xmx + eps){
              long double d3 = get_dist(x, x, t);
              mn = min(mn, d3);
            }
          }
        } else if (C > -eps){
          long double a = dist(P[i], P[i + 1]);
          long double b = dist(P[j], P[j + 1]);
          point H = projection(P[i + 1], line(P[j], P[j + 1]));
          long double h = dist(P[i + 1], H);
          long double s = (S - S1 * 2) / h;
          if (-eps <= s && s <= a + b + eps){
            long double xmn = max((long double) 0, s - b);
            long double xmx = min(a, s);
            point P1 = P[i + 1] + unit(P[i] - P[i + 1]) * xmn;
            point Q1 = P[j] + unit(P[j + 1] - P[j]) * (s - xmn);
            long double d1 = dist(P1, Q1);
            mn = min(mn, d1);
            mx = max(mx, d1);
            point P2 = P[i + 1] + unit(P[i] - P[i + 1]) * xmx;
            point Q2 = P[j] + unit(P[j + 1] - P[j]) * (s - xmx);
            long double d2 = dist(P2, Q2);
            mn = min(mn, d2);
            mx = max(mx, d2);
            if (dot(P[i] - P1, Q1 - P1) > -eps && dot(P[i] - P2, Q2 - P2) < eps){
              mn = min(mn, h);
            }
          }
        }
      }
    }
  }
  cout << mn << endl;
  cout << mx << endl;
}
accuracy: 0.4936708860759494
time_ms: 70
memory_kb: 3952
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
const long double eps = 0.0000001;
const long double INF = 100000;
struct point{
  long double x, y;
  point(){
  }
  point(long double x, long double y): x(x), y(y){
  }
  point operator +(point P){
    return point(x + P.x, y + P.y);
  }
  point operator -(point P){
    return point(x - P.x, y - P.y);
  }
  point operator *(long double k){
    return point(x * k, y * k);
  }
  point operator /(long double k){
    return point(x / k, y / k);
  }
};
long double abs(point P){
  return sqrt(P.x * P.x + P.y * P.y);
}
long double dist(point P, point Q){
  return abs(Q - P);
}
point unit(point P){
  return P / abs(P);
}
long double dot(point P, point Q){
  return P.x * Q.x + P.y * Q.y;
}
long double cross(point P, point Q){
  return P.x * Q.y - P.y * Q.x;
}
long double angle(point P, point Q){
  return acos(dot(P, Q) / (abs(P) * abs(Q)));
}
long double area(point A, point B, point C){
  return abs(cross(B - A, C - A)) / 2;
}
struct line{
  point A, B;
  line(){
  }
  line(point A, point B): A(A), B(B){
  }
};
point vec(line L){
  return L.B - L.A;
}
point projection(point P, line L){
  return L.A + unit(vec(L)) * dot(P - L.A, vec(L)) / abs(vec(L));
}
point line_intersection(line L1, line L2){
  return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2));
}
long double get_dist(long double a, long double b, long double t){
  return sqrt(pow(a - b, 2) + 4 * a * b * pow(sin(t / 2), 2));
}
int main(){
  cout << fixed << setprecision(20);
  int n;
  cin >> n;
  vector<point> P(n + 1);
  for (int i = 0; i < n; i++){
    cin >> P[i].x >> P[i].y;
  }
  P[n] = P[0];
  long double S = 0;
  for (int i = 0; i < n; i++){
    S += cross(P[i], P[i + 1]) / 2;
  }
  long double mn = INF, mx = 0;
  for (int i = 0; i < n; i++){
    long double S1 = 0, S2 = S;
    for (int p = 1; p < n; p++){
      int j = (i + p) % n;
      S2 -= area(P[i], P[j], P[j + 1]);
      if (p >= 3){
        int j2 = (j - 1 + n) % n;
        S1 += area(P[j], P[j2], P[i + 1]);
      }
      if (S1 <= S / 2 + eps && S2 <= S / 2 + eps){
        long double C = cross(P[j + 1] - P[j], P[i] - P[i + 1]);
        if (C > eps){
          long double t = angle(P[j + 1] - P[j], P[i] - P[i + 1]);
          point A = line_intersection(line(P[i], P[i + 1]), line(P[j], P[j + 1]));
          long double a1 = dist(A, P[i + 1]);
          long double a2 = dist(A, P[i]);
          long double b1 = dist(A, P[j]);
          long double b2 = dist(A, P[j + 1]);
          long double pr = a1 * b1 + (S - S1 * 2) / sin(t);
          long double xmn = max(a1, pr / (b2 + eps));
          long double xmx = min(a2, pr / (b1 + eps));
          if (xmn <= xmx + eps){
            long double d1 = get_dist(xmn, pr / xmn, t);
            mn = min(mn, d1);
            mx = max(mx, d1);
            long double d2 = get_dist(xmx, pr / xmx, t);
            mn = min(mn, d2);
            mx = max(mx, d2);
            long double x = sqrt(pr);
            if (xmn - eps <= x && x <= xmx + eps){
              long double d3 = get_dist(x, x, t);
              mn = min(mn, d3);
            }
          }
        } else if (C > -eps){
          long double a = dist(P[i], P[i + 1]);
          long double b = dist(P[j], P[j + 1]);
          point H = projection(P[i + 1], line(P[j], P[j + 1]));
          long double h = dist(P[i + 1], H);
          long double s = (S - S1 * 2) / h;
          if (-eps <= s && s <= a + b + eps){
            long double xmn = max((long double) 0, s - b);
            long double xmx = min(a, s);
            point P1 = P[i + 1] + unit(P[i] - P[i + 1]) * xmn;
            point Q1 = P[j] + unit(P[j + 1] - P[j]) * (s - xmn);
            long double d1 = dist(P1, Q1);
            mn = min(mn, d1);
            mx = max(mx, d1);
            point P2 = P[i + 1] + unit(P[i] - P[i + 1]) * xmx;
            point Q2 = P[j] + unit(P[j + 1] - P[j]) * (s - xmx);
            long double d2 = dist(P2, Q2);
            mn = min(mn, d2);
            mx = max(mx, d2);
            if (dot(P[i] - P1, Q1 - P1) > -eps && dot(P[i] - P2, Q2 - P2) < eps){
              mn = min(mn, h);
            }
          }
        }
      }
    }
  }
  cout << mn << endl;
  cout << mx << endl;
}
accuracy: 0.4936708860759494
time_ms: 70
memory_kb: 3956
final_rank: 12

code_snippet: #define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
using namespace std;
const long double eps = 0.000001;
const long double INF = 100000;
struct point{
  long double x, y;
  point(){
  }
  point(long double x, long double y): x(x), y(y){
  }
  point operator +(point P){
    return point(x + P.x, y + P.y);
  }
  point operator -(point P){
    return point(x - P.x, y - P.y);
  }
  point operator *(long double k){
    return point(x * k, y * k);
  }
  point operator /(long double k){
    return point(x / k, y / k);
  }
};
long double abs(point P){
  return sqrt(P.x * P.x + P.y * P.y);
}
long double dist(point P, point Q){
  return abs(Q - P);
}
point unit(point P){
  return P / abs(P);
}
long double dot(point P, point Q){
  return P.x * Q.x + P.y * Q.y;
}
long double cross(point P, point Q){
  return P.x * Q.y - P.y * Q.x;
}
long double angle(point P, point Q){
  return acos(dot(P, Q) / (abs(P) * abs(Q)));
}
long double area(point A, point B, point C){
  return abs(cross(B - A, C - A)) / 2;
}
struct line{
  point A, B;
  line(){
  }
  line(point A, point B): A(A), B(B){
  }
};
point vec(line L){
  return L.B - L.A;
}
point projection(point P, line L){
  return L.A + unit(vec(L)) * dot(P - L.A, vec(L)) / abs(vec(L));
}
point line_intersection(line L1, line L2){
  return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2));
}
long double get_dist(long double a, long double b, long double t){
  return sqrt(pow(a - b, 2) + 4 * a * b * pow(sin(t / 2), 2));
}
int main(){
  cout << fixed << setprecision(20);
  int n;
  cin >> n;
  vector<point> P(n + 1);
  for (int i = 0; i < n; i++){
    cin >> P[i].x >> P[i].y;
  }
  P[n] = P[0];
  long double S = 0;
  for (int i = 0; i < n; i++){
    S += cross(P[i], P[i + 1]) / 2;
  }
  long double mn = INF, mx = 0;
  for (int i = 0; i < n; i++){
    long double S1 = 0, S2 = S;
    for (int p = 1; p < n; p++){
      int j = (i + p) % n;
      S2 -= area(P[i], P[j], P[j + 1]);
      if (p >= 3){
        int j2 = (j - 1 + n) % n;
        S1 += area(P[j], P[j2], P[i + 1]);
      }
      if (S1 <= S / 2 + eps && S2 <= S / 2 + eps){
        long double C = cross(P[j + 1] - P[j], P[i] - P[i + 1]);
        if (C > eps){
          long double t = angle(P[j + 1] - P[j], P[i] - P[i + 1]);
          point A = line_intersection(line(P[i], P[i + 1]), line(P[j], P[j + 1]));
          long double a1 = dist(A, P[i + 1]);
          long double a2 = dist(A, P[i]);
          long double b1 = dist(A, P[j]);
          long double b2 = dist(A, P[j + 1]);
          long double pr = a1 * b1 + (S - S1 * 2) / sin(t);
          long double xmn = max(a1, pr / (b2 + eps));
          long double xmx = min(a2, pr / (b1 + eps));
          if (xmn <= xmx + eps){
            long double d1 = get_dist(xmn, pr / xmn, t);
            mn = min(mn, d1);
            mx = max(mx, d1);
            long double d2 = get_dist(xmx, pr / xmx, t);
            mn = min(mn, d2);
            mx = max(mx, d2);
            long double x = sqrt(pr);
            if (xmn - eps <= x && x <= xmx + eps){
              long double d3 = get_dist(x, x, t);
              mn = min(mn, d3);
            }
          }
        } else if (C > -eps){
          long double a = dist(P[i], P[i + 1]);
          long double b = dist(P[j], P[j + 1]);
          point H = projection(P[i + 1], line(P[j], P[j + 1]));
          long double h = dist(P[i + 1], H);
          long double s = (S - S1 * 2) / h;
          if (-eps <= s && s <= a + b + eps){
            long double xmn = max((long double) 0, s - b);
            long double xmx = min(a, s);
            point P1 = P[i + 1] + unit(P[i] - P[i + 1]) * xmn;
            point Q1 = P[j] + unit(P[j + 1] - P[j]) * (s - xmn);
            long double d1 = dist(P1, Q1);
            mn = min(mn, d1);
            mx = max(mx, d1);
            point P2 = P[i + 1] + unit(P[i] - P[i + 1]) * xmx;
            point Q2 = P[j] + unit(P[j + 1] - P[j]) * (s - xmx);
            long double d2 = dist(P2, Q2);
            mn = min(mn, d2);
            mx = max(mx, d2);
            if (dot(P[i] - P1, Q1 - P1) > -eps && dot(P[i] - P2, Q2 - P2) < eps){
              mn = min(mn, h);
            }
          }
        }
      }
    }
  }
  cout << mn << endl;
  cout << mx << endl;
}
accuracy: 0.4936708860759494
time_ms: 70
memory_kb: 3964
final_rank: 13

code_snippet: #define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
using namespace std;
const long double eps = 0.000001;
const long double INF = 100000;
struct point{
  long double x, y;
  point(){
  }
  point(long double x, long double y): x(x), y(y){
  }
  point operator +(point P){
    return point(x + P.x, y + P.y);
  }
  point operator -(point P){
    return point(x - P.x, y - P.y);
  }
  point operator *(long double k){
    return point(x * k, y * k);
  }
  point operator /(long double k){
    return point(x / k, y / k);
  }
};
long double abs(point P){
  return sqrt(P.x * P.x + P.y * P.y);
}
long double dist(point P, point Q){
  return abs(Q - P);
}
point unit(point P){
  return P / abs(P);
}
long double dot(point P, point Q){
  return P.x * Q.x + P.y * Q.y;
}
long double cross(point P, point Q){
  return P.x * Q.y - P.y * Q.x;
}
long double angle(point P, point Q){
  return acos(dot(P, Q) / (abs(P) * abs(Q)));
}
long double area(point A, point B, point C){
  return abs(cross(B - A, C - A)) / 2;
}
struct line{
  point A, B;
  line(){
  }
  line(point A, point B): A(A), B(B){
  }
};
point vec(line L){
  return L.B - L.A;
}
point projection(point P, line L){
  return L.A + unit(vec(L)) * dot(P - L.A, vec(L)) / abs(vec(L));
}
point line_intersection(line L1, line L2){
  return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2));
}
long double get_dist(long double a, long double b, long double t){
  return sqrt(pow(a - b, 2) + 2 * a * b * (1 - cos(t)));
}
int main(){
  cout << fixed << setprecision(20);
  int n;
  cin >> n;
  vector<point> P(n + 1);
  for (int i = 0; i < n; i++){
    cin >> P[i].x >> P[i].y;
  }
  P[n] = P[0];
  long double S = 0;
  for (int i = 0; i < n; i++){
    S += cross(P[i], P[i + 1]) / 2;
  }
  long double mn = INF, mx = 0;
  for (int i = 0; i < n; i++){
    long double S1 = 0, S2 = S;
    for (int p = 1; p < n; p++){
      int j = (i + p) % n;
      S2 -= area(P[i], P[j], P[j + 1]);
      if (p >= 3){
        int j2 = (j - 1 + n) % n;
        S1 += area(P[j], P[j2], P[i + 1]);
      }
      if (S1 <= S / 2 + eps && S2 <= S / 2 + eps){
        long double C = cross(P[j + 1] - P[j], P[i] - P[i + 1]);
        if (C > eps){
          long double t = angle(P[j + 1] - P[j], P[i] - P[i + 1]);
          point A = line_intersection(line(P[i], P[i + 1]), line(P[j], P[j + 1]));
          long double a1 = dist(A, P[i + 1]);
          long double a2 = dist(A, P[i]);
          long double b1 = dist(A, P[j]);
          long double b2 = dist(A, P[j + 1]);
          long double pr = a1 * b1 + (S - S1 * 2) / sin(t);
          long double xmn = max(a1, pr / (b2 + eps));
          long double xmx = min(a2, pr / (b1 + eps));
          if (xmn <= xmx + eps){
            long double d1 = get_dist(xmn, pr / xmn, t);
            mn = min(mn, d1);
            mx = max(mx, d1);
            long double d2 = get_dist(xmx, pr / xmx, t);
            mn = min(mn, d2);
            mx = max(mx, d2);
            long double x = sqrt(pr);
            if (xmn - eps <= x && x <= xmx + eps){
              long double d3 = get_dist(x, x, t);
              mn = min(mn, d3);
            }
          }
        } else if (C > -eps){
          long double a = dist(P[i], P[i + 1]);
          long double b = dist(P[j], P[j + 1]);
          point H = projection(P[i + 1], line(P[j], P[j + 1]));
          long double h = dist(P[i + 1], H);
          long double s = (S - S1 * 2) / h;
          if (-eps <= s && s <= a + b + eps){
            long double xmn = max((long double) 0, s - b);
            long double xmx = min(a, s);
            point P1 = P[i + 1] + unit(P[i] - P[i + 1]) * xmn;
            point Q1 = P[j] + unit(P[j + 1] - P[j]) * (s - xmn);
            long double d1 = dist(P1, Q1);
            mn = min(mn, d1);
            mx = max(mx, d1);
            point P2 = P[i + 1] + unit(P[i] - P[i + 1]) * xmx;
            point Q2 = P[j] + unit(P[j + 1] - P[j]) * (s - xmx);
            long double d2 = dist(P2, Q2);
            mn = min(mn, d2);
            mx = max(mx, d2);
            if (dot(P[i] - P1, Q1 - P1) > -eps && dot(P[i] - P2, Q2 - P2) < eps){
              mn = min(mn, h);
            }
          }
        }
      }
    }
  }
  cout << mn << endl;
  cout << mx << endl;
}
accuracy: 0.4936708860759494
time_ms: 70
memory_kb: 3964
final_rank: 13

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long double ld;
const ld eps = 1e-9;
struct pt {
    ld x, y;
    pt() {x = 0; y = 0;}
    pt(ld xx, ld yy) {
        x = xx; y = yy;
    }
    ld mag() {
        return sqrt(x*x + y*y);
    }
    pt operator+(pt o) {
        return pt(x + o.x, y + o.y);
    }
    pt operator-(pt o) {
        return pt(x - o.x, y - o.y);
    }
    pt operator*(ld val) {
        return pt(x*val, y*val);
    }
    pt operator/(ld val) {
        return pt(x/val, y/val);
    }
    friend ostream& operator<<(ostream &os, pt p) {
        return os << "(" << p.x << ", " << p.y << ")";
    }
};
ld cross(pt a, pt b) {
    return a.x*b.y - a.y*b.x;
}
ld dot(pt a, pt b) {
    return a.x*b.x + a.y*b.y;
}
 
void solve() {
    int n; cin >> n;
    vector<pt> poly(n);
    ld x, y, tpolyar = 0;
    for (int i = 0; i < n; ++i) {
        cin >> x >> y;
        poly[i] = pt(x, y);

        if (i > 1) 
            tpolyar += cross(poly[i - 1] - poly[0], poly[i] - poly[0]);
    }

    ld longest = 0, shortest = 4e+7;
    for (int i = 0; i < n; ++i) {
        // find the area bisector that passes through poly[i]
        int j = (i + 1) % n;
        ld runar = cross(poly[j] - poly[i], poly[(j + 1) % n] - poly[i]);
        while (2*runar - tpolyar <= eps) {
            j = (j + 1) % n;
            runar += cross(poly[j] - poly[i], poly[(j + 1) % n] - poly[i]);
        }
 
        ld lar = runar - 0.5*tpolyar;
        ld rar = cross(poly[j] - poly[i], poly[(j + 1) % n] - poly[i]) - lar;
        pt arbsct = (poly[j]*lar + poly[(j + 1) % n]*rar)/(lar + rar);
        ld l = (arbsct - poly[i]).mag();
 
        // calculate local longest bisector
        longest = max(longest, l);
 
        // begin calculation of shortest bisector
        shortest = min(shortest, l);
 
        ld theta = asin(cross(poly[(j + 1) % n] - poly[j], poly[i] - poly[(i + 1) % n]) / ((poly[(j + 1) %n] - poly[j]).mag() * (poly[i] - poly[(i + 1) % n]).mag()));
        ld alpha = acos(dot(arbsct - poly[i], poly[(i + 1) % n] - poly[i]) / (l * (poly[(i + 1) % n] - poly[i]).mag()));
        if (M_PI_2 - alpha - theta/2 > eps && alpha + theta > eps) {
            ld r1 = l * sin(alpha) * sqrt(sin(alpha + theta)) / (cos(theta/2) * (sqrt(sin(alpha + theta)) + sqrt(sin(alpha))));
            ld r2 = r1 * sqrt(sin(alpha + theta) / sin(alpha));
            ld b1 = r1 * cos(alpha + theta/2) / sin(alpha);
            ld b2 = r2 * cos(alpha + theta/2) / sin(alpha + theta);
 
            if (b1 - (poly[(i + 1) % n] - poly[i]).mag() <= eps && b2 - (poly[(j + 1) % n] - arbsct).mag() <= eps)
                shortest = min(shortest, r1 + r2);
        }
 
        theta = asin(cross(poly[(j + 1) % n] - poly[j], poly[(n + i - 1) % n] - poly[i]) / ((poly[(j + 1) % n] - poly[j]).mag() * (poly[(n + i - 1) % n] - poly[i]).mag()));
        alpha = acos(dot(arbsct - poly[i], poly[(n + i - 1) % n] - poly[i]) / (l * (poly[(n + i - 1) % n] - poly[i]).mag()));
        if (M_PI_2 - alpha + theta/2 > eps && alpha - theta > eps) {
            ld r1 = l * sin(alpha) * sqrt(sin(alpha - theta)) / (cos(theta/2) * (sqrt(sin(alpha - theta)) + sqrt(sin(alpha))));
            ld r2 = r1 * sqrt(sin(alpha - theta) / sin(alpha));
            ld b1 = r1 * cos(alpha - theta/2) / sin(alpha);
            ld b2 = r2 * cos(alpha - theta/2) / sin(alpha - theta);
 
            if (b1 - (poly[(n + i - 1) % n] - poly[i]).mag() <= eps && b2 - (poly[j] - arbsct).mag() <= eps)
                shortest = min(shortest, r1 + r2);
        }
    }
 
    cout << shortest << "\n" << longest << "\n";
}
 
int main() {
    cin.tie(0)->sync_with_stdio(0);
    cin.exceptions(cin.failbit);
    cout << setprecision(6) << fixed;
    solve();
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 3996
final_rank: 3

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long double ld;
const ld eps = 1e-9;
struct pt {
    ld x, y;
    pt() {x = 0; y = 0;}
    pt(ld xx, ld yy) {
        x = xx; y = yy;
    }
    ld mag() {
        return sqrt(x*x + y*y);
    }
    pt operator+(pt o) {
        return pt(x + o.x, y + o.y);
    }
    pt operator-(pt o) {
        return pt(x - o.x, y - o.y);
    }
    pt operator*(ld val) {
        return pt(x*val, y*val);
    }
    pt operator/(ld val) {
        return pt(x/val, y/val);
    }
    friend ostream& operator<<(ostream &os, pt p) {
        return os << "(" << p.x << ", " << p.y << ")";
    }
};
ld cross(pt a, pt b) {
    return a.x*b.y - a.y*b.x;
}
ld dot(pt a, pt b) {
    return a.x*b.x + a.y*b.y;
}
 
int n;
ld tpolyar = 0;
vector<pt> poly;
void initpoly() {
    cin >> n;
    poly.resize(n);
    ld x, y;
    for (int i = 0; i < n; ++i) {
        cin >> x >> y;
        poly[i] = pt(x, y);
    }
 
    for (int i = 2; i < n; ++i)
        tpolyar += cross(poly[i - 1] - poly[0], poly[i] - poly[0]);
}
 
void solve() {
    ld longest = 0, shortest = 4e+7;
    for (int i = 0; i < n; ++i) {
        // find the area bisector that passes through poly[i]
        int j = (i + 1) % n;
        ld runar = cross(poly[j] - poly[i], poly[(j + 1) % n] - poly[i]);
        while (2*runar - tpolyar <= eps) {
            j = (j + 1) % n;
            runar += cross(poly[j] - poly[i], poly[(j + 1) % n] - poly[i]);
        }
 
        ld lar = runar - 0.5*tpolyar;
        ld rar = cross(poly[j] - poly[i], poly[(j + 1) % n] - poly[i]) - lar;
        pt arbsct = (poly[j]*lar + poly[(j + 1) % n]*rar)/(lar + rar);
        ld l = (arbsct - poly[i]).mag();
 
        // calculate local longest bisector
        longest = max(longest, l);
 
        // begin calculation of shortest bisector
        shortest = min(shortest, l);
 
        ld theta = asin(cross(poly[(j + 1) % n] - poly[j], poly[i] - poly[(i + 1) % n]) / ((poly[(j + 1) %n] - poly[j]).mag() * (poly[i] - poly[(i + 1) % n]).mag()));
        ld alpha = acos(dot(arbsct - poly[i], poly[(i + 1) % n] - poly[i]) / (l * (poly[(i + 1) % n] - poly[i]).mag()));
        if (M_PI_2 - alpha - theta/2 > eps && alpha + theta > eps) {
            ld r1 = l * sin(alpha) * sqrt(sin(alpha + theta)) / (cos(theta/2) * (sqrt(sin(alpha + theta)) + sqrt(sin(alpha))));
            ld r2 = r1 * sqrt(sin(alpha + theta) / sin(alpha));
            ld b1 = r1 * cos(alpha + theta/2) / sin(alpha);
            ld b2 = r2 * cos(alpha + theta/2) / sin(alpha + theta);
 
            if (b1 - (poly[(i + 1) % n] - poly[i]).mag() <= eps && b2 - (poly[(j + 1) % n] - arbsct).mag() <= eps)
                shortest = min(shortest, r1 + r2);
        }
 
        theta = asin(cross(poly[(j + 1) % n] - poly[j], poly[(n + i - 1) % n] - poly[i]) / ((poly[(j + 1) % n] - poly[j]).mag() * (poly[(n + i - 1) % n] - poly[i]).mag()));
        alpha = acos(dot(arbsct - poly[i], poly[(n + i - 1) % n] - poly[i]) / (l * (poly[(n + i - 1) % n] - poly[i]).mag()));
        if (M_PI_2 - alpha + theta/2 > eps && alpha - theta > eps) {
            ld r1 = l * sin(alpha) * sqrt(sin(alpha - theta)) / (cos(theta/2) * (sqrt(sin(alpha - theta)) + sqrt(sin(alpha))));
            ld r2 = r1 * sqrt(sin(alpha - theta) / sin(alpha));
            ld b1 = r1 * cos(alpha - theta/2) / sin(alpha);
            ld b2 = r2 * cos(alpha - theta/2) / sin(alpha - theta);
 
            if (b1 - (poly[(n + i - 1) % n] - poly[i]).mag() <= eps && b2 - (poly[j] - arbsct).mag() <= eps)
                shortest = min(shortest, r1 + r2);
        }
    }
 
    cout << shortest << "\n" << longest << "\n";
}
 
int main() {
    cin.tie(0)->sync_with_stdio(0);
    cin.exceptions(cin.failbit);
    initpoly();
    cout << setprecision(6) << fixed;
    solve();
    return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 3968
final_rank: 2

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
//#define EPS 0.000000001
using namespace std;


#define EPS 0.000000001
#define SIZE 5005

enum Type{
	Horizon,
	Vertical,
	Normal,
};

struct Point{
	Point(long double arg_x,long double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (long double a){ return Point(a*x,a*y); }
	Point operator / (long double a){ return Point(x/a,y/a); }

	long double abs(){ return sqrt(norm()); }
	long double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3Lf,%.3Lf)\n",x,y);
	}

	long double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	void outPut(){

		printf("(%.3Lf,%.3Lf)-(%.3Lf,%.3Lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}
	Point p[2];
};

int N;
Polygon POLY;
Line line[SIZE];
//long double NUM = 10000000;
long double NUM = BIG_NUM;
//long double NUM = 1;


long double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

long double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

long double abs(Vector a){
	return sqrt(norm(a));
}

long double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

long double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

/*
 * p0を基準点として、p1から見てp2が
 * 反時計回り側にあれば
 * COUNTER_CLOCKWISE
 * */
int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}
int func(long double x1,long double y1,long double x2, long double y2, long double xp, long double yp){
	long double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}

Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

long double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
long double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
long double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

//線分と線分の距離
long double getDistance(Line A,Line B){
	if(is_Cross(A,B))return 0.0;
	return min(min(getDistanceSP(A,B.p[0]),getDistanceSP(A,B.p[1])),
			min(getDistanceSP(B,A.p[0]),getDistanceSP(B,A.p[1])));
}


//交点を求める関数
Point calc_Cross_Point(long double x1,long double x2,long double x3,long double x4,long double y1,long double y2,long double y3,long double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){


	long double MULT = 100; //EPSのままだと誤差が出る

	if(getDistanceSP(B,A.p[0]) < EPS*MULT){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS*MULT){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS*MULT){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS*MULT){

		return B.p[1];
	}

	double E = 10000; //★★★★nan対策★★★★

	return calc_Cross_Point(A.p[0]*E,A.p[1]*E,B.p[0]*E,B.p[1]*E)/E;
}

long double calc_S(Polygon g){

	int N = g.size();
	long double ret = 0;

	for(int i = 0; i < g.size(); i++){
		ret += cross(g[i],g[(i+1)%N]);
	}
	return ret/2.0;
}

/*点moveをbaseを中心にradラジアン回転させる
rad > 0なら反時計回り、rad < 0なら時計周り
*/
Point rotate(Point base,Point move,long double rad){

	Point ret;
	move = move-base;

	ret.x = move.x*cos(rad)-move.y*sin(rad);
	ret.y = move.x*sin(rad)+move.y*cos(rad);

	ret = ret+base;

	return ret;
}

//2つのvectorがなすラジアンを求める関数
long double calc_rad(Vector vec1,Vector vec2){

	long double tmp = dot(vec1,vec2)/(abs(vec1)*abs(vec2));

	if(fabs(tmp+1.0) < EPS){

		return M_PI;
	}

	if(fabs(tmp-1.0) < EPS){

		return  0.0;
	}

	return acos(dot(vec1,vec2)/(abs(vec1)*abs(vec2)));
}

//3点がなすラジアンを求める関数(ccw(base,a,b) == CCW)
long double calc_rad(Point base,Point a,Point b){

	Vector vec1 = b-base;
	Vector vec2 = a-base;

	return calc_rad(vec1,vec2);
}

long double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

//線分をp[1]方向へ伸ばす
Line make_longer(Line arg_line){

	Line ret;
	ret.p[0] = arg_line.p[0];

	//p[1]方向へ直線を伸ばす
	if(fabs(arg_line.p[0].x-arg_line.p[1].x) < EPS){ //垂直

		if(arg_line.p[0].y > arg_line.p[1].y){

			ret.p[1] = Point(arg_line.p[0].x,arg_line.p[0].y-NUM);

		}else{

			ret.p[1] = Point(arg_line.p[0].x,arg_line.p[0].y+NUM);
		}

	}else if(fabs(arg_line.p[0].y-arg_line.p[1].y) < EPS){

		if(arg_line.p[0].x > arg_line.p[1].x){

			ret.p[1] = Point(arg_line.p[0].x-NUM,arg_line.p[0].y);

		}else{

			ret.p[1] = Point(arg_line.p[0].x+NUM,arg_line.p[0].y);
		}

	}else{

		long double work_slope = calc_slope(arg_line);

		if(arg_line.p[0].x > arg_line.p[1].x){

			ret.p[1] = Point(arg_line.p[0].x-NUM,arg_line.p[0].y-NUM*work_slope);

		}else{

			ret.p[1] = Point(arg_line.p[0].x+NUM,arg_line.p[0].y+NUM*work_slope);
		}
	}

	return ret;
}

int main(){

	scanf("%d",&N);

	long double x,y;

	for(int i = 0; i < N; i++){

		scanf("%Lf %Lf",&x,&y);
		POLY.push_back(Point(x,y));
	}

	long double S = calc_S(POLY);
	long double half_S = S/2;

	for(int i = 0; i < N; i++){

		line[i].p[0] = POLY[i];
		line[i].p[1] = POLY[(i+1)%N];
	}

	long double minimum = BIG_NUM,maximum = -BIG_NUM;


	for(int base = 0; base < N; base++){

		int toimen,toimen_next;
		int base_next = (base+1)%N;

		long double tmp_S = 0;

		int pre = (base+1)%N;
		int next = (base+2)%N;

		long double last_add;

		while(true){

			last_add = cross(POLY[pre]-POLY[base],POLY[next]-POLY[base])/2;
			tmp_S += last_add;

			if(fabs(tmp_S-half_S) < EPS){ //ちょうど半分

				long double tmp_dist = calc_dist(POLY[base],POLY[next]);

				maximum = max(maximum,tmp_dist);
				minimum = min(minimum,tmp_dist);

				toimen = next;
				toimen_next = (next+1)%N;

				break;

			}else if(tmp_S > half_S+EPS){

				toimen = pre;
				toimen_next = next;

				break;
			}

			pre = next;
			next = (next+1)%N;
		}


		if(tmp_S > half_S+EPS){

			long double calc_S = tmp_S-last_add;
			long double diff = half_S-calc_S;

			long double bottom_len = calc_dist(POLY[toimen_next],POLY[toimen]);
			long double tmp_mult = (diff/last_add)*bottom_len;

			Vector tmp_vec = POLY[toimen_next]-POLY[toimen];
			tmp_vec = tmp_vec/abs(tmp_vec); //単位ベクトル

			Point tmp_p = POLY[toimen]+tmp_vec*tmp_mult; //線分base-tmp_pがポリゴンの面積を二等分する

			long double tmp_dist = calc_dist(POLY[base],tmp_p);

			maximum = max(maximum,tmp_dist);
			minimum = min(minimum,tmp_dist);
		}

		Line base_line = make_longer(Line(POLY[base],POLY[base_next]));
		Line toimen_line = make_longer(Line(POLY[toimen_next],POLY[toimen]));

		long double base_slope = calc_slope(base_line);
		long double toimen_slope = calc_slope(toimen_line);

		Line corner_bisector; //角の二等分線

		long double rest_S = S-tmp_S;

		if(fabs(base_slope-toimen_slope) < EPS){ //★★★★★例外ケース★★★★★

			minimum = min(minimum,getDistance(base_line,toimen_line));
			continue;

		}else{

			if(!is_Cross(base_line,toimen_line)){ //■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■逆処理■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

				//逆方向に伸ばす
				base_line = make_longer(Line(POLY[base_next],POLY[base]));
				toimen_line = make_longer(Line(POLY[toimen],POLY[toimen_next]));

				Point cross_p = calc_Cross_Point(base_line,toimen_line);
				long double tmp_rad = calc_rad(cross_p,POLY[base_next],POLY[toimen]);

				Point work_p = rotate(cross_p,POLY[base_next],tmp_rad/2); //角の二等分線の計算用

				corner_bisector = make_longer(Line(cross_p,work_p)); //角の二等分線

				Point temae = calc_Cross_Point(corner_bisector,Line(POLY[toimen_next],POLY[base]));
				Point oku = calc_Cross_Point(corner_bisector,Line(POLY[base_next],POLY[toimen]));


				Vector vec = oku-temae;
				long double R = abs(vec);

				vec = vec/abs(vec); //単位ベクトルにする

				long double L = 0;

				long double SLOPE;
				Type type;

				if(fabs(corner_bisector.p[0].x-corner_bisector.p[1].x) < EPS){ //角の二等分線が垂直

					type = Horizon;

				}else if(fabs(corner_bisector.p[0].y-corner_bisector.p[1].y) < EPS){ //角の二等分線が水平

					type = Vertical;
				}else{

					type = Normal;
					SLOPE = -1.0/calc_slope(corner_bisector);
				}


				//面積を半分にする地点を三分探索する
				for(int loop = 0; loop < 100; loop++){

					if(fabs(L-R) < EPS)break;

					long double mid1 = (2.0*L+R)/3.0;
					long double mid2 = (1.0*L+2.0*R)/3.0;

					vector<Point> tmp_P;
					tmp_P.push_back(temae+vec*mid1);
					tmp_P.push_back(temae+vec*mid2);

					long double diff_1,diff_2;

					for(int a = 0; a < tmp_P.size(); a++){

						Line div_line;

						if(type == Horizon){

							div_line = Line(Point(tmp_P[a].x-NUM,tmp_P[a].y),Point(tmp_P[a].x+NUM,tmp_P[a].y));

						}else if(type == Vertical){

							div_line = Line(Point(tmp_P[a].x,tmp_P[a].y-NUM),Point(tmp_P[a].x,tmp_P[a].y+NUM));

						}else{

							div_line.p[0] = Point(tmp_P[a].x-NUM,tmp_P[a].y-NUM*SLOPE);
							div_line.p[1] = Point(tmp_P[a].x+NUM,tmp_P[a].y+NUM*SLOPE);
						}

						Point cross_1 = calc_Cross_Point(base_line,div_line);
						Point cross_2 = calc_Cross_Point(toimen_line,div_line);

						Polygon add_poly;
						add_poly.push_back(POLY[base]);
						add_poly.push_back(cross_1);
						add_poly.push_back(cross_2);
						add_poly.push_back(POLY[toimen_next]);

						long double add_S = calc_S(add_poly);

						if(a == 0){

							diff_1 = fabs(half_S-(rest_S+add_S));
						}else{

							diff_2 = fabs(half_S-(rest_S+add_S));
						}
					}

					if(diff_1 < diff_2){

						R = mid2;
					}else{

						L = mid1;
					}
				}

				Point on_P = temae+vec*((L+R)/2);

				Line final_line;

				if(type == Horizon){

					final_line = Line(Point(on_P.x-NUM,on_P.y),Point(on_P.x+NUM,on_P.y));

				}else if(type == Vertical){

					final_line = Line(Point(on_P.x,on_P.y-NUM),Point(on_P.x,on_P.y+NUM));

				}else{

					final_line.p[0] = Point(on_P.x-NUM,on_P.y-NUM*SLOPE);
					final_line.p[1] = Point(on_P.x+NUM,on_P.y+NUM*SLOPE);
				}

				Point final_1 = calc_Cross_Point(base_line,final_line);
				Point final_2 = calc_Cross_Point(toimen_line,final_line);

				long double final_dist = calc_dist(final_1,final_2);

				minimum = min(minimum,final_dist);


				continue;
			} //■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■逆処理■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

			Point cross_p = calc_Cross_Point(base_line,toimen_line);
			long double tmp_rad = calc_rad(cross_p,POLY[toimen_next],POLY[base]);

			Point work_p = rotate(cross_p,POLY[toimen_next],tmp_rad/2); //角の二等分線の計算用

			Vector tmp_vec = work_p-cross_p;
			corner_bisector = Line(cross_p,cross_p+tmp_vec*NUM); //角の二等分線
		}

		Point temae,oku;

		double calc_slope_1 = calc_slope(Line(POLY[base_next],POLY[toimen]));
		double calc_slope_2 = calc_slope(Line(POLY[base],POLY[toimen_next]));

		if(fabs(corner_bisector.p[0].x-corner_bisector.p[1].x) < EPS*1000){ //角の二等分線が垂直

			if(fabs(calc_slope_1) < EPS){ //水平

				temae = Point(corner_bisector.p[0].x,POLY[base_next].y);

			}else{

				temae = calc_Cross_Point(corner_bisector,Line(POLY[base_next],POLY[toimen]));
			}

			if(fabs(calc_slope_2) < EPS){

				oku = Point(corner_bisector.p[0].x,POLY[base].y);

			}else{

				oku	= calc_Cross_Point(corner_bisector,Line(POLY[base],POLY[toimen_next]));
			}

		}else if(fabs(corner_bisector.p[0].y-corner_bisector.p[1].y) < EPS){ //角の二等分線が水平

			if(fabs(calc_slope_1-DBL_MAX) < EPS){

				temae = Point(POLY[toimen].x,corner_bisector.p[0].y);

			}else{

				temae = calc_Cross_Point(corner_bisector,Line(POLY[base_next],POLY[toimen]));
			}

			if(fabs(calc_slope_2-DBL_MAX) < EPS){

				oku = Point(POLY[base].x,corner_bisector.p[0].y);

			}else{

				oku	= calc_Cross_Point(corner_bisector,Line(POLY[base],POLY[toimen_next]));
			}

		}else{

			temae = calc_Cross_Point(corner_bisector,Line(POLY[base_next],POLY[toimen]));
			oku	= calc_Cross_Point(corner_bisector,Line(POLY[base],POLY[toimen_next]));
		}

		Vector vec = temae-oku;
		long double R = abs(vec);

		vec = vec/abs(vec); //単位ベクトルにする

		long double L = 0;

		long double SLOPE;
		Type type;

		if(fabs(corner_bisector.p[0].x-corner_bisector.p[1].x) < EPS*1000){ //角の二等分線が垂直

			type = Horizon;

		}else if(fabs(corner_bisector.p[0].y-corner_bisector.p[1].y) < EPS){ //角の二等分線が水平

			type = Vertical;
		}else{

			type = Normal;
			SLOPE = -1.0/calc_slope(corner_bisector);
		}

		long double add_S;
		//面積を半分にする地点を三分探索する
		for(int loop = 0; loop < 100; loop++){

			if(fabs(L-R) < EPS)break;

			long double mid1 = (2.0*L+R)/3.0;
			long double mid2 = (1.0*L+2.0*R)/3.0;

			vector<Point> tmp_P;
			tmp_P.push_back(oku+vec*mid1);
			tmp_P.push_back(oku+vec*mid2);

			long double diff_1,diff_2;

			for(int a = 0; a < tmp_P.size(); a++){

				Line div_line;

				if(type == Horizon){

					div_line = Line(Point(tmp_P[a].x-NUM,tmp_P[a].y),Point(tmp_P[a].x+NUM,tmp_P[a].y));

				}else if(type == Vertical){

					div_line = Line(Point(tmp_P[a].x,tmp_P[a].y-NUM),Point(tmp_P[a].x,tmp_P[a].y+NUM));

				}else{

					div_line.p[0] = Point(tmp_P[a].x-NUM,tmp_P[a].y-NUM*SLOPE);
					div_line.p[1] = Point(tmp_P[a].x+NUM,tmp_P[a].y+NUM*SLOPE);
				}

				Point cross_1 = calc_Cross_Point(base_line,div_line);
				Point cross_2 = calc_Cross_Point(toimen_line,div_line);

				Polygon add_poly;
				add_poly.push_back(POLY[base]);
				add_poly.push_back(cross_1);
				add_poly.push_back(cross_2);
				add_poly.push_back(POLY[toimen_next]);

				add_S = calc_S(add_poly);

				if(a == 0){

					diff_1 = fabs(half_S-(rest_S+add_S));
				}else{

					diff_2 = fabs(half_S-(rest_S+add_S));
				}
			}

			if(diff_1 < diff_2){

				R = mid2;
			}else{

				L = mid1;
			}
		}

		Point on_P = oku+vec*((L+R)/2);

		Line final_line;

		if(type == Horizon){

			final_line = Line(Point(on_P.x-NUM,on_P.y),Point(on_P.x+NUM,on_P.y));

		}else if(type == Vertical){

			final_line = Line(Point(on_P.x,on_P.y-NUM),Point(on_P.x,on_P.y+NUM));

		}else{

			final_line.p[0] = Point(on_P.x-NUM,on_P.y-NUM*SLOPE);
			final_line.p[1] = Point(on_P.x+NUM,on_P.y+NUM*SLOPE);
		}

		Point final_1 = calc_Cross_Point(base_line,final_line);
		Point final_2 = calc_Cross_Point(toimen_line,final_line);

		long double final_dist = calc_dist(final_1,final_2);

		minimum = min(minimum,final_dist);
	}

	printf("%.10Lf\n",minimum);
	printf("%.10Lf\n",maximum);


	return 0;
}
accuracy: 1
time_ms: 320
memory_kb: 3988
final_rank: 5

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
//#define EPS 0.000000001
using namespace std;


#define EPS 0.000000001
#define SIZE 5005

enum Type{
	Horizon,
	Vertical,
	Normal,
};

struct Point{
	Point(long double arg_x,long double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (long double a){ return Point(a*x,a*y); }
	Point operator / (long double a){ return Point(x/a,y/a); }

	long double abs(){ return sqrt(norm()); }
	long double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3Lf,%.3Lf)\n",x,y);
	}

	long double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	void outPut(){

		printf("(%.3Lf,%.3Lf)-(%.3Lf,%.3Lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}
	Point p[2];
};

int N;
Polygon POLY;
Line line[SIZE];
//long double NUM = 10000000;
long double NUM = BIG_NUM;
//long double NUM = 1;


long double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

long double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

long double abs(Vector a){
	return sqrt(norm(a));
}

long double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

long double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

/*
 * p0を基準点として、p1から見てp2が
 * 反時計回り側にあれば
 * COUNTER_CLOCKWISE
 * */
int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}
int func(long double x1,long double y1,long double x2, long double y2, long double xp, long double yp){
	long double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}

Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

long double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
long double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
long double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

//線分と線分の距離
long double getDistance(Line A,Line B){
	if(is_Cross(A,B))return 0.0;
	return min(min(getDistanceSP(A,B.p[0]),getDistanceSP(A,B.p[1])),
			min(getDistanceSP(B,A.p[0]),getDistanceSP(B,A.p[1])));
}


//交点を求める関数
Point calc_Cross_Point(long double x1,long double x2,long double x3,long double x4,long double y1,long double y2,long double y3,long double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){


	long double MULT = 100; //EPSのままだと誤差が出る

	if(getDistanceSP(B,A.p[0]) < EPS*MULT){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS*MULT){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS*MULT){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS*MULT){

		return B.p[1];
	}

	double E = 10000;

	return calc_Cross_Point(A.p[0]*E,A.p[1]*E,B.p[0]*E,B.p[1]*E)/E;
}

long double calc_S(Polygon g){

	int N = g.size();
	long double ret = 0;

	for(int i = 0; i < g.size(); i++){
		ret += cross(g[i],g[(i+1)%N]);
	}
	return ret/2.0;
}

/*点moveをbaseを中心にradラジアン回転させる
rad > 0なら反時計回り、rad < 0なら時計周り
*/
Point rotate(Point base,Point move,long double rad){

	Point ret;
	move = move-base;

	ret.x = move.x*cos(rad)-move.y*sin(rad);
	ret.y = move.x*sin(rad)+move.y*cos(rad);

	ret = ret+base;

	return ret;
}

//2つのvectorがなすラジアンを求める関数
long double calc_rad(Vector vec1,Vector vec2){

	long double tmp = dot(vec1,vec2)/(abs(vec1)*abs(vec2));

	if(fabs(tmp+1.0) < EPS){

		return M_PI;
	}

	if(fabs(tmp-1.0) < EPS){

		return  0.0;
	}

	return acos(dot(vec1,vec2)/(abs(vec1)*abs(vec2)));
}

//3点がなすラジアンを求める関数(ccw(base,a,b) == CCW)
long double calc_rad(Point base,Point a,Point b){

	Vector vec1 = b-base;
	Vector vec2 = a-base;

	return calc_rad(vec1,vec2);
}

long double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

//線分をp[1]方向へ伸ばす
Line make_longer(Line arg_line){

	Line ret;
	ret.p[0] = arg_line.p[0];

	//p[1]方向へ直線を伸ばす
	if(fabs(arg_line.p[0].x-arg_line.p[1].x) < EPS){ //垂直

		if(arg_line.p[0].y > arg_line.p[1].y){

			ret.p[1] = Point(arg_line.p[0].x,arg_line.p[0].y-NUM);

		}else{

			ret.p[1] = Point(arg_line.p[0].x,arg_line.p[0].y+NUM);
		}

	}else if(fabs(arg_line.p[0].y-arg_line.p[1].y) < EPS){

		if(arg_line.p[0].x > arg_line.p[1].x){

			ret.p[1] = Point(arg_line.p[0].x-NUM,arg_line.p[0].y);

		}else{

			ret.p[1] = Point(arg_line.p[0].x+NUM,arg_line.p[0].y);
		}

	}else{

		long double work_slope = calc_slope(arg_line);

		if(arg_line.p[0].x > arg_line.p[1].x){

			ret.p[1] = Point(arg_line.p[0].x-NUM,arg_line.p[0].y-NUM*work_slope);

		}else{

			ret.p[1] = Point(arg_line.p[0].x+NUM,arg_line.p[0].y+NUM*work_slope);
		}
	}

	return ret;
}

bool DEBUG = false;

int main(){

	scanf("%d",&N);

	long double x,y;

	for(int i = 0; i < N; i++){

		scanf("%Lf %Lf",&x,&y);
		POLY.push_back(Point(x,y));
	}

	long double S = calc_S(POLY);
	long double half_S = S/2;

	for(int i = 0; i < N; i++){

		line[i].p[0] = POLY[i];
		line[i].p[1] = POLY[(i+1)%N];
	}

	long double minimum = BIG_NUM,maximum = -BIG_NUM;


	for(int base = 0; base < N; base++){

		int toimen,toimen_next;
		int base_next = (base+1)%N;

		long double tmp_S = 0;

		int pre = (base+1)%N;
		int next = (base+2)%N;

		long double last_add;

		bool just_FLG = false;

		while(true){

			last_add = cross(POLY[pre]-POLY[base],POLY[next]-POLY[base])/2;
			tmp_S += last_add;

			if(fabs(tmp_S-half_S) < EPS){ //ちょうど半分

				just_FLG = true;

				if(DEBUG){

					printf("@@@@@@@@ちょうど半分@@@@@@@@\n");
				}

				long double tmp_dist = calc_dist(POLY[base],POLY[next]);

				maximum = max(maximum,tmp_dist);
				minimum = min(minimum,tmp_dist);

				toimen = next;
				toimen_next = (next+1)%N;

				break;

			}else if(tmp_S > half_S+EPS){

				toimen = pre;
				toimen_next = next;

				break;
			}

			pre = next;
			next = (next+1)%N;
		}


		if(tmp_S > half_S+EPS){

			long double calc_S = tmp_S-last_add;
			long double diff = half_S-calc_S;

			long double bottom_len = calc_dist(POLY[toimen_next],POLY[toimen]);
			long double tmp_mult = (diff/last_add)*bottom_len;

			Vector tmp_vec = POLY[toimen_next]-POLY[toimen];
			tmp_vec = tmp_vec/abs(tmp_vec); //単位ベクトル

			Point tmp_p = POLY[toimen]+tmp_vec*tmp_mult; //線分base-tmp_pがポリゴンの面積を二等分する

			long double tmp_dist = calc_dist(POLY[base],tmp_p);

			if(DEBUG){

				//printf("half_Sとの差\n");
				//printf("%.12lf\n",fabs(half_S-(calc_S+last_add*(tmp_mult/tmp_dist))));
			}

			maximum = max(maximum,tmp_dist);
			minimum = min(minimum,tmp_dist);
		}

		if(DEBUG){

			printf("\nbase:%d base_next:%d toi:%d toi_next:%d\n",base,base_next,toimen,toimen_next);
			printf("tmp_S-half_S:%.10Lf\n",tmp_S-half_S);
			printf("base");
			POLY[base].debug();
			printf("base_next");
			POLY[base_next].debug();
		}


		Line base_line = make_longer(Line(POLY[base],POLY[base_next]));
		Line toimen_line = make_longer(Line(POLY[toimen_next],POLY[toimen]));

		long double base_slope = calc_slope(base_line);
		long double toimen_slope = calc_slope(toimen_line);

		if(DEBUG){

			printf("toimen:");
			POLY[toimen].debug();
			printf("toi_next");
			POLY[toimen_next].debug();

			//printf("base_slope:%.3lf toi_slope:%.3lf\n",base_slope,toimen_slope);
		}

		Line corner_bisector; //角の二等分線

		long double rest_S = S-tmp_S;

		if(DEBUG){

			//printf("restS:%.3lf\n",rest_S);
		}

		bool is_exception = false;
		Type exception_type;

		if(fabs(base_slope-toimen_slope) < EPS){ //★★★★★例外ケース★★★★★

			minimum = min(minimum,getDistance(base_line,toimen_line));
			continue;

			is_exception = true;

			double L,R;

			if(fabs(base_slope-DBL_MAX) < EPS){

				exception_type = Vertical;
				double min_1 = min(POLY[base].y,POLY[base+1].y);
				double max_1 = max(POLY[base].y,POLY[base+1].y);

				double min_2 = min(POLY[toimen].y,POLY[toimen_next].y);
				double max_2 = max(POLY[toimen].y,POLY[toimen_next].y);

				L = max(min_1,min_2);
				R = min(max_1,max_2);

				if(L > R)continue;

			}else{

				exception_type = Horizon;

				double min_1 = min(POLY[base].x,POLY[base+1].x);
				double max_1 = max(POLY[base].x,POLY[base+1].x);

				double min_2 = min(POLY[toimen].x,POLY[toimen_next].x);
				double max_2 = max(POLY[toimen].x,POLY[toimen_next].x);

				L = max(min_1,min_2);
				R = min(max_1,max_2);

				if(L > R)continue;

				printf("minimum:%.12Lfでchmin\n",fabs(POLY[base].y-POLY[toimen].y));
				minimum = min(minimum,fabs(POLY[base].y-POLY[toimen].y));
			}

			continue;

		}else{

			if(!is_Cross(base_line,toimen_line)){ //■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■逆処理■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

				if(DEBUG){
					printf("★base_lineとtoimen_lineが交差しない★\n");
					printf("base_line\n");
					base_line.outPut();
					printf("toimen\n");
					toimen_line.outPut();
				}

				//逆方向に伸ばす
				base_line = make_longer(Line(POLY[base_next],POLY[base]));
				toimen_line = make_longer(Line(POLY[toimen],POLY[toimen_next]));

				if(!is_Cross(base_line,toimen_line)){

					printf("★revでも非交差 NUMが小さい★\n");


					return 0;
				}

				Point cross_p = calc_Cross_Point(base_line,toimen_line);
				long double tmp_rad = calc_rad(cross_p,POLY[base_next],POLY[toimen]);

				Point work_p = rotate(cross_p,POLY[base_next],tmp_rad/2); //角の二等分線の計算用

				corner_bisector = make_longer(Line(cross_p,work_p)); //角の二等分線

				Point temae = calc_Cross_Point(corner_bisector,Line(POLY[toimen_next],POLY[base]));
				Point oku = calc_Cross_Point(corner_bisector,Line(POLY[base_next],POLY[toimen]));

				if(DEBUG){

									printf("手前");
									temae.debug();
									printf("置く");
									oku.debug();
								}


				Vector vec = oku-temae;
				long double R = abs(vec);

				vec = vec/abs(vec); //単位ベクトルにする

				long double L = 0;

				long double SLOPE;
				Type type;

				if(fabs(corner_bisector.p[0].x-corner_bisector.p[1].x) < EPS){ //角の二等分線が垂直

					type = Horizon;

				}else if(fabs(corner_bisector.p[0].y-corner_bisector.p[1].y) < EPS){ //角の二等分線が水平

					type = Vertical;
				}else{

					type = Normal;
					SLOPE = -1.0/calc_slope(corner_bisector);
				}


				//面積を半分にする地点を三分探索する
				for(int loop = 0; loop < 100; loop++){

					if(fabs(L-R) < EPS)break;

					long double mid1 = (2.0*L+R)/3.0;
					long double mid2 = (1.0*L+2.0*R)/3.0;

					vector<Point> tmp_P;
					tmp_P.push_back(temae+vec*mid1);
					tmp_P.push_back(temae+vec*mid2);

					long double diff_1,diff_2;

					for(int a = 0; a < tmp_P.size(); a++){

						Line div_line;

						if(type == Horizon){

							div_line = Line(Point(tmp_P[a].x-NUM,tmp_P[a].y),Point(tmp_P[a].x+NUM,tmp_P[a].y));

						}else if(type == Vertical){

							div_line = Line(Point(tmp_P[a].x,tmp_P[a].y-NUM),Point(tmp_P[a].x,tmp_P[a].y+NUM));

						}else{

							div_line.p[0] = Point(tmp_P[a].x-NUM,tmp_P[a].y-NUM*SLOPE);
							div_line.p[1] = Point(tmp_P[a].x+NUM,tmp_P[a].y+NUM*SLOPE);
						}

						Point cross_1 = calc_Cross_Point(base_line,div_line);
						if(isnan(cross_1.x)){
							printf("NAN L:%.15Lf R:%.15Lf\n",L,R);
							return 0;
						}
						Point cross_2 = calc_Cross_Point(toimen_line,div_line);
						if(isnan(cross_2.x)){
							printf("NAN L:%.15Lf R:%.15Lf\n",L,R);
							return 0;
						}

						Polygon add_poly;
						add_poly.push_back(POLY[base]);
						add_poly.push_back(cross_1);
						add_poly.push_back(cross_2);
						add_poly.push_back(POLY[toimen_next]);

						long double add_S = calc_S(add_poly);

						if(a == 0){

							diff_1 = fabs(half_S-(rest_S+add_S));
						}else{

							diff_2 = fabs(half_S-(rest_S+add_S));
						}
					}

					if(diff_1 < diff_2){

						R = mid2;
					}else{

						L = mid1;
					}
				}

				Point on_P = temae+vec*((L+R)/2);

				Line final_line;

				if(type == Horizon){

					final_line = Line(Point(on_P.x-NUM,on_P.y),Point(on_P.x+NUM,on_P.y));

				}else if(type == Vertical){

					final_line = Line(Point(on_P.x,on_P.y-NUM),Point(on_P.x,on_P.y+NUM));

				}else{

					final_line.p[0] = Point(on_P.x-NUM,on_P.y-NUM*SLOPE);
					final_line.p[1] = Point(on_P.x+NUM,on_P.y+NUM*SLOPE);
				}

				Point final_1 = calc_Cross_Point(base_line,final_line);
				Point final_2 = calc_Cross_Point(toimen_line,final_line);

				long double final_dist = calc_dist(final_1,final_2);

				minimum = min(minimum,final_dist);


				continue;
			} //■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■逆処理■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

			Point cross_p = calc_Cross_Point(base_line,toimen_line);
			long double tmp_rad = calc_rad(cross_p,POLY[toimen_next],POLY[base]);

			Point work_p = rotate(cross_p,POLY[toimen_next],tmp_rad/2); //角の二等分線の計算用

			Vector tmp_vec = work_p-cross_p;
			corner_bisector = Line(cross_p,cross_p+tmp_vec*NUM); //角の二等分線

			if(DEBUG){

				printf("角の二等分線\n");
				corner_bisector.outPut();
			}

		}

		Point temae,oku;

		double calc_slope_1 = calc_slope(Line(POLY[base_next],POLY[toimen]));
		double calc_slope_2 = calc_slope(Line(POLY[base],POLY[toimen_next]));

		if(fabs(corner_bisector.p[0].x-corner_bisector.p[1].x) < EPS*1000){ //角の二等分線が垂直

			if(fabs(calc_slope_1) < EPS){ //水平

				temae = Point(corner_bisector.p[0].x,POLY[base_next].y);

			}else{

				temae = calc_Cross_Point(corner_bisector,Line(POLY[base_next],POLY[toimen]));
			}

			if(fabs(calc_slope_2) < EPS){

				oku = Point(corner_bisector.p[0].x,POLY[base].y);

			}else{

				oku	= calc_Cross_Point(corner_bisector,Line(POLY[base],POLY[toimen_next]));
			}

		}else if(fabs(corner_bisector.p[0].y-corner_bisector.p[1].y) < EPS){ //角の二等分線が水平

			if(fabs(calc_slope_1-DBL_MAX) < EPS){

				temae = Point(POLY[toimen].x,corner_bisector.p[0].y);

			}else{

				temae = calc_Cross_Point(corner_bisector,Line(POLY[base_next],POLY[toimen]));
			}

			if(fabs(calc_slope_2-DBL_MAX) < EPS){

				oku = Point(POLY[base].x,corner_bisector.p[0].y);

			}else{

				oku	= calc_Cross_Point(corner_bisector,Line(POLY[base],POLY[toimen_next]));
			}

		}else{

			temae = calc_Cross_Point(corner_bisector,Line(POLY[base_next],POLY[toimen]));
			oku	= calc_Cross_Point(corner_bisector,Line(POLY[base],POLY[toimen_next]));
		}

		if(DEBUG){

					printf("手前");
					temae.debug();
					printf("置く");
					oku.debug();
				}


		Vector vec = temae-oku;
		long double R = abs(vec);

		vec = vec/abs(vec); //単位ベクトルにする

		long double L = 0;

		long double SLOPE;
		Type type;

		if(fabs(corner_bisector.p[0].x-corner_bisector.p[1].x) < EPS*1000){ //角の二等分線が垂直

			//printf("@@@角の二等分線が垂直@@@\n");
			type = Horizon;

		}else if(fabs(corner_bisector.p[0].y-corner_bisector.p[1].y) < EPS){ //角の二等分線が水平

			type = Vertical;
		}else{

			type = Normal;
			SLOPE = -1.0/calc_slope(corner_bisector);
		}

		long double add_S;
		//面積を半分にする地点を散文探索する
		for(int loop = 0; loop < 100; loop++){

			if(fabs(L-R) < EPS)break;

			long double mid1 = (2.0*L+R)/3.0;
			long double mid2 = (1.0*L+2.0*R)/3.0;

			vector<Point> tmp_P;
			tmp_P.push_back(oku+vec*mid1);
			tmp_P.push_back(oku+vec*mid2);

			long double diff_1,diff_2;

			for(int a = 0; a < tmp_P.size(); a++){

				Line div_line;

				if(type == Horizon){

					div_line = Line(Point(tmp_P[a].x-NUM,tmp_P[a].y),Point(tmp_P[a].x+NUM,tmp_P[a].y));

				}else if(type == Vertical){

					div_line = Line(Point(tmp_P[a].x,tmp_P[a].y-NUM),Point(tmp_P[a].x,tmp_P[a].y+NUM));

				}else{

					div_line.p[0] = Point(tmp_P[a].x-NUM,tmp_P[a].y-NUM*SLOPE);
					div_line.p[1] = Point(tmp_P[a].x+NUM,tmp_P[a].y+NUM*SLOPE);
				}

				Point cross_1 = calc_Cross_Point(base_line,div_line);
				Point cross_2 = calc_Cross_Point(toimen_line,div_line);
				if(isnan(cross_1.x)){
					printf("NAN L:%.15Lf R:%.15Lf\n",L,R);
					return 0;
				}
				if(isnan(cross_2.x)){
					printf("NAN L:%.15Lf R:%.15Lf\n",L,R);
					return 0;
				}


				Polygon add_poly;
				add_poly.push_back(POLY[base]);
				add_poly.push_back(cross_1);
				add_poly.push_back(cross_2);
				add_poly.push_back(POLY[toimen_next]);

				add_S = calc_S(add_poly);

				if(a == 0){

					diff_1 = fabs(half_S-(rest_S+add_S));
				}else{

					diff_2 = fabs(half_S-(rest_S+add_S));
				}
			}

			if(diff_1 < diff_2){

				R = mid2;
			}else{

				L = mid1;
			}
		}

		if(DEBUG){

			printf("haf_Sとの差");
			printf("%.12Lf\n",fabs(half_S-(rest_S+add_S)));
		}

		Point on_P = oku+vec*((L+R)/2);

		Line final_line;

		if(type == Horizon){

			final_line = Line(Point(on_P.x-NUM,on_P.y),Point(on_P.x+NUM,on_P.y));

		}else if(type == Vertical){

			final_line = Line(Point(on_P.x,on_P.y-NUM),Point(on_P.x,on_P.y+NUM));

		}else{

			final_line.p[0] = Point(on_P.x-NUM,on_P.y-NUM*SLOPE);
			final_line.p[1] = Point(on_P.x+NUM,on_P.y+NUM*SLOPE);
		}

		Point final_1 = calc_Cross_Point(base_line,final_line);
		Point final_2 = calc_Cross_Point(toimen_line,final_line);

		double deb_slope = calc_slope(Line(final_1,final_2));


		long double final_dist = calc_dist(final_1,final_2);

		if(DEBUG){
		printf("★★★★★★base:%d final_dist:%.10Lf★★★★★★\n",base,final_dist);
		}

		minimum = min(minimum,final_dist);
	}



	printf("%.10Lf\n",minimum);
	printf("%.10Lf\n",maximum);


	return 0;
}
accuracy: 1
time_ms: 340
memory_kb: 3980
final_rank: 6

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
//#define EPS 0.000000001
using namespace std;


#define EPS 0.000000001
#define SIZE 5005

enum Type{
	Horizon,
	Vertical,
	Normal,
};

struct Point{
	Point(long double arg_x,long double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (long double a){ return Point(a*x,a*y); }
	Point operator / (long double a){ return Point(x/a,y/a); }

	long double abs(){ return sqrt(norm()); }
	long double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3Lf,%.3Lf)\n",x,y);
	}

	long double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	void outPut(){

		printf("(%.3Lf,%.3Lf)-(%.3Lf,%.3Lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}
	Point p[2];
};

int N;
Polygon POLY;
Line line[SIZE];
//long double NUM = 10000000;
long double NUM = BIG_NUM;
//long double NUM = 1;


long double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

long double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

long double abs(Vector a){
	return sqrt(norm(a));
}

long double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

long double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

/*
 * p0を基準点として、p1から見てp2が
 * 反時計回り側にあれば
 * COUNTER_CLOCKWISE
 * */
int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}
int func(long double x1,long double y1,long double x2, long double y2, long double xp, long double yp){
	long double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}

Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

long double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
long double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
long double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

//線分と線分の距離
long double getDistance(Line A,Line B){
	if(is_Cross(A,B))return 0.0;
	return min(min(getDistanceSP(A,B.p[0]),getDistanceSP(A,B.p[1])),
			min(getDistanceSP(B,A.p[0]),getDistanceSP(B,A.p[1])));
}


//交点を求める関数
Point calc_Cross_Point(long double x1,long double x2,long double x3,long double x4,long double y1,long double y2,long double y3,long double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){


	long double MULT = 100; //EPSのままだと誤差が出る

	if(getDistanceSP(B,A.p[0]) < EPS*MULT){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS*MULT){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS*MULT){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS*MULT){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

long double calc_S(Polygon g){

	int N = g.size();
	long double ret = 0;

	for(int i = 0; i < g.size(); i++){
		ret += cross(g[i],g[(i+1)%N]);
	}
	return ret/2.0;
}

/*点moveをbaseを中心にradラジアン回転させる
rad > 0なら反時計回り、rad < 0なら時計周り
*/
Point rotate(Point base,Point move,long double rad){

	Point ret;
	move = move-base;

	ret.x = move.x*cos(rad)-move.y*sin(rad);
	ret.y = move.x*sin(rad)+move.y*cos(rad);

	ret = ret+base;

	return ret;
}

//2つのvectorがなすラジアンを求める関数
long double calc_rad(Vector vec1,Vector vec2){

	long double tmp = dot(vec1,vec2)/(abs(vec1)*abs(vec2));

	if(fabs(tmp+1.0) < EPS){

		return M_PI;
	}

	if(fabs(tmp-1.0) < EPS){

		return  0.0;
	}

	return acos(dot(vec1,vec2)/(abs(vec1)*abs(vec2)));
}

//3点がなすラジアンを求める関数(ccw(base,a,b) == CCW)
long double calc_rad(Point base,Point a,Point b){

	Vector vec1 = b-base;
	Vector vec2 = a-base;

	return calc_rad(vec1,vec2);
}

long double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

//線分をp[1]方向へ伸ばす
Line make_longer(Line arg_line){

	Line ret;
	ret.p[0] = arg_line.p[0];

	//p[1]方向へ直線を伸ばす
	if(fabs(arg_line.p[0].x-arg_line.p[1].x) < EPS){ //垂直

		if(arg_line.p[0].y > arg_line.p[1].y){

			ret.p[1] = Point(arg_line.p[0].x,arg_line.p[0].y-NUM);

		}else{

			ret.p[1] = Point(arg_line.p[0].x,arg_line.p[0].y+NUM);
		}

	}else if(fabs(arg_line.p[0].y-arg_line.p[1].y) < EPS){

		if(arg_line.p[0].x > arg_line.p[1].x){

			ret.p[1] = Point(arg_line.p[0].x-NUM,arg_line.p[0].y);

		}else{

			ret.p[1] = Point(arg_line.p[0].x+NUM,arg_line.p[0].y);
		}

	}else{

		long double work_slope = calc_slope(arg_line);

		if(arg_line.p[0].x > arg_line.p[1].x){

			ret.p[1] = Point(arg_line.p[0].x-NUM,arg_line.p[0].y-NUM*work_slope);

		}else{

			ret.p[1] = Point(arg_line.p[0].x+NUM,arg_line.p[0].y+NUM*work_slope);
		}
	}

	return ret;
}

bool DEBUG = false;

int main(){

	scanf("%d",&N);

	long double x,y;

	for(int i = 0; i < N; i++){

		scanf("%Lf %Lf",&x,&y);
		POLY.push_back(Point(x,y));
	}

	long double S = calc_S(POLY);
	long double half_S = S/2;

	for(int i = 0; i < N; i++){

		line[i].p[0] = POLY[i];
		line[i].p[1] = POLY[(i+1)%N];
	}

	long double minimum = BIG_NUM,maximum = -BIG_NUM;


	for(int base = 0; base < N; base++){

		int toimen,toimen_next;
		int base_next = (base+1)%N;

		long double tmp_S = 0;

		int pre = (base+1)%N;
		int next = (base+2)%N;

		long double last_add;

		bool just_FLG = false;

		while(true){

			last_add = cross(POLY[pre]-POLY[base],POLY[next]-POLY[base])/2;
			tmp_S += last_add;

			if(fabs(tmp_S-half_S) < EPS){ //ちょうど半分

				just_FLG = true;

				if(DEBUG){

					printf("@@@@@@@@ちょうど半分@@@@@@@@\n");
				}

				long double tmp_dist = calc_dist(POLY[base],POLY[next]);

				maximum = max(maximum,tmp_dist);
				minimum = min(minimum,tmp_dist);

				toimen = next;
				toimen_next = (next+1)%N;

				break;

			}else if(tmp_S > half_S+EPS){

				toimen = pre;
				toimen_next = next;

				break;
			}

			pre = next;
			next = (next+1)%N;
		}


		if(tmp_S > half_S+EPS){

			long double calc_S = tmp_S-last_add;
			long double diff = half_S-calc_S;

			long double bottom_len = calc_dist(POLY[toimen_next],POLY[toimen]);
			long double tmp_mult = (diff/last_add)*bottom_len;

			Vector tmp_vec = POLY[toimen_next]-POLY[toimen];
			tmp_vec = tmp_vec/abs(tmp_vec); //単位ベクトル

			Point tmp_p = POLY[toimen]+tmp_vec*tmp_mult; //線分base-tmp_pがポリゴンの面積を二等分する

			long double tmp_dist = calc_dist(POLY[base],tmp_p);

			if(DEBUG){

				//printf("half_Sとの差\n");
				//printf("%.12lf\n",fabs(half_S-(calc_S+last_add*(tmp_mult/tmp_dist))));
			}

			maximum = max(maximum,tmp_dist);
			minimum = min(minimum,tmp_dist);
		}

		if(DEBUG){

			printf("\nbase:%d base_next:%d toi:%d toi_next:%d\n",base,base_next,toimen,toimen_next);
			printf("tmp_S-half_S:%.10Lf\n",tmp_S-half_S);
			printf("base");
			POLY[base].debug();
			printf("base_next");
			POLY[base_next].debug();
		}


		Line base_line = make_longer(Line(POLY[base],POLY[base_next]));
		Line toimen_line = make_longer(Line(POLY[toimen_next],POLY[toimen]));

		long double base_slope = calc_slope(base_line);
		long double toimen_slope = calc_slope(toimen_line);

		if(DEBUG){

			printf("toimen:");
			POLY[toimen].debug();
			printf("toi_next");
			POLY[toimen_next].debug();

			//printf("base_slope:%.3lf toi_slope:%.3lf\n",base_slope,toimen_slope);
		}

		Line corner_bisector; //角の二等分線

		long double rest_S = S-tmp_S;

		if(DEBUG){

			//printf("restS:%.3lf\n",rest_S);
		}

		bool is_exception = false;
		Type exception_type;

		if(fabs(base_slope-toimen_slope) < EPS){ //★★★★★例外ケース★★★★★

			minimum = min(minimum,getDistance(base_line,toimen_line));
			continue;

			is_exception = true;

			double L,R;

			if(fabs(base_slope-DBL_MAX) < EPS){

				exception_type = Vertical;
				double min_1 = min(POLY[base].y,POLY[base+1].y);
				double max_1 = max(POLY[base].y,POLY[base+1].y);

				double min_2 = min(POLY[toimen].y,POLY[toimen_next].y);
				double max_2 = max(POLY[toimen].y,POLY[toimen_next].y);

				L = max(min_1,min_2);
				R = min(max_1,max_2);

				if(L > R)continue;

			}else{

				exception_type = Horizon;

				double min_1 = min(POLY[base].x,POLY[base+1].x);
				double max_1 = max(POLY[base].x,POLY[base+1].x);

				double min_2 = min(POLY[toimen].x,POLY[toimen_next].x);
				double max_2 = max(POLY[toimen].x,POLY[toimen_next].x);

				L = max(min_1,min_2);
				R = min(max_1,max_2);

				if(L > R)continue;

				printf("minimum:%.12Lfでchmin\n",fabs(POLY[base].y-POLY[toimen].y));
				minimum = min(minimum,fabs(POLY[base].y-POLY[toimen].y));
			}

			continue;

		}else{

			if(!is_Cross(base_line,toimen_line)){ //■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■逆処理■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

				if(DEBUG){
					printf("★base_lineとtoimen_lineが交差しない★\n");
					printf("base_line\n");
					base_line.outPut();
					printf("toimen\n");
					toimen_line.outPut();
				}

				//逆方向に伸ばす
				base_line = make_longer(Line(POLY[base_next],POLY[base]));
				toimen_line = make_longer(Line(POLY[toimen],POLY[toimen_next]));

				if(!is_Cross(base_line,toimen_line)){

					printf("★revでも非交差 NUMが小さい★\n");


					return 0;
				}

				Point cross_p = calc_Cross_Point(base_line,toimen_line);
				long double tmp_rad = calc_rad(cross_p,POLY[base_next],POLY[toimen]);

				Point work_p = rotate(cross_p,POLY[base_next],tmp_rad/2); //角の二等分線の計算用

				corner_bisector = make_longer(Line(cross_p,work_p)); //角の二等分線

				Point temae = calc_Cross_Point(corner_bisector,Line(POLY[toimen_next],POLY[base]));
				Point oku = calc_Cross_Point(corner_bisector,Line(POLY[base_next],POLY[toimen]));

				if(DEBUG){

									printf("手前");
									temae.debug();
									printf("置く");
									oku.debug();
								}


				Vector vec = oku-temae;
				long double R = abs(vec);

				vec = vec/abs(vec); //単位ベクトルにする

				long double L = 0;

				long double SLOPE;
				Type type;

				if(fabs(corner_bisector.p[0].x-corner_bisector.p[1].x) < EPS){ //角の二等分線が垂直

					type = Horizon;

				}else if(fabs(corner_bisector.p[0].y-corner_bisector.p[1].y) < EPS){ //角の二等分線が水平

					type = Vertical;
				}else{

					type = Normal;
					SLOPE = -1.0/calc_slope(corner_bisector);
				}


				//面積を半分にする地点を三分探索する
				for(int loop = 0; loop < 100; loop++){

					if(fabs(L-R) < EPS)break;

					long double mid1 = (2.0*L+R)/3.0;
					long double mid2 = (1.0*L+2.0*R)/3.0;

					vector<Point> tmp_P;
					tmp_P.push_back(temae+vec*mid1);
					tmp_P.push_back(temae+vec*mid2);

					long double diff_1,diff_2;

					for(int a = 0; a < tmp_P.size(); a++){

						Line div_line;

						if(type == Horizon){

							div_line = Line(Point(tmp_P[a].x-NUM,tmp_P[a].y),Point(tmp_P[a].x+NUM,tmp_P[a].y));

						}else if(type == Vertical){

							div_line = Line(Point(tmp_P[a].x,tmp_P[a].y-NUM),Point(tmp_P[a].x,tmp_P[a].y+NUM));

						}else{

							div_line.p[0] = Point(tmp_P[a].x-NUM,tmp_P[a].y-NUM*SLOPE);
							div_line.p[1] = Point(tmp_P[a].x+NUM,tmp_P[a].y+NUM*SLOPE);
						}

						Point cross_1 = calc_Cross_Point(base_line,div_line);
						if(isnan(cross_1.x)){
							printf("NAN L:%.15Lf R:%.15Lf\n",L,R);
							return 0;
						}
						Point cross_2 = calc_Cross_Point(toimen_line,div_line);
						if(isnan(cross_2.x)){
							printf("NAN L:%.15Lf R:%.15Lf\n",L,R);
							return 0;
						}

						Polygon add_poly;
						add_poly.push_back(POLY[base]);
						add_poly.push_back(cross_1);
						add_poly.push_back(cross_2);
						add_poly.push_back(POLY[toimen_next]);

						long double add_S = calc_S(add_poly);

						if(a == 0){

							diff_1 = fabs(half_S-(rest_S+add_S));
						}else{

							diff_2 = fabs(half_S-(rest_S+add_S));
						}
					}

					if(diff_1 < diff_2){

						R = mid2;
					}else{

						L = mid1;
					}
				}

				Point on_P = temae+vec*((L+R)/2);

				Line final_line;

				if(type == Horizon){

					final_line = Line(Point(on_P.x-NUM,on_P.y),Point(on_P.x+NUM,on_P.y));

				}else if(type == Vertical){

					final_line = Line(Point(on_P.x,on_P.y-NUM),Point(on_P.x,on_P.y+NUM));

				}else{

					final_line.p[0] = Point(on_P.x-NUM,on_P.y-NUM*SLOPE);
					final_line.p[1] = Point(on_P.x+NUM,on_P.y+NUM*SLOPE);
				}

				Point final_1 = calc_Cross_Point(base_line,final_line);
				Point final_2 = calc_Cross_Point(toimen_line,final_line);

				long double final_dist = calc_dist(final_1,final_2);

				minimum = min(minimum,final_dist);


				continue;
			} //■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■逆処理■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

			Point cross_p = calc_Cross_Point(base_line,toimen_line);
			long double tmp_rad = calc_rad(cross_p,POLY[toimen_next],POLY[base]);

			Point work_p = rotate(cross_p,POLY[toimen_next],tmp_rad/2); //角の二等分線の計算用

			Vector tmp_vec = work_p-cross_p;
			corner_bisector = Line(cross_p,cross_p+tmp_vec*NUM); //角の二等分線

			if(DEBUG){

				printf("角の二等分線\n");
				corner_bisector.outPut();
			}

		}

		Point temae,oku;

		double calc_slope_1 = calc_slope(Line(POLY[base_next],POLY[toimen]));
		double calc_slope_2 = calc_slope(Line(POLY[base],POLY[toimen_next]));

		if(fabs(corner_bisector.p[0].x-corner_bisector.p[1].x) < EPS*1000){ //角の二等分線が垂直

			if(fabs(calc_slope_1) < EPS){ //水平

				temae = Point(corner_bisector.p[0].x,POLY[base_next].y);

			}else{

				temae = calc_Cross_Point(corner_bisector,Line(POLY[base_next],POLY[toimen]));
			}

			if(fabs(calc_slope_2) < EPS){

				oku = Point(corner_bisector.p[0].x,POLY[base].y);

			}else{

				oku	= calc_Cross_Point(corner_bisector,Line(POLY[base],POLY[toimen_next]));
			}

		}else if(fabs(corner_bisector.p[0].y-corner_bisector.p[1].y) < EPS){ //角の二等分線が水平

			if(fabs(calc_slope_1-DBL_MAX) < EPS){

				temae = Point(POLY[toimen].x,corner_bisector.p[0].y);

			}else{

				temae = calc_Cross_Point(corner_bisector,Line(POLY[base_next],POLY[toimen]));
			}

			if(fabs(calc_slope_2-DBL_MAX) < EPS){

				oku = Point(POLY[base].x,corner_bisector.p[0].y);

			}else{

				oku	= calc_Cross_Point(corner_bisector,Line(POLY[base],POLY[toimen_next]));
			}

		}else{

			temae = calc_Cross_Point(corner_bisector,Line(POLY[base_next],POLY[toimen]));
			oku	= calc_Cross_Point(corner_bisector,Line(POLY[base],POLY[toimen_next]));
		}

		if(DEBUG){

					printf("手前");
					temae.debug();
					printf("置く");
					oku.debug();
				}


		Vector vec = temae-oku;
		long double R = abs(vec);

		vec = vec/abs(vec); //単位ベクトルにする

		long double L = 0;

		long double SLOPE;
		Type type;

		if(fabs(corner_bisector.p[0].x-corner_bisector.p[1].x) < EPS*1000){ //角の二等分線が垂直

			//printf("@@@角の二等分線が垂直@@@\n");
			type = Horizon;

		}else if(fabs(corner_bisector.p[0].y-corner_bisector.p[1].y) < EPS){ //角の二等分線が水平

			type = Vertical;
		}else{

			type = Normal;
			SLOPE = -1.0/calc_slope(corner_bisector);
		}

		long double add_S;
		//面積を半分にする地点を散文探索する
		for(int loop = 0; loop < 100; loop++){

			if(fabs(L-R) < EPS)break;

			long double mid1 = (2.0*L+R)/3.0;
			long double mid2 = (1.0*L+2.0*R)/3.0;

			vector<Point> tmp_P;
			tmp_P.push_back(oku+vec*mid1);
			tmp_P.push_back(oku+vec*mid2);

			long double diff_1,diff_2;

			for(int a = 0; a < tmp_P.size(); a++){

				Line div_line;

				if(type == Horizon){

					div_line = Line(Point(tmp_P[a].x-NUM,tmp_P[a].y),Point(tmp_P[a].x+NUM,tmp_P[a].y));

				}else if(type == Vertical){

					div_line = Line(Point(tmp_P[a].x,tmp_P[a].y-NUM),Point(tmp_P[a].x,tmp_P[a].y+NUM));

				}else{

					div_line.p[0] = Point(tmp_P[a].x-NUM,tmp_P[a].y-NUM*SLOPE);
					div_line.p[1] = Point(tmp_P[a].x+NUM,tmp_P[a].y+NUM*SLOPE);
				}

				Point cross_1 = calc_Cross_Point(base_line,div_line);
				Point cross_2 = calc_Cross_Point(toimen_line,div_line);
				if(isnan(cross_1.x)){
					printf("NAN L:%.15Lf R:%.15Lf\n",L,R);
					return 0;
				}
				if(isnan(cross_2.x)){
					printf("NAN L:%.15Lf R:%.15Lf\n",L,R);
					return 0;
				}


				Polygon add_poly;
				add_poly.push_back(POLY[base]);
				add_poly.push_back(cross_1);
				add_poly.push_back(cross_2);
				add_poly.push_back(POLY[toimen_next]);

				add_S = calc_S(add_poly);

				if(a == 0){

					diff_1 = fabs(half_S-(rest_S+add_S));
				}else{

					diff_2 = fabs(half_S-(rest_S+add_S));
				}
			}

			if(diff_1 < diff_2){

				R = mid2;
			}else{

				L = mid1;
			}
		}

		if(DEBUG){

			printf("haf_Sとの差");
			printf("%.12Lf\n",fabs(half_S-(rest_S+add_S)));
		}

		Point on_P = oku+vec*((L+R)/2);

		Line final_line;

		if(type == Horizon){

			final_line = Line(Point(on_P.x-NUM,on_P.y),Point(on_P.x+NUM,on_P.y));

		}else if(type == Vertical){

			final_line = Line(Point(on_P.x,on_P.y-NUM),Point(on_P.x,on_P.y+NUM));

		}else{

			final_line.p[0] = Point(on_P.x-NUM,on_P.y-NUM*SLOPE);
			final_line.p[1] = Point(on_P.x+NUM,on_P.y+NUM*SLOPE);
		}

		Point final_1 = calc_Cross_Point(base_line,final_line);
		Point final_2 = calc_Cross_Point(toimen_line,final_line);

		double deb_slope = calc_slope(Line(final_1,final_2));


		long double final_dist = calc_dist(final_1,final_2);

		if(DEBUG){
		printf("★★★★★★base:%d final_dist:%.10Lf★★★★★★\n",base,final_dist);
		}

		minimum = min(minimum,final_dist);
	}



	printf("%.10Lf\n",minimum);
	printf("%.10Lf\n",maximum);


	return 0;
}
accuracy: 0.4936708860759494
time_ms: 160
memory_kb: 3968
final_rank: 17

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
//#define EPS 0.000000001
using namespace std;


#define EPS 0.000000001
#define SIZE 5005

enum Type{
	Horizon,
	Vertical,
	Normal,
};

struct Point{
	Point(long double arg_x,long double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (long double a){ return Point(a*x,a*y); }
	Point operator / (long double a){ return Point(x/a,y/a); }

	long double abs(){ return sqrt(norm()); }
	long double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{

		if(fabs(x-p.x) > EPS){

			return x < p.x;
		}else{

			return y < p.y;
		}
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}


	void debug(){

		printf("(%.3Lf,%.3Lf)\n",x,y);
	}

	long double x,y;
};

typedef Point Vector;
typedef vector<Point> Polygon;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	void outPut(){

		printf("(%.3Lf,%.3Lf)-(%.3Lf,%.3Lf)\n",p[0].x,p[0].y,p[1].x,p[1].y);
	}
	Point p[2];
};

int N;
Polygon POLY;
Line line[SIZE];
//long double NUM = 10000000;
long double NUM = BIG_NUM;
//long double NUM = 1;


long double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

long double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

long double abs(Vector a){
	return sqrt(norm(a));
}

long double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

long double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

/*
 * p0を基準点として、p1から見てp2が
 * 反時計回り側にあれば
 * COUNTER_CLOCKWISE
 * */
int ccw(Point p0,Point p1,Point p2){

	Vector a = p1 - p0;
	Vector b = p2 - p0;

	if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
	if(cross(a,b) < -EPS)return CLOCKWISE;
	if(dot(a,b) < -EPS)return ONLINE_BACK;
	if(a.norm() < b.norm())return ONLINE_FRONT;

	return ON_SEGMENT;
}
int func(long double x1,long double y1,long double x2, long double y2, long double xp, long double yp){
	long double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}


//★★直線ではなく、線分の交差判定★★
bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}

Point calc_minus(Point a,Point b){
    Point ret;

    ret.x = a.x-b.x;
    ret.y = a.y-b.y;

    return ret;
}

long double calc_len(Vector a){
    return sqrt(a.x*a.x+a.y*a.y);
}

//線分ではなく直線と点の距離
long double getDistanceLP(Line l,Point p){
    return fabs(cross(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0]))/calc_len(calc_minus(l.p[1],l.p[0])));
}

//点と線分の距離
long double getDistanceSP(Line l,Point p){
	if(dot(calc_minus(l.p[1],l.p[0]),calc_minus(p,l.p[0])) < 0.0)return calc_len(calc_minus(p,l.p[0]));
	if(dot(calc_minus(l.p[0],l.p[1]),calc_minus(p,l.p[1])) < 0.0)return calc_len(calc_minus(p,l.p[1]));
	return getDistanceLP(l,p);
}

//線分と線分の距離
long double getDistance(Line A,Line B){
	if(is_Cross(A,B))return 0.0;
	return min(min(getDistanceSP(A,B.p[0]),getDistanceSP(A,B.p[1])),
			min(getDistanceSP(B,A.p[0]),getDistanceSP(B,A.p[1])));
}


//交点を求める関数
Point calc_Cross_Point(long double x1,long double x2,long double x3,long double x4,long double y1,long double y2,long double y3,long double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(fabs(x1-x2) > EPS){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

Point calc_Cross_Point(Line A,Line B){

	long double MULT = 100; //EPSのままだと誤差が出る

	if(getDistanceSP(B,A.p[0]) < EPS*MULT){

		return A.p[0];

	}else if(getDistanceSP(B,A.p[1]) < EPS*MULT){

		return A.p[1];

	}else if(getDistanceSP(A,B.p[0]) < EPS*MULT){

		return B.p[0];

	}else if(getDistanceSP(A,B.p[1]) < EPS*MULT){

		return B.p[1];
	}

	return calc_Cross_Point(A.p[0],A.p[1],B.p[0],B.p[1]);
}

long double calc_S(Polygon g){

	int N = g.size();
	long double ret = 0;

	for(int i = 0; i < g.size(); i++){
		ret += cross(g[i],g[(i+1)%N]);
	}
	return ret/2.0;
}

/*点moveをbaseを中心にradラジアン回転させる
rad > 0なら反時計回り、rad < 0なら時計周り
*/
Point rotate(Point base,Point move,long double rad){

	Point ret;
	move = move-base;

	ret.x = move.x*cos(rad)-move.y*sin(rad);
	ret.y = move.x*sin(rad)+move.y*cos(rad);

	ret = ret+base;

	return ret;
}

//2つのvectorがなすラジアンを求める関数
long double calc_rad(Vector vec1,Vector vec2){

	long double tmp = dot(vec1,vec2)/(abs(vec1)*abs(vec2));

	if(fabs(tmp+1.0) < EPS){

		return M_PI;
	}

	if(fabs(tmp-1.0) < EPS){

		return  0.0;
	}

	return acos(dot(vec1,vec2)/(abs(vec1)*abs(vec2)));
}

//3点がなすラジアンを求める関数(ccw(base,a,b) == CCW)
long double calc_rad(Point base,Point a,Point b){

	Vector vec1 = b-base;
	Vector vec2 = a-base;

	return calc_rad(vec1,vec2);
}

long double calc_slope(Line A){

	if(fabs(A.p[0].x-A.p[1].x) < EPS){

		return DBL_MAX;

	}else if(fabs(A.p[0].y-A.p[1].y) < EPS){

		return 0;

	}else{

		return (A.p[1].y-A.p[0].y)/(A.p[1].x-A.p[0].x);
	}
}

//線分をp[1]方向へ伸ばす
Line make_longer(Line arg_line){

	Line ret;
	ret.p[0] = arg_line.p[0];

	//p[1]方向へ直線を伸ばす
	if(fabs(arg_line.p[0].x-arg_line.p[1].x) < EPS){ //垂直

		if(arg_line.p[0].y > arg_line.p[1].y){

			ret.p[1] = Point(arg_line.p[0].x,arg_line.p[0].y-NUM);

		}else{

			ret.p[1] = Point(arg_line.p[0].x,arg_line.p[0].y+NUM);
		}

	}else if(fabs(arg_line.p[0].y-arg_line.p[1].y) < EPS){

		if(arg_line.p[0].x > arg_line.p[1].x){

			ret.p[1] = Point(arg_line.p[0].x-NUM,arg_line.p[0].y);

		}else{

			ret.p[1] = Point(arg_line.p[0].x+NUM,arg_line.p[0].y);
		}

	}else{

		long double work_slope = calc_slope(arg_line);

		if(arg_line.p[0].x > arg_line.p[1].x){

			ret.p[1] = Point(arg_line.p[0].x-NUM,arg_line.p[0].y-NUM*work_slope);

		}else{

			ret.p[1] = Point(arg_line.p[0].x+NUM,arg_line.p[0].y+NUM*work_slope);
		}
	}

	return ret;
}

bool DEBUG = false;

int main(){

	scanf("%d",&N);

	long double x,y;

	for(int i = 0; i < N; i++){

		scanf("%Lf %Lf",&x,&y);
		POLY.push_back(Point(x,y));
	}

	long double S = calc_S(POLY);
	long double half_S = S/2;

	for(int i = 0; i < N; i++){

		line[i].p[0] = POLY[i];
		line[i].p[1] = POLY[(i+1)%N];
	}

	long double minimum = BIG_NUM,maximum = -BIG_NUM;


	for(int base = 0; base < N; base++){

		int toimen,toimen_next;
		int base_next = (base+1)%N;

		long double tmp_S = 0;

		int pre = (base+1)%N;
		int next = (base+2)%N;

		long double last_add;

		bool just_FLG = false;

		while(true){

			last_add = cross(POLY[pre]-POLY[base],POLY[next]-POLY[base])/2;
			tmp_S += last_add;

			if(fabs(tmp_S-half_S) < EPS){ //ちょうど半分

				just_FLG = true;

				if(DEBUG){

					printf("@@@@@@@@ちょうど半分@@@@@@@@\n");
				}

				long double tmp_dist = calc_dist(POLY[base],POLY[next]);

				maximum = max(maximum,tmp_dist);
				minimum = min(minimum,tmp_dist);

				toimen = next;
				toimen_next = (next+1)%N;

				break;

			}else if(tmp_S > half_S+EPS){

				toimen = pre;
				toimen_next = next;

				break;
			}

			pre = next;
			next = (next+1)%N;
		}


		if(tmp_S > half_S+EPS){

			long double calc_S = tmp_S-last_add;
			long double diff = half_S-calc_S;

			long double bottom_len = calc_dist(POLY[toimen_next],POLY[toimen]);
			long double tmp_mult = (diff/last_add)*bottom_len;

			Vector tmp_vec = POLY[toimen_next]-POLY[toimen];
			tmp_vec = tmp_vec/abs(tmp_vec); //単位ベクトル

			Point tmp_p = POLY[toimen]+tmp_vec*tmp_mult; //線分base-tmp_pがポリゴンの面積を二等分する

			long double tmp_dist = calc_dist(POLY[base],tmp_p);

			if(DEBUG){

				//printf("half_Sとの差\n");
				//printf("%.12lf\n",fabs(half_S-(calc_S+last_add*(tmp_mult/tmp_dist))));
			}

			maximum = max(maximum,tmp_dist);
			minimum = min(minimum,tmp_dist);
		}

		if(DEBUG){

			printf("\nbase:%d base_next:%d toi:%d toi_next:%d\n",base,base_next,toimen,toimen_next);
			printf("tmp_S-half_S:%.10Lf\n",tmp_S-half_S);
		}


		Line base_line = make_longer(Line(POLY[base],POLY[base_next]));
		Line toimen_line = make_longer(Line(POLY[toimen_next],POLY[toimen]));

		long double base_slope = calc_slope(base_line);
		long double toimen_slope = calc_slope(toimen_line);

		if(DEBUG){

			printf("toimen:");
			POLY[toimen].debug();
			printf("toi_next");
			POLY[toimen_next].debug();

			//printf("base_slope:%.3lf toi_slope:%.3lf\n",base_slope,toimen_slope);
		}

		Line corner_bisector; //角の二等分線

		long double rest_S = S-tmp_S;

		if(DEBUG){

			//printf("restS:%.3lf\n",rest_S);
		}

		bool is_exception = false;
		Type exception_type;

		if(fabs(base_slope-toimen_slope) < EPS){ //★★★★★例外ケース★★★★★

			//if(just_FLG)continue;

			//printf("minimum:%.12Lfでchmin\n",fabs(POLY[base].x-POLY[toimen].x));
			minimum = min(minimum,getDistance(base_line,toimen_line));
			continue;

			is_exception = true;

			double L,R;

			if(fabs(base_slope-DBL_MAX) < EPS){

				exception_type = Vertical;
				double min_1 = min(POLY[base].y,POLY[base+1].y);
				double max_1 = max(POLY[base].y,POLY[base+1].y);

				double min_2 = min(POLY[toimen].y,POLY[toimen_next].y);
				double max_2 = max(POLY[toimen].y,POLY[toimen_next].y);

				L = max(min_1,min_2);
				R = min(max_1,max_2);

				if(L > R)continue;

			}else{

				exception_type = Horizon;

				double min_1 = min(POLY[base].x,POLY[base+1].x);
				double max_1 = max(POLY[base].x,POLY[base+1].x);

				double min_2 = min(POLY[toimen].x,POLY[toimen_next].x);
				double max_2 = max(POLY[toimen].x,POLY[toimen_next].x);

				L = max(min_1,min_2);
				R = min(max_1,max_2);

				if(L > R)continue;

				printf("minimum:%.12Lfでchmin\n",fabs(POLY[base].y-POLY[toimen].y));
				minimum = min(minimum,fabs(POLY[base].y-POLY[toimen].y));
			}

			continue;

		}else{

			if(!is_Cross(base_line,toimen_line)){ //■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■逆処理■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

				if(DEBUG){
					printf("★base_lineとtoimen_lineが交差しない★\n");
					printf("base_line\n");
					base_line.outPut();
					printf("toimen\n");
					toimen_line.outPut();
				}

				//逆方向に伸ばす
				base_line = make_longer(Line(POLY[base_next],POLY[base]));
				toimen_line = make_longer(Line(POLY[toimen],POLY[toimen_next]));

				if(!is_Cross(base_line,toimen_line)){

					printf("★revでも非交差 NUMが小さい★\n");


					return 0;
				}

				Point cross_p = calc_Cross_Point(base_line,toimen_line);
				long double tmp_rad = calc_rad(cross_p,POLY[base_next],POLY[toimen]);

				Point work_p = rotate(cross_p,POLY[base_next],tmp_rad/2); //角の二等分線の計算用

				corner_bisector = make_longer(Line(cross_p,work_p)); //角の二等分線

				Point temae = calc_Cross_Point(corner_bisector,Line(POLY[toimen_next],POLY[base]));
				Point oku = calc_Cross_Point(corner_bisector,Line(POLY[base_next],POLY[toimen]));

				if(DEBUG){

									printf("手前");
									temae.debug();
									printf("置く");
									oku.debug();
								}


				Vector vec = oku-temae;
				long double R = abs(vec);

				vec = vec/abs(vec); //単位ベクトルにする

				long double L = 0;

				long double SLOPE;
				Type type;

				if(fabs(corner_bisector.p[0].x-corner_bisector.p[1].x) < EPS){ //角の二等分線が垂直

					type = Horizon;

				}else if(fabs(corner_bisector.p[0].y-corner_bisector.p[1].y) < EPS){ //角の二等分線が水平

					type = Vertical;
				}else{

					type = Normal;
					SLOPE = -1.0/calc_slope(corner_bisector);
				}


				//面積を半分にする地点を三分探索する
				for(int loop = 0; loop < 100; loop++){

					if(fabs(L-R) < EPS)break;

					long double mid1 = (2.0*L+R)/3.0;
					long double mid2 = (1.0*L+2.0*R)/3.0;

					vector<Point> tmp_P;
					tmp_P.push_back(temae+vec*mid1);
					tmp_P.push_back(temae+vec*mid2);

					long double diff_1,diff_2;

					for(int a = 0; a < tmp_P.size(); a++){

						Line div_line;

						if(type == Horizon){

							div_line = Line(Point(tmp_P[a].x-NUM,tmp_P[a].y),Point(tmp_P[a].x+NUM,tmp_P[a].y));

						}else if(type == Vertical){

							div_line = Line(Point(tmp_P[a].x,tmp_P[a].y-NUM),Point(tmp_P[a].x,tmp_P[a].y+NUM));

						}else{

							div_line.p[0] = Point(tmp_P[a].x-NUM,tmp_P[a].y-NUM*SLOPE);
							div_line.p[1] = Point(tmp_P[a].x+NUM,tmp_P[a].y+NUM*SLOPE);
						}

						Point cross_1 = calc_Cross_Point(base_line,div_line);
						if(isnan(cross_1.x)){
							printf("NAN L:%.15Lf R:%.15Lf\n",L,R);
							return 0;
						}
						Point cross_2 = calc_Cross_Point(toimen_line,div_line);
						if(isnan(cross_2.x)){
							printf("NAN L:%.15Lf R:%.15Lf\n",L,R);
							return 0;
						}

						Polygon add_poly;
						add_poly.push_back(POLY[base]);
						add_poly.push_back(cross_1);
						add_poly.push_back(cross_2);
						add_poly.push_back(POLY[toimen_next]);

						long double add_S = calc_S(add_poly);

						if(a == 0){

							diff_1 = fabs(half_S-(rest_S+add_S));
						}else{

							diff_2 = fabs(half_S-(rest_S+add_S));
						}
					}

					if(diff_1 < diff_2){

						R = mid2;
					}else{

						L = mid1;
					}
				}

				Point on_P = temae+vec*((L+R)/2);

				Line final_line;

				if(type == Horizon){

					final_line = Line(Point(on_P.x-NUM,on_P.y),Point(on_P.x+NUM,on_P.y));

				}else if(type == Vertical){

					final_line = Line(Point(on_P.x,on_P.y-NUM),Point(on_P.x,on_P.y+NUM));

				}else{

					final_line.p[0] = Point(on_P.x-NUM,on_P.y-NUM*SLOPE);
					final_line.p[1] = Point(on_P.x+NUM,on_P.y+NUM*SLOPE);
				}

				Point final_1 = calc_Cross_Point(base_line,final_line);
				Point final_2 = calc_Cross_Point(toimen_line,final_line);

				long double final_dist = calc_dist(final_1,final_2);

				minimum = min(minimum,final_dist);


				continue;
			} //■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■逆処理■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

			Point cross_p = calc_Cross_Point(base_line,toimen_line);
			long double tmp_rad = calc_rad(cross_p,POLY[toimen_next],POLY[base]);

			Point work_p = rotate(cross_p,POLY[toimen_next],tmp_rad/2); //角の二等分線の計算用

			Vector tmp_vec = work_p-cross_p;
			corner_bisector = Line(cross_p,cross_p+tmp_vec*NUM); //角の二等分線

			if(DEBUG){

				printf("角の二等分線\n");
				corner_bisector.outPut();
			}

		}

		Point temae = calc_Cross_Point(corner_bisector,Line(POLY[base_next],POLY[toimen]));
		Point oku = calc_Cross_Point(corner_bisector,Line(POLY[base],POLY[toimen_next]));

		if(DEBUG){

					printf("手前");
					temae.debug();
					printf("置く");
					oku.debug();
				}


		Vector vec = temae-oku;
		long double R = abs(vec);

		vec = vec/abs(vec); //単位ベクトルにする

		long double L = 0;

		long double SLOPE;
		Type type;

		if(fabs(corner_bisector.p[0].x-corner_bisector.p[1].x) < EPS){ //角の二等分線が垂直

			type = Horizon;

		}else if(fabs(corner_bisector.p[0].y-corner_bisector.p[1].y) < EPS){ //角の二等分線が水平

			type = Vertical;
		}else{

			type = Normal;
			SLOPE = -1.0/calc_slope(corner_bisector);
		}

		long double add_S;
		//面積を半分にする地点を散文探索する
		for(int loop = 0; loop < 100; loop++){

			if(fabs(L-R) < EPS)break;

			long double mid1 = (2.0*L+R)/3.0;
			long double mid2 = (1.0*L+2.0*R)/3.0;

			vector<Point> tmp_P;
			tmp_P.push_back(oku+vec*mid1);
			tmp_P.push_back(oku+vec*mid2);

			long double diff_1,diff_2;

			for(int a = 0; a < tmp_P.size(); a++){

				Line div_line;

				if(type == Horizon){

					div_line = Line(Point(tmp_P[a].x-NUM,tmp_P[a].y),Point(tmp_P[a].x+NUM,tmp_P[a].y));

				}else if(type == Vertical){

					div_line = Line(Point(tmp_P[a].x,tmp_P[a].y-NUM),Point(tmp_P[a].x,tmp_P[a].y+NUM));

				}else{

					div_line.p[0] = Point(tmp_P[a].x-NUM,tmp_P[a].y-NUM*SLOPE);
					div_line.p[1] = Point(tmp_P[a].x+NUM,tmp_P[a].y+NUM*SLOPE);
				}

				Point cross_1 = calc_Cross_Point(base_line,div_line);
				Point cross_2 = calc_Cross_Point(toimen_line,div_line);
				if(isnan(cross_1.x)){
					printf("NAN L:%.15Lf R:%.15Lf\n",L,R);
					return 0;
				}
				if(isnan(cross_2.x)){
					printf("NAN L:%.15Lf R:%.15Lf\n",L,R);
					return 0;
				}


				Polygon add_poly;
				add_poly.push_back(POLY[base]);
				add_poly.push_back(cross_1);
				add_poly.push_back(cross_2);
				add_poly.push_back(POLY[toimen_next]);

				add_S = calc_S(add_poly);

				if(a == 0){

					diff_1 = fabs(half_S-(rest_S+add_S));
				}else{

					diff_2 = fabs(half_S-(rest_S+add_S));
				}
			}

			if(diff_1 < diff_2){

				R = mid2;
			}else{

				L = mid1;
			}
		}

		if(DEBUG){

			printf("haf_Sとの差");
			printf("%.12Lf\n",fabs(half_S-(rest_S+add_S)));
		}

		Point on_P = oku+vec*((L+R)/2);

		Line final_line;

		if(type == Horizon){

			final_line = Line(Point(on_P.x-NUM,on_P.y),Point(on_P.x+NUM,on_P.y));

		}else if(type == Vertical){

			final_line = Line(Point(on_P.x,on_P.y-NUM),Point(on_P.x,on_P.y+NUM));

		}else{

			final_line.p[0] = Point(on_P.x-NUM,on_P.y-NUM*SLOPE);
			final_line.p[1] = Point(on_P.x+NUM,on_P.y+NUM*SLOPE);
		}

		Point final_1 = calc_Cross_Point(base_line,final_line);
		Point final_2 = calc_Cross_Point(toimen_line,final_line);

		double deb_slope = calc_slope(Line(final_1,final_2));


		long double final_dist = calc_dist(final_1,final_2);

		minimum = min(minimum,final_dist);
	}



	printf("%.10Lf\n",minimum);
	printf("%.10Lf\n",maximum);


	return 0;
}
accuracy: 0.3924050632911392
time_ms: 160
memory_kb: 3872
final_rank: 18

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
#include <array>
using namespace std;
const double EPS = 1e-8;
const double INF = 1e12;
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b){ at(0)=a; at(1)=b; }
    L(){}
};
namespace std{
    bool operator < (const P& a, const P& b){
        return !EQ(a.X,b.X) ? a.X<b.X : a.Y+EPS<b.Y;
    }
    bool operator == (const P& a, const P& b){
        return abs(a-b) < EPS;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1; //ccw
    if(cross(b,c) < -EPS) return -1; //cw
    if(dot(b,c) < -EPS) return +2; //c-a-b
    if(abs(c)-abs(b) > EPS) return -2; //a-b-c
    return 0; //a-c-b
}
P unit(const P &p){
    return p/abs(p);
}

double distanceLP(const L &l, const P &p) {
    return abs(cross(l[1]-l[0], p-l[0])) /abs(l[1]-l[0]);
}
P crosspointLL(const L &l, const L &m) {
  double A = cross(l[1]-l[0], m[1]-m[0]);
  double B = cross(l[1]-l[0], l[1]-m[0]);
  return m[0] + B/A *(m[1]-m[0]);
}
double getarea(const VP &poly){
    double ret = 0;
    for (int i=0; i<(int)poly.size(); i++){ 
        ret += cross(poly[i], poly[(i+1)%poly.size()]);
    }
    return ret*0.5;
}
double gettriarea(P a, P b, P c){
    return (cross(a,b) +cross(b,c) +cross(c,a))*0.5;
}
VP convex_cut(const VP& p, const L& l){
    VP ret;
    int n = p.size();
    for(int i=0; i<n; i++){
        P curr = p[i];
        P next = p[(i+1)%n];
        if(ccw(l[0], l[1], curr) != -1) ret.push_back(curr);
        if(ccw(l[0], l[1], curr) *ccw(l[0], l[1], next) == -1){
            ret.push_back(crosspointLL(L(curr, next), l));
        }
    }
    return ret;
}

vector<L> split_to_lines(VP &p){
    int n = p.size();
    double halfarea = getarea(p)/2;
    vector<VP> cps(n);
    for(int i=0; i<n; i++){
        double currarea = 0;
        int opp;
        for(int j=2; j<n; j++){
            double tmparea = gettriarea(p[i], p[(i+j-1)%n], p[(i+j)%n]);
            if(currarea +tmparea > halfarea){
                opp = (i+j-1)%n;
                break;
            }
            currarea += tmparea;
        }
        double remarea = halfarea -currarea;
        double h = distanceLP(L(p[opp], p[(opp+1)%n]), p[i]);
        cps[opp].push_back(p[opp] +2*remarea/h *unit(p[(opp+1)%n] -p[opp]));
    }
    vector<L> ret;
    for(int i=0; i<n; i++){
        cps[i].push_back(p[i]);
        cps[i].push_back(p[(i+1)%n]);
        sort(cps[i].begin(), cps[i].end());
        cps[i].erase(unique(cps[i].begin(), cps[i].end()), cps[i].end());
        if(cps[i][0] != p[i]){
            reverse(cps[i].begin(), cps[i].end());
        }
        for(int j=0; j<(int)cps[i].size()-1; j++){
            ret.emplace_back(cps[i][j], cps[i][j+1]);
        }
    }
    return ret;
}

pair<double, double> minmax_cut(VP &p){
    vector<L> lines = split_to_lines(p);
    int n = lines.size();
    double halfarea = getarea(p)/2;
    double ansmin = INF;
    double ansmax = 0;
    for(int i=0; i<n/2; i++){
        L s = lines[i];
        L t = lines[(i+n/2)%n];
        ansmax = max(ansmax, max(abs(t[0]-s[0]), abs(t[1]-s[1])));
        double remarea = halfarea -getarea(convex_cut(p, L(t[0], s[1])));
        P lb = s[0];
        P ub = s[1];
        for(int r=0; r<100; r++){
            P mid[2];
            mid[0] = (lb+lb+ub) /3.0;
            mid[1] = (lb+ub+ub) /3.0;
            double len[2];
            for(int d=0; d<2; d++){
                double h = distanceLP(L(t[0], t[1]), mid[d]);
                double l = 2*(remarea -gettriarea(mid[d], s[1], t[0])) /h;
                len[d] = abs(mid[d] -(t[0] +l*unit(t[1]-t[0])));
            }
            if(len[0] < len[1]){
                ub = mid[1];
            }else{
                lb = mid[0];
            }
            ansmin = min(ansmin, len[0]);
        }
    }
    return make_pair(ansmin, ansmax);
}

int main(){
    int n;
    cin >> n;
    VP p(n);
    for(int i=0; i<n; i++){
        int x,y;
        cin >> x >> y;
        p[i] = P(x, y);
    }
    auto ans = minmax_cut(p);
    cout << fixed << setprecision(10);
    cout << ans.first << endl;
    cout << ans.second << endl;
    return 0;
}
accuracy: 1
time_ms: 820
memory_kb: 4076
final_rank: 8

code_snippet: #include<bits/stdc++.h>
#define inf 1<<29
#define linf (1e16)
#define eps (1e-8)
#define Eps (1e-12)
#define mod 1000000007
#define pi acos(-1.0)
#define phi (1.0+sqrt(5.0))/2.0
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define pld(a) printf("%.10Lf\n",(ld)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define Unique(v) v.erase(unique(all(v)),v.end())
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long double ld;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<int,double> pid;
typedef pair<double,int> pdi;
typedef pair<double,double> pdd;
typedef vector<int> vi;
typedef vector<pii> vpi;
#define track() cout<<"AAAAAAAAA"<<endl;

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}

  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(double k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ return equals(x,p.x) ? y-p.y<-eps : x-p.x<-eps; }
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}

  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;

class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;

double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}

double Area(Polygon p){
  double area=0.0;
  int n=p.size();
  for(int i=0;i<n;i++)area+=cross(p[i],p[(i+1)%n]);
  return area/2.0;
}

double getDistanceLP(Line l,Point p){
  return abs(cross(l.p2-l.p1,p-l.p1)/abs(l.p2-l.p1));
}

bool onLine(Line L,Point p){ return getDistanceLP(L,p)<eps; }
bool onSegment(Segment s,Point p){
  if(!onLine(s,p))return false;
  if(dot(s.p2-s.p1,p-s.p1)<-eps)return false;
  if(dot(s.p1-s.p2,p-s.p2)<-eps)return false;
  return true;
}

typedef pair<Point,Point> pp;

int n,m;
Polygon P;
vector<Point> D;
vector<pp> V;
double area;

Point cal(Point base,int i){
  double sum = 0.0,t = 0.0;
  while(1){
    t = cross(P[i]-base,P[(i+1)%n]-base)/2.0;
    if(area<sum+t)break;
    i = (i+1)%n;
    sum+=t;
  }
  double a = (area-sum)/t;
  Vector v = P[(i+1)%n]-P[i];
  return P[i]+v*a;
}

Point Search(Point base,Point a,Point b,double X){
  Vector v = b-a;
  v = v/abs(b-a);
  double L = 0.0, R = abs(b-a), M;
  FOR(i,0,50){
    M = (L+R)/2.0;
    Point c = a+v*M;
    if(X>cross(a-base,c-base)/2.0)L = M;
    else R = M;
  }
  return a+v*M;
}

double Minimum(){
  double res = inf;
  FOR(i,0,m){
    int j = (i+1)%m;
    Vector v = V[j].f-V[i].f;
    double dis = abs(v);
    double X = cross(V[j].f-V[i].f,V[i].s-V[i].f)/2.0;
    v = v/dis;
    double L=0.0,R=dis;
    FOR(k,0,50){
      double m1=(L*phi+R)/(1.0+phi);
      double m2=(L+R*phi)/(1.0+phi);
      Point p1 = V[i].f+v*m1;
      Point p2 = V[i].f+v*m2;
      double y1 = cross(V[j].f-p1,V[i].s-p1)/2.0;
      double y2 = cross(V[j].f-p2,V[i].s-p2)/2.0;
      Point p3 = Search(p1,V[i].s,V[j].s,X-y1);
      Point p4 = Search(p2,V[i].s,V[j].s,X-y2);
      double res1 = abs(p1-p3);
      double res2 = abs(p2-p4);
      if(res1<res2)R=m2;
      else L=m1;
      res = min(res,res1);
    }
  }
  return res;
}

double Maximum(){
  double res = 0.0;
  FOR(i,0,V.size())res = max(res,abs(V[i].f-V[i].s));
  return res;
}

void solve(){
  area = Area(P)/2.0;
  FOR(i,0,n)D.pb(cal(P[i],(i+1)%n));
  FOR(i,0,n){
    Segment S = Segment(P[i],P[(i+1)%n]);
    vector<pair<double,pp> > tmp;
    V.pb(mp(P[i],D[i]));
    FOR(j,0,n){
      if(D[j]==P[i])continue;
      if(D[j]==P[(i+1)%n])continue;
      if(onSegment(S,D[j]))tmp.pb(mp(abs(P[i]-D[j]),mp(D[j],P[j])));
    }
    sort(all(tmp));
    FOR(j,0,tmp.size())V.pb(tmp[j].s);
  }
  m = V.size();
  pd(Minimum());
  pd(Maximum());
  return;
}

int main()
{
  cin>>n;
  P.resize(n);
  FOR(i,0,n)cin>>P[i].x>>P[i].y;
  solve();
  return 0;
}
accuracy: 1
time_ms: 890
memory_kb: 3704
final_rank: 7