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);
        }
    }
}

  

posted @ 2017-01-25 19:06  天翎月  阅读(270)  评论(0编辑  收藏  举报