# K-D Tree 学习笔记

k=1的时候就是一只BST

k>1的话，每一层换一维来分割

## 怎么做？

### 查询

k近邻的话，用个大根堆，一直保持堆中有k个的元素

### 代码实现

bzoj2648 带插入最近邻

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int N = 1e6+5, inf = 1e9;
#define lc t[x].ch[0]
#define rc t[x].ch[1]
#define max0(x) max(x, 0)

int n, m;
int curD = 0;
struct meow {
int d[2];
meow() {}
meow(int x, int y){d[0]=x; d[1]=y;}
bool operator < (const meow &r) const {
return d[curD] < r.d[curD];
}
int calDist(meow &a) {
return abs(d[0] - a.d[0]) + abs(d[1] - a.d[1]);
}
};
meow a[N];
struct node {
int ch[2], x[2], y[2];
meow p;
void update(node &a) {
x[0] = min(x[0], a.x[0]); x[1] = max(x[1], a.x[1]);
y[0] = min(y[0], a.y[0]); y[1] = max(y[1], a.y[1]);
}
void set(meow &a) {
p = a;
x[0] = x[1] = a.d[0];
y[0] = y[1] = a.d[1];
}
int xx = a.d[0], yy = a.d[1];
return max0(x[0] - xx) + max0(xx - x[1]) + max0(y[0] - yy) + max0(yy - y[1]);
}
} t[N];
int root;
int build(int l, int r, int d) {
curD = d;
int x = (l+r)>>1;
nth_element(a+l, a+x, a+r+1);
t[x].set(a[x]);
if(l < x) lc = build(l, x-1, d^1), t[x].update(t[lc]);
if(x < r) rc = build(x+1, r, d^1), t[x].update(t[rc]);
return x;
}
void insert(meow q) {
t[++n].set(q);
for(int x=root, D=0; x; D^=1) {
t[x].update(t[n]);
int &nxt = t[x].ch[q.d[D] >= t[x].p.d[D]];
if(nxt == 0) {
nxt = n;
break;
}
else x = nxt;
}
}

int ans;
void query(int x, meow q) {
int nowDist = t[x].p.calDist(q), d[2];
d[0] = lc ? t[lc].evaDist(q) : inf;
d[1] = rc ? t[rc].evaDist(q) : inf;
int wh = d[1] <= d[0];
ans = min(ans, nowDist);
if(d[wh] < ans) query(t[x].ch[wh], q);
wh ^= 1;
if(d[wh] < ans) query(t[x].ch[wh], q);
}

int main() {
cin >> n >> m;
int c, x, y;
for(int i=1; i<=n; i++) {
scanf("%d %d", &x, &y);
a[i] = meow(x, y);
}
root = build(1, n, 0);
for(int i=1; i<=m; i++) {
scanf("%d %d %d", &c, &x, &y);
if(c == 1) insert(meow(x, y));
else {
ans = inf;
query(root, meow(x, y));
printf("%d\n", ans);
}
}
}

bzoj4520 k远点对

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <ctime>
#include <queue>
using namespace std;
typedef long long ll;
const int N = 1e5+5;
const ll inf = 1e18;
#define lc t[x].ch[0]
#define rc t[x].ch[1]
#define max0(x) max(x, 0)

inline ll sqr(ll x) {return x*x;}

int n, K;
int curD = 0;
struct meow {
ll d[2];
meow() {}
meow(ll x, ll y){d[0]=x; d[1]=y;}
bool operator < (const meow &r) const {
//if(d[curD] == r.d[curD]) return d[curD^1] < r.d[curD^1];
return d[curD] < r.d[curD];
}
ll calDist(meow &a) {
//return abs(d[0] - a.d[0]) + abs(d[1] - a.d[1]);
return sqr(d[0] - a.d[0]) + sqr(d[1] - a.d[1]);
}
};
meow a[N];
struct node {
int ch[2], x[2], y[2];
meow p;
void update(node &a) {
x[0] = min(x[0], a.x[0]);
x[1] = max(x[1], a.x[1]);
y[0] = min(y[0], a.y[0]);
y[1] = max(y[1], a.y[1]);
}
void set(meow &a) {
p = a;
x[0] = x[1] = a.d[0];
y[0] = y[1] = a.d[1];
}
ll evaMaxDist(meow &a) {
ll xx = a.d[0], yy = a.d[1];
return max(sqr(x[0]-xx), sqr(x[1]-xx)) + max(sqr(y[0]-yy), sqr(y[1]-yy));
}
} t[N];
int root;
int build(int l, int r, int d) {
curD = d;
int x = (l+r)>>1;
nth_element(a+l, a+x, a+r+1);
t[x].set(a[x]);
if(l < x) {
lc = build(l, x-1, d^1);
t[x].update(t[lc]);
}
if(x < r) {
rc = build(x+1, r, d^1);
t[x].update(t[rc]);
}
return x;
}

priority_queue<ll, vector<ll>, greater<ll> > ans;
void query(int x, meow q) {
ll nowDist = t[x].p.calDist(q), d[2];
d[0] = lc ? t[lc].evaMaxDist(q) : -inf;
d[1] = rc ? t[rc].evaMaxDist(q) : -inf;
int wh = d[1] >= d[0];
if(nowDist > ans.top()) ans.pop(), ans.push(nowDist);
if(d[wh] > ans.top()) query(t[x].ch[wh], q);
wh ^= 1;
if(d[wh] > ans.top()) query(t[x].ch[wh], q);
}

int main() {
cin >> n >> K; K <<= 1;
int x, y;
for(int i=1; i<=n; i++) {
scanf("%d %d", &x, &y);
a[i] = meow(x, y);
}
root = build(1, n, 0);
for(int j=1; j<=K; j++) ans.push(-inf);
for(int i=1; i<=n; i++) {
query(root, a[i]);
}
cout << ans.top() << endl;
}
posted @ 2019-02-01 19:58 Candy? 阅读(...) 评论(...) 编辑 收藏