K-D tree
注意得到最大最小值的距离计算函数
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 500010
using namespace std;
int n, D;
void read(int& num){
num = 0;
int f = 1;
char ch = getchar();
for(; ch < '!'; ch = getchar());
if(ch == '-'){
ch = getchar();
f = -1;
}
for(; ch > '!'; ch = getchar())
num = num * 10 + ch - 48;
num *= f;
}
struct Point{
int mn[2], mx[2], d[2], l, r;
int& operator[](int i){return d[i];}
void InState(){
read(d[0]), read(d[1]);
l = r = 0;
}
bool operator<(Point k)const{
return d[D] < k.d[D];
}
}t[maxn << 1];
int ans[maxn];
const int inf = 0x7fffffff;
namespace KDtree{
int root, ans;
Point P;
#define L(p) t[p].l
#define R(p) t[p].r
void update(int p){
for(int i = 0; i < 2; i ++){
t[p].mn[i] = t[p].mx[i] = t[p].d[i];
if(L(p)){
t[p].mn[i] = min(t[p].mn[i], t[L(p)].mn[i]);
t[p].mx[i] = max(t[p].mx[i], t[L(p)].mx[i]);
}
if(R(p)){
t[p].mn[i] = min(t[p].mn[i], t[R(p)].mn[i]);
t[p].mx[i] = max(t[p].mx[i], t[R(p)].mx[i]);
}
}
}
int build(int l, int r, int now){
if(l > r)
return 0;
int mid = l + r >> 1;
D = now;
nth_element(t + l, t + mid, t + r + 1);
L(mid) = build(l, mid - 1, now ^ 1);
R(mid) = build(mid + 1, r, now ^ 1);
update(mid);
return mid;
}
int Abs(int x){return x > 0 ? x : -x;}
int dis(Point k){
int ret = 0;
for(int i = 0; i < 2; i ++)
ret += Abs(k[i] - P[i]);
return ret;
}
int dist_mn(const Point& k){
int ret = 0;
for(int i = 0; i < 2; i ++)
ret += max(P[i] - k.mx[i], k.mn[i] - P[i]);
return ret;
}
int dist_mx(const Point& k){
int ret = 0;
for(int i = 0; i < 2; i ++)
ret += max(k.mx[i] - P[i], P[i] - k.mn[i]);
return ret;
}
void ask_mx(int root, int now){
if(!root)return;
int dl = -inf, dr = -inf;
int d = dis(t[root]);
ans = max(ans, d);
if(L(root))dl = dist_mx(t[L(root)]);
if(R(root))dr = dist_mx(t[R(root)]);
if(dl > dr){
if(dl > ans)ask_mx(L(root), now ^ 1);
if(dr > ans)ask_mx(R(root), now ^ 1);
}
else{
if(dr > ans)ask_mx(R(root), now ^ 1);
if(dl > ans)ask_mx(L(root), now ^ 1);
}
}
void ask_mn(int root, int now){
int dl = inf, dr = inf;
int d = dis(t[root]);
if(d)ans = min(ans, d);
if(L(root))dl = dist_mn(t[L(root)]);
if(R(root))dr = dist_mn(t[R(root)]);
if(dl < dr){
if(dl < ans)ask_mn(L(root), now ^ 1);
if(dr < ans)ask_mn(R(root), now ^ 1);
}
else{
if(dr < ans)ask_mn(R(root), now ^ 1);
if(dl < ans)ask_mn(L(root), now ^ 1);
}
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("1941.in", "r", stdin);
freopen("1941.out", "w", stdout);
#endif
read(n);
for(int i = 1; i <= n; i ++)
t[i].InState();
KDtree:: root = KDtree:: build(1, n, 0);
int ret = inf;
for(int i = 1; i <= n; i ++){
KDtree::P = t[i];
KDtree::ans = 0;
KDtree::ask_mx(KDtree::root, 0);
ans[i] = KDtree::ans;
KDtree::ans = inf;
KDtree::ask_mn(KDtree::root, 0);
ans[i] -= KDtree::ans;
ret = min(ret, ans[i]);
}
printf("%d\n", ret);
return 0;
}