kd树
转移自老blog
      
kd树是平衡树的多维拓展,说白了就是多维平衡树,它
和普通的的区别就在于,它是按照深度决定以哪个维度
作为建树划分标准的。(优化算法另当别论)
        
算法在注释里面已经很清楚了。
kdTree
#define pow2(x) ((x)*(x)) struct kdtree{ static const int maxn=1e5,maxkd=5; static int kd,idx; int sz[maxn<<2],spile[maxn<<2]; struct node{ int w[maxkd]; bool operator<(const node&rhs)const{return w[idx]<rhs.w[idx];} }t[maxn<<2],in[maxn]; priority_queue<pair<double,node> > que; int maxvar(int l,int r){ int ret=0; double val=-1; for(int i=0;i<kd;i++){ double average=0; for(int j=l;j<=r;j++)average+=in[j].w[i]; average/=r-l+1; double variance=0; for(int j=l;j<=r;j++)variance+=pow2(average-in[j].w[i]); if(variance>val)ret=i,val=variance; } return ret; } void build(int u,int l,int r){//用前初始化kd if(l>r){sz[u]=0; return;} int mid=(l+r)>>1; spile[u]=idx=maxvar(l,r); sz[u]=r-l+1; nth_element(in+l,in+mid,in+r+1); t[u]=in[mid]; build(u<<1|0,l,mid-1); build(u<<1|1,mid+1,r); } void query(int u,int m,node&q){//用前清空que if(sz[u]==0)return ; pair<double,node> tmp(0,t[u]); for(int i=0;i<kd;i++)tmp.first+=pow2(q.w[i]-t[u].w[i]);//dist int dim=spile[u]; int closed=u<<1|(t[u].w[dim]<=q.w[dim]);//离q近的儿子 query(closed,m,q); if(que.size()<m){//not full que.push(tmp); query(closed^1,m,q);//因为没满,所以要搜 } else{// it is full if(tmp.first<que.top().first) que.pop(),que.push(tmp);//replace if(pow2(q.w[dim]-t[u].w[dim])<que.top().first)query(closed^1,m,q);//than maybe beter ,else it is imposable } } }KDT; int kdtree::idx=0,kdtree::kd=0;