Brief description:
给定平面上的一组点集 ,对于每个询问,输出一个新的点,查询所有距离她最近的点的编号。
(点集规模 N <= 100000, 询问次数 M <= 10000)
Analysis:
.. .
Naive:
const int N = 100009;
Po P[N], cur;
int n, m;
int main() {
//freopen("in.txt", "r", stdin);
REP_C(i, _RD(n)){
scanf("%lf %lf", &P[i].x, &P[i].y);
}
DO_C(RD()){
scanf("%lf %lf", &cur.x, &cur.y);
DB d = INF; REP(i, n) checkMin(d, dist_sqr(cur, P[i]));
REP(i, n) if (d == dist_sqr(cur, P[i]))
printf("%d ", i + 1);
puts("");
}
}
….
Hash:
Data Structure:
...
int random(int l, int r){
return rand() % (r - l + 1) + l;
}
struct Rec: Po{
int id;
};
const int N = 100009;
const int NN = N;
/*
|
1|0
-----
3|2
|
*/
Rec node[NN]; DB xl[NN], xr[NN], yl[NN], yr[NN]; int c[NN][4], root, total;
// Point Quadtree .. .
Rec P[N], temp; Po cur; DB d; VI L;
int n, m;
inline int Dir(Po a, Po b){
return a.x < b.x ? (a.y < b.y ? 3 : 1) : (a.y < b.y ? 2 : 0);
}
inline int Rev(int dir){
return dir ^ 3;
}
void Insert(int &now = root){
if (!now) now = ++total, node[now] = temp;
else Insert(c[now][Dir(temp, node[now])]);
}
void Cut(int now, int parent){
if (!now) return;
if (node[now].x < node[parent].x) xl[now] = xl[parent], xr[now] = node[parent].x; else xl[now] = node[parent].x, xr[now] = xr[parent];
if (node[now].y < node[parent].y) yl[now] = yl[parent], yr[now] = node[parent].y; else yl[now] = node[parent].y, yr[now] = yr[parent];
REP(i, 4) Cut(c[now][i], now);
}
void Update(Rec item){
DB dd = dist_sqr(cur, item);
if (sgn(dd, d) <= 0){
if (sgn(dd, d) == -1) d = dd, CLR(L);
L.PB(item.id);
}
}
void Find(int now = root){
if (!now) return;
if (xl[now] <= cur.x && cur.x <= xr[now]){
if (cur.y <= yl[now]) if (sgn(d, sqr(yl[now] - cur.y)) < 0) return;
if (yr[now] <= cur.y) if (sgn(d, sqr(cur.y - yr[now])) < 0) return;
}
else if (yl[now] <= cur.y && cur.y <= yr[now]){
if (cur.x <= xl[now]) if (sgn(d, sqr(xl[now] - cur.x)) < 0) return;
if (xr[now] <= cur.x) if (sgn(d, sqr(cur.x - xr[now])) < 0) return;
}
else if (sgn(d, min(sqr(xl[now] - cur.x), sqr(xr[now] - cur.x)) + min(sqr(yl[now] - cur.y), sqr(yr[now] - cur.y))) < 0) return;
int dir = Dir(cur, node[now]);
Find(c[now][dir]), Update(node[now]);
if (dir == 0 || dir == 3) Find(c[now][1]), Find(c[now][2]);
else if (dir == 1 || dir == 2) Find(c[now][0]), Find(c[now][3]);
}
int main() {
//freopen("in.txt", "r", stdin);
REP_C(i, _RD(n)){
scanf("%lf %lf", &P[i].x, &P[i].y);
P[i].id = i + 1;
}
srand((unsigned)time(NULL)); REP(i, n) swap(P[i], P[random(i, n - 1)]);
REP(i, n) temp = P[i], Insert();
xl[root] = yl[root] = -10000, xr[root] = yr[root] = 10000;
REP(i, 4) Cut(c[root][i], root);
DO_C(RD()){
scanf("%lf %lf", &cur.x, &cur.y), CLR(L), d = INF; Find();
SRT(L); REP(i, SZ(L) - 1) printf("%d ", L[i]);
printf("%d\n", L[SZ(L)-1]);
}
}
...
int random(int l, int r){
return rand() % (r - l + 1) + l;
}
struct Rec: Po{
int id;
};
const int N = 100009;
const int NN = N;
Rec node[NN]; DB xl[NN], xr[NN], yl[NN], yr[NN];
int c[NN][2], root, total;
// 2-d tree .. .
Rec P[N], temp; Po cur; DB d; VI L;
int n, m;
inline int Dir(int level, Po a, Po b){
if (level&1) return a.x < b.x ? 0 : 1;
else return a.y < b.y ? 0 : 1;
}
inline int Rev(int dir){
return dir ^ 1;
}
void Insert(int &now = root, int level = 0){
if (!now) now = ++total, node[now] = temp;
else Insert(c[now][Dir(level, temp, node[now])], level + 1);
}
void Cut(int now, int parent, int level){
if (!now) return;
if (level&1){
if (node[now].x < node[parent].x) xl[now] = xl[parent], xr[now] = node[parent].x; else xl[now] = node[parent].x, xr[now] = xr[parent];
yl[now] = yl[parent], yr[now] = yr[parent];
}
else {
if (node[now].y < node[parent].y) yl[now] = yl[parent], yr[now] = node[parent].y; else yl[now] = node[parent].y, yr[now] = yr[parent];
xl[now] = xl[parent], xr[now] = xr[parent];
}
REP(i, 2) Cut(c[now][i], now, level + 1);
}
void Update(Rec item){
DB dd = dist_sqr(cur, item);
if (sgn(dd, d) <= 0){
if (sgn(dd, d) == -1) d = dd, CLR(L);
L.PB(item.id);
}
}
void Find(int now = root, int level = 0){
if (!now || sgn(d, ((xl[now] <= cur.x && cur.x <= xr[now]) ? 0. : min(sqr(cur.x - xl[now]), sqr(cur.x - xr[now]))) + ((yl[now] <= cur.y && cur.y <= yr[now]) ? 0. : min(sqr(cur.y - yl[now]), sqr(cur.y - yr[now])))) < 0) return;
int dir = Dir(level, cur, node[now]); Find(c[now][dir], level + 1), Update(node[now]); Find(c[now][Rev(dir)], level + 1);
}
int main() {
//freopen("in.txt", "r", stdin);
REP_C(i, _RD(n)){
scanf("%lf %lf", &P[i].x, &P[i].y);
P[i].id = i + 1;
}
//srand((unsigned)time(NULL)); REP(i, n) swap(P[i], P[random(i, n - 1)]);
REP(i, n) temp = P[i], Insert();
xl[root] = yl[root] = -10000, xr[root] = yr[root] = 10000;
REP(i, 2) Cut(c[root][i], root, 0);
DO_C(RD()){
scanf("%lf %lf", &cur.x, &cur.y), CLR(L), d = INF; Find();
SRT(L); REP(i, SZ(L) - 1) printf("%d ", L[i]);
printf("%d\n", L[SZ(L)-1]);
}
}
Vonoir Graph:
Reference:
The Design and Analysis of Spatial Data Structures[Hanan][Samet]
External links:
http://acm.timus.ru/problem.aspx?space=1&num=1369
http://en.wikipedia.org/wiki/Nearest_neighbor_search






Alca
Amber
Belleve Invis
Chensiting123
Edward_mj
Fotile96
Hlworld
Kuangbin
Liyaos
Lwins
LYPenny
Mato 完整版
Mikeni2006
Mzry
Nagatsuki
Neko13
Oneplus
Rukata
Seter
Sevenkplus
Sevenzero
Shirleycrow
Vfleaking
wangzhpp
Watashi
WJMZBMR
Wywcgs
XadillaX
Yangzhe
三途川玉子
About.me
Vijos

kd树。。。
随机增量法能搞过去么。。。 /$:^ ^
/$:T_T 还是要用高端四叉树