由于本人比较菜,所以只写了个旋转坐标系的做法 (Q omega Q)
旋转坐标系的原理很显然,我们考虑到离得最近的两个点,它们的横坐标之差肯定也不会大,离得最远的同理。
但是我们肯定还是不能 naive 地直接去算,为了更好地保证正确性,我们可以随机旋转坐标系。
虽然操作不好会 T ,不过这题确实还是稳过的。
参考代码:
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <ctime>
using namespace std;
const double pi = acos(-1.0);
const int _ = 2e5 + 5;
int n; double mn = 1e18, mx = 0;
struct node { double x, y; } t[_];
int cmp(node a, node b) { return a.x < b.x; }
double dist(node a, node b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); }
void calc(double d) {
d = d / 180.0 * pi;
for (int i = 1; i <= n; ++i) {
double x = t[i].x, y = t[i].y;
t[i].x = x * cos(d) - y * sin(d);
t[i].y = x * sin(d) + y * cos(d);
}
sort(t + 1, t + n + 1, cmp);
for (int i = 1; i <= n; ++i)
for (int j = i + 1; j <= min(i + 10, n); ++j)
mn = min(mn, dist(t[i], t[j]));
for (int i = 1; i <= min(10, n); ++i)
for (int j = max(1, n - 9); j <= n; ++j)
mx = max(mx, dist(t[i], t[j]));
}
int main() {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin), freopen("cpp.out", "w", stdout);
#endif
srand(time(0));
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%lf %lf", &t[i].x, &t[i].y);
calc(0);
calc(rand() % 360);
calc(rand() % 360);
printf("%.5lf %.5lf
", mn, mx);
return 0;
}