【题意】
给定二维平面上N个不同点。求每个点距离它最近的点的距离平方。
【分析】
模板题。。。KD_tree。
http://baike.baidu.com/view/2249897.htm 百科里说得很明白
【复杂度】
建树:N*lgN;
查询:均摊时间N^0.5 + lgN。
【Mark】
nth_element(),stl提供的在线性时间内找到第k大的数,并且把前k个放在最前面。
http://www.cplusplus.com/reference/algorithm/nth_element/
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<algorithm> 5 6 using namespace std; 7 #define LL long long 8 9 const int maxn = 100010; 10 const LL inf = 1LL<<61; 11 12 struct Point{ 13 LL x[2]; 14 LL dist(const Point &cur){ 15 return (x[0] - cur.x[0]) * (x[0] - cur.x[0]) + (x[1] - cur.x[1])*(x[1] - cur.x[1]); 16 } 17 }p[maxn],q[maxn],tree[maxn]; 18 int n; 19 int vis[maxn]; 20 21 bool cmpx(Point p1, Point p2) 22 { 23 return p1.x[0] < p2.x[0]; 24 } 25 bool cmpy(Point p1, Point p2) 26 { 27 return p1.x[1] < p2.x[1]; 28 } 29 LL ans; 30 31 void build(int l, int r) 32 { 33 if (l > r){ 34 return ; 35 } 36 int mid = (l + r) / 2; 37 LL minX = inf, minY = inf ,maxX = -inf, maxY = -inf; 38 for (int i=l;i<=r;i++){ 39 minX = min(minX , p[i].x[0]); 40 maxX = max(maxX , p[i].x[0]); 41 minY = min(minY , p[i].x[1]); 42 maxY = max(maxY , p[i].x[1]); 43 } 44 vis[mid] = (maxX - minX) >= (maxY - minY); 45 nth_element(p+l,p+mid,p+r+1,vis[mid]?cmpx:cmpy); 46 tree[mid] = p[mid]; 47 build(l, mid-1); 48 build(mid+1,r); 49 return ; 50 } 51 void find(int l, int r, Point v) 52 { 53 if (l > r) 54 { 55 return ; 56 } 57 int mid = (l + r)/2; 58 LL tmp = v.dist(tree[mid]); 59 if (tmp > 0){ 60 ans = min(ans, tmp); 61 } 62 if (vis[mid]){ 63 LL d = (v.x[0] - tree[mid].x[0]) * (v.x[0] - tree[mid].x[0]); 64 if (v.x[0] <= tree[mid].x[0]){ 65 find(l,mid-1,v); 66 if (d < ans){ 67 find(mid+1, r,v); 68 } 69 }else{ 70 find(mid+1, r,v); 71 if (d < ans){ 72 find(l , mid - 1,v); 73 } 74 } 75 }else{ 76 LL d = (v.x[1] - tree[mid].x[1]) * (v.x[1] - tree[mid].x[1]); 77 if (v.x[1] <= tree[mid].x[1]){ 78 find(l,mid-1,v); 79 if (d < ans){ 80 find(mid+1, r,v); 81 } 82 }else{ 83 find(mid+1, r,v); 84 if (d < ans){ 85 find(l , mid - 1,v); 86 } 87 } 88 } 89 return ; 90 } 91 int main() 92 { 93 int cas; 94 scanf("%d" , &cas); 95 while (cas--){ 96 scanf("%d", &n); 97 for (int i=1;i<=n;i++){ 98 scanf("%I64d%I64d", &p[i].x[0],&p[i].x[1]); 99 q[i] = p[i]; 100 } 101 102 build(1,n); 103 104 for (int i=1;i<=n;i++) 105 { 106 ans = inf; 107 find(1,n, q[i]); 108 printf("%I64d\n",ans); 109 } 110 } 111 return 0; 112 }