首先先将坐标轴旋转,之后二分答案,维护滑窗,前后缀优化判定连通性即可。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 110000;
const double eps = 1e-8;
int n;
double premax[maxn], premin[maxn];
double sufmax[maxn], sufmin[maxn];
struct Point {
double x, y;
void in() {
scanf("%lf%lf", &x, &y);
double tmp = x;
x -= y;
y = tmp + y;
// cout<<x<<" "<<y<<" denug "<<endl;
}
bool operator < (const Point & b) const {
if(x == b.x) return y < b.y;
return x < b.x;
}
} p[maxn];
bool check(double d) {
for(int i = 1, j = 1; i <= n; i++) {
while(p[i].x - p[j].x > d) j++;
double ymax = max(sufmax[i+1], premax[j-1]);
double ymin = min(sufmin[i+1], premin[j-1]);
if(ymax - ymin <= d || ymax == -1e18 || ymin == 1e18)
return 1;
}
return 0;
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++)
p[i].in();
sort(p+1, p+1+n);
premax[0] = sufmax[n+1] = -1e18;
premin[0] = sufmin[n+1] = 1e18;
for(int i = 1; i <= n; i++) {
premax[i] = max(premax[i-1], p[i].y);
premin[i] = min(premin[i-1], p[i].y);
}
for(int i = n; i >= 1; i--) {
sufmax[i] = max(sufmax[i+1], p[i].y);
sufmin[i] = min(sufmin[i+1], p[i].y);
}
double L = 0, R = 1e18, M;
for(int i = 0; i < 100; i++) {
M = (L + R) / 2;
if(check(M)) R = M;
else L = M;
}
printf("%.10f\n", L/2);
return 0;
}