#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
const double eps = 1e-12;
// typedef long long ll;
typedef double ll;
typedef pair<ll, ll> PII;
ll read() { // 快速读入
ll res = 0, f = 1; char c = getchar();
while(!isdigit(c)) {
if(c == '-') f = -f;
c = getchar();
}
while(isdigit(c)) res = res * 10 + c - '0', c = getchar();
return res * f;
}
struct Point { // 点结构体
ll x, y, id;
Point(ll x = 0, ll y = 0):x(x), y(y) {}
};
struct Line { // 线结构体
ll k, b, id;
Line(ll k = 0, ll b = 0):k(k), b(b) {}
};
bool operator < (const Line &l1, const Line &l2) { return l1.k != l2.k ? l1.k < l2.k : l1.b < l2.b; }
bool operator < (const Point &p1, const Point &p2) { return p1.x != p2.x ? p1.x < p2.x : p1.y < p2.y; }
Point operator - (const Point &p1, const Point &p2) { return Point(p1.x - p2.x, p1.y - p2.y); }
Point operator + (const Point &p1, const Point &p2) { return Point(p1.x + p2.x, p1.y + p2.y); }
bool operator == (const Point &p1, const Point &p2) { return p1.x == p2.x && p1.y == p2.y; }
ll operator * (const Point &p1, const Point &p2) { return p1.x * p2.y - p1.y * p2.x; }
ll Cross(const Point &p1, const Point &p2, const Point &p3) { return (p1 - p3) * (p2 - p3); } // 叉积--负数表示p3在向量p1p2右侧
bool Is_line(const Point &p1, const Point &p2, const Point &p3) { // p3是否在p1p2直线上
auto t1 = p1 - p2;
auto t2 = p3 - p2;
return t1.x * t2.y == t1.y * t2.x;
}
bool Is_Segment(const Point &p1, const Point &p2, const Point &p3) { // p3是否在p1p2线段上
if(!Is_line(p1, p2, p3)) return false;
return min(p1.x, p2.x) <= p3.x && p3.x <= max(p1.x, p2.x);
}
ll Get_Dis2(const Point &p1, const Point &p2) { // 两点距离的平方
auto t = p1 - p2;
return t.x * t.x + t.y * t.y;
}
Point Get_Intersection(Line &l1, Line &l2) { // 两直线求交,有精度问题,慎用
double x = (l1.b - l2.b) / (l2.k - l1.k);
double y = l1.k * x + l1.b;
return Point(x, y);
}
int n, stk[N], top;
bool used[N];
Point p[N], temp[N];
Line l[N];
double Andrew() { // 求二维凸包(节点编号存在栈中),返回周长
top = 0;
sort(p + 1, p + n + 1);
for(int i = 1; i <= n; i ++) used[i] = false;
for(int i = 1; i <= n; i ++) {
while(top >= 2 && Cross(p[stk[top]], p[i], p[stk[top - 1]]) < 0) used[stk[top --]] = false;
stk[++ top] = i, used[i] = true;
}
used[1] = false;
for(int i = n; i; i --) {
if(used[i]) continue;
while(top >= 2 && Cross(p[stk[top]], p[i], p[stk[top - 1]]) < 0) top--;
stk[++ top] = i;
}
double res = 0;
for(int i = 2; i <= top; i ++)
res += sqrt(Get_Dis2(p[stk[i - 1]], p[stk[i]]));
top --;
return res;
}
double Convex_D() { // 求凸包的直径
double res = 0;
for(int i = 0; i < top; i ++)
temp[i] = p[stk[i + 1]];
for(int i = 0, j = 1; i < top; i ++) {
while(fabs(Cross(temp[i], temp[(i + 1) % top], temp[j])) < fabs(Cross(temp[i], temp[(i + 1) % top], temp[(j + 1) % top]))) j = (j + 1) % top;
res = max(res, sqrt(Get_Dis2(temp[i], temp[j])));
}
return res;
}
double merge(int l, int r) { // 返回平面最近点对的距离 (需要提前排序)
if(l == r) return 1e18;
ll mid = l + r >> 1, mid_x = p[(int)mid].x;
double res = min(merge(l, mid), merge(mid + 1, r));
int k = l, i = l, j = mid + 1;
while(i <= mid && j <= r) {
if(p[i].y < p[j].y) temp[k ++] = p[i ++];
else temp[k ++] = p[j ++];
}
while(i <= mid) temp[k ++] = p[i ++];
while(j <= r) temp[k ++] = p[j ++];
for(int i = l; i <= r; i ++) p[i] = temp[i];
k = l;
for(int i = l; i <= r; i ++)
if(p[i].x >= mid_x - res && p[i].x <= mid_x + res) temp[k ++] = p[i];
for(int i = l; i < k; i ++)
for(int j = i - 1; j >= l && temp[i].y - temp[j].y + eps <= res; j --)
res = min(res, sqrt(Get_Dis2(temp[i], temp[j])));
return res;
}