KD-Tree解决空间最短距离的利器
KD-Tree解决空间最短距离的利器
本文作者:Caozhijie
/**************************************************************
Problem: 2648
User: Cardinal
Language: C++
Result: Accepted
Time:14476 ms
Memory:40356 kb
****************************************************************/
#include <cstdio>
#include <cstring>
#include <climits>
#include <iostream>
#include <algorithm>
using namespace std;
#define Min(a, b) ((a)<(b)?(a):(b))
#define Max(a, b) ((a)>(b)?(a):(b))
#define Abs(x) ((x)>0?(x):-(x))
#define N 500010
#define M 500010
int n, m;
struct Point {
int x, y;
Point(int _x = 0, int _y = 0):x(_x),y(_y){}
void set(int _, int __) {
x = _, y = __;
}
}P[N + M];
int Dis(const Point &A, const Point &B) {
return Abs(A.x - B.x) + Abs(A.y - B.y);
}
bool sign;
inline bool cmp(const Point &A, const Point &B) {
if (sign)
return A.x < B.x || (A.x == B.x && A.y < B.y);
else
return A.y < B.y || (A.y == B.y && A.x < B.x);
}
struct Node {
Node *l, *r;
int x[2], y[2];
Point p;
void SetP(const Point &P) {
p = P;
x[0] = x[1] = P.x;
y[0] = y[1] = P.y;
}
int Dis(const Point &p) const {
int res = 0;
if (p.x < x[0] || p.x > x[1])
res += (p.x < x[0]) ? x[0] - p.x : p.x - x[1];
if (p.y < y[0] || p.y > y[1])
res += (p.y < y[0]) ? y[0] - p.y : p.y - y[1];
return res;
}
void up(Node *B) {
x[0] = Min(x[0], B->x[0]);
x[1] = Max(x[1], B->x[1]);
y[0] = Min(y[0], B->y[0]);
y[1] = Max(y[1], B->y[1]);
}
}mem[N + M], *C = mem, Tnull, *null = &Tnull;
Node *Build(int tl, int tr, bool d) {
if (tl > tr)
return null;
int mid = (tl + tr) >> 1;
sign = d;
std::nth_element(P + tl + 1, P + mid + 1, P + tr + 1, cmp);
Node *q = C++;
q->SetP(P[mid]);
q->l = Build(tl, mid - 1, d ^ 1);
q->r = Build(mid + 1, tr, d ^ 1);
if (q->l != null)
q->up(q->l);
if (q->r != null)
q->up(q->r);
return q;
}
#define INF 0x3f3f3f3f
int res;
void Ask(Node *q, const Point &p) {
res = Min(res, Dis(q->p, p));
int DisL = q->l != null ? q->l->Dis(p) : INF;
int DisR = q->r != null ? q->r->Dis(p) : INF;
if (DisL < DisR) {
if (q->l != null)
Ask(q->l, p);
if (DisR < res && q->r != null)
Ask(q->r, p);
}
else {
if (q->r != null)
Ask(q->r, p);
if (DisL < res && q->l != null)
Ask(q->l, p);
}
}
void Insert(Node *root, const Point &p) {
Node *q = C++;
q->l = q->r = null;
q->SetP(p);
sign = 0;
while(1) {
root->up(q);
if (cmp(q->p, root->p)) {
if (root->l == null) {
root->l = q;
break;
}
else
root = root->l;
}
else {
if (root->r == null) {
root->r = q;
break;
}
else
root = root->r;
}
sign ^= 1;
}
}
int main() {
#ifndef ONLINE_JUDGE
//freopen("tt.in", "r", stdin);
//freopen("tt.out", "w", stdout);
#endif
scanf("%d%d", &n, &m);
register int i;
int ope, x, y;
for(i = 1; i <= n; ++i) {
scanf("%d%d", &x, &y);
P[i] = Point(x, y);
}
Node* root = Build(1, n, 0);
while(m--) {
scanf("%d%d%d", &ope, &x, &y);
if (ope == 1)
Insert(root, Point(x, y));
else {
res = INF;
Ask(root, Point(x, y));
printf("%d\n", res);
}
}
return 0;
}