BZOJ 2648 kd-tree模板
学习了一下kd-tree的基本写法 http://blog.csdn.net/jiangshibiao/article/details/34144829 配合 http://www.bilibili.com/video/av7039143/ 食用
不过这个博客的里面那道2648的代码是错的 应该加上一句if(n)build 否则应该在插入第一个黑点的时候建树
kd-tree的写法还是很简单的 如果学习过线段树 应该很容易就学会了模板了
#include<stdio.h> #include<string.h> #include<algorithm> #include<map> #include<math.h> #include<queue> #include<string> using namespace std; #define L long long const int INF = 999999999 ; int n , m , root , cmp_d ; int x, y ; struct node{ int d[2] , Max[2] , Min[2] ; int l, r ; }tr[1000050]; bool cmp(node a , node b){ return a.d[cmp_d] < b.d[cmp_d] || a.d[cmp_d] == b.d[cmp_d] && a.d[cmp_d^1] < b.d[cmp_d^1]; } void up(int p,int k){ if(tr[k].Max[0] > tr[p].Max[0]) tr[p].Max[0] = tr[k].Max[0] ; if(tr[k].Max[1] > tr[p].Max[1]) tr[p].Max[1] = tr[k].Max[1] ; if(tr[k].Min[0] < tr[p].Min[0]) tr[p].Min[0] = tr[k].Min[0] ; if(tr[k].Min[1] < tr[p].Min[1]) tr[p].Min[1] = tr[k].Min[1] ; } int build(int l,int r, int D){ int mid = (l+r) >> 1; cmp_d = D; nth_element(tr+l+1,tr+mid+1,tr+r+1,cmp) ; tr[mid].Max[0] = tr[mid].Min[0] = tr[mid].d[0]; tr[mid].Max[1] = tr[mid].Min[1] = tr[mid].d[1]; if(l!=mid) tr[mid].l = build(l,mid-1,D^1) ; else tr[mid].l = 0; if(r!=mid) tr[mid].r = build(mid+1,r,D^1); else tr[mid].r = 0; if(tr[mid].l)up(mid,tr[mid].l); if(tr[mid].r)up(mid,tr[mid].r); return mid ; } void inse(int k){ int p = root ; int D = 0 ; while(true){ up(p,k); if(tr[k].d[D] <= tr[p].d[D]){ if(!tr[p].l){ tr[p].l = k ; return; } p = tr[p].l ; } else { if(!tr[p].r){ tr[p].r = k ; return; } p = tr[p].r ; } D ^= 1; } } int ans ; int getdis(int p,int x,int y){ int res = 0; if(x > tr[p].Max[0])res += x - tr[p].Max[0]; if(x < tr[p].Min[0])res += tr[p].Min[0] - x; if(y > tr[p].Max[1])res += y - tr[p].Max[1]; if(y < tr[p].Min[1])res += tr[p].Min[1] - y; return res ; } void ask(int p){ int d0 = abs(x - tr[p].d[0]) + abs(y - tr[p].d[1]) ; if(d0<ans)ans = d0 ; int dl , dr ; if(tr[p].l)dl=getdis(tr[p].l,x,y) ;else dl = INF ; if(tr[p].r)dr=getdis(tr[p].r,x,y) ;else dr = INF ; if(dl < dr){ if(dl < ans)ask(tr[p].l) ; if(dr < ans)ask(tr[p].r) ; } else { if(dr < ans)ask(tr[p].r) ; if(dl < ans)ask(tr[p].l) ; } } int main(){ scanf("%d%d",&n,&m); for(int i = 1; i <= n ; i ++ ){ scanf("%d%d",&tr[i].d[0] , &tr[i].d[1]); } if(n) root = build(1,n,0) ; for(int i = 1; i <= m ; i ++ ){ int q; scanf("%d%d%d",&q,&x,&y); if(q == 1){ n ++ ; tr[n].d[0]=tr[n].Max[0]=tr[n].Min[0]=x; tr[n].d[1]=tr[n].Max[1]=tr[n].Min[1]=y; if(n>1) inse(n); else { root = build(1,n,0); } } else { ans = INF; ask(root); printf("%d\n",ans); } } }