您的位置:首页 > 大数据 > 人工智能

【HDU】2966 In case of failure【KD树】

2015-11-10 12:54 603 查看
传送门:【HDU】2966 In case of failure【KD树】

题意:给平面图上N(1≤N≤105)个点,对每个点,找到其他 欧几里德距离 离他最近的点,输出他们之间的距离。保证没有重点。

这是本弱学习KD树做的第一题。本题做法网上很多,我就不详细说了。

KD树在算法竞赛中主要用来做各种各样的平面区域查询,包含则累加直接返回,相交则继续递归,相离的没有任何贡献也直接返回。可以处理圆,三角形,矩形等判断起来相对容易的平面区域内的符合加法性质的操作。

KD树的建树:交替选择当前递归区间内所有点的横、纵坐标的中位数然后以此为新的划分点继续递归。因为每次都是划分成一半,而求中位数可以用nth_element()做到O(N),因此复杂度为T(N)=2T(N2)+O(N)=O(NlogN)。

my code:

#include <bits/stdc++.h>
using namespace std ;

typedef long long LL ;

const int MAXN = 100005 ;

struct Node {
int p[2] ;
int f , l , r ;
int Min[2] , Max[2] ;
int operator [] ( const int& idx ) const {
return p[idx] ;
}
void input ( int idx ) {
scanf ( "%d%d" , &p[0] , &p[1] ) ;
f = idx ;
}
void up ( Node& a ) {
Min[0] = min ( Min[0] , a.Min[0] ) ;
Max[0] = max ( Max[0] , a.Max[0] ) ;
Min[1] = min ( Min[1] , a.Min[1] ) ;
Max[1] = max ( Max[1] , a.Max[1] ) ;
}
} ;

Node T[MAXN] ;
int idx[MAXN] ;
int cmpw ;
int root ;
int n ;
LL ans ;

bool cmp ( const Node& a , const Node& b ) {
return a[cmpw] < b[cmpw] ;
}

void up ( int o ) {
if ( T[o].l ) T[o].up ( T[T[o].l] ) ;
if ( T[o].r ) T[o].up ( T[T[o].r] ) ;
}

int build ( int l , int r , int w , int f ) {
int mid = l + r >> 1 ;
cmpw = w ;
nth_element ( T + l , T + mid , T + r + 1 , cmp ) ;
idx[T[mid].f] = mid ;
//T[mid].f = f ;
//T[mid].Min[0] = T[mid].Max[0] = T[f].p[0] ;
//T[mid].Min[1] = T[mid].Max[1] = T[f].p[1] ;
T[mid].l = l != mid ? build ( l , mid - 1 , !w , mid ) : 0 ;
T[mid].r = r != mid ? build ( mid + 1 , r , !w , mid ) : 0 ;
//up ( mid ) ;
return mid ;
}

LL dist ( LL x , LL y = 0 ) {
return x * x + y * y ;
}

LL query ( int o , int w , LL x , LL y ) {
LL tmp = dist ( x - T[o][0] , y - T[o][1] ) ;
if ( tmp ) ans = min ( ans , tmp ) ;
if ( T[o].l && T[o].r ) {
bool d = !w ? ( x <= T[o][0] ) : ( y <= T[o][1] ) ;
LL dis = !w ? dist ( x - T[o][0] ) : dist ( y - T[o][1] ) ;
query ( d ? T[o].l : T[o].r , !w , x , y ) ;
if ( dis < ans ) query ( d ? T[o].r : T[o].l , !w , x , y ) ;
}
else if ( T[o].l ) query ( T[o].l , !w , x , y ) ;
else if ( T[o].r ) query ( T[o].r , !w , x , y ) ;
}

void solve () {
scanf ( "%d" , &n ) ;
for ( int i = 1 ; i <= n ; ++ i ) {
T[i].input ( i ) ;
}
root = build ( 1 , n , 0 , 0 ) ;
for ( int i = 1 ; i <= n ; ++ i ) {
ans = 9e18 ;
query ( root , 0 , T[idx[i]][0] , T[idx[i]][1] ) ;
printf ( "%lld\n" , ans ) ;
}
}

int main () {
int T ;
scanf ( "%d" , &T ) ;
for ( int i = 1 ; i <= T ; ++ i ) {
solve () ;
}
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: