BZOJ2648&&2716 不講道理的KD-tree

不得不承認KDtree的卻是二維空間類距離處理利器,省去了樹套樹繁瑣的操作,code簡潔明瞭。

爲了防止KDtree我還特意加上了rebuild的操作……結果反而更滿了……,cnt太小<=70000還會TLE……WCO

哎,KDTREE就那樣吧,隨便打打,開心開心就好了。

//去掉rebuild操作更快。
#include<bits/stdc++.h>
inline int maxn(int x,int y){return x<y?y:x;}
inline int minn(int x,int y){return x<y?x:y;}
int n,m,root,cmp_d,k1,k2,k3,ans;
struct node{
    int d[2],l,r,maxn[2],minn[2];
}tree[1000001],pte[1000001],tmp;
inline 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]<b.d[!cmp_d]));
}
void update(const int p){
    if(tree[p].l){
        if(tree[p].maxn[0]<tree[tree[p].l].maxn[0])tree[p].maxn[0]=tree[tree[p].l].maxn[0];
        if(tree[p].minn[0]>tree[tree[p].l].minn[0])tree[p].minn[0]=tree[tree[p].l].minn[0];
        if(tree[p].maxn[1]<tree[tree[p].l].maxn[1])tree[p].maxn[1]=tree[tree[p].l].maxn[1];
        if(tree[p].minn[1]>tree[tree[p].l].minn[1])tree[p].minn[1]=tree[tree[p].l].minn[1];
    }if(tree[p].r){
        if(tree[p].maxn[0]<tree[tree[p].r].maxn[0])tree[p].maxn[0]=tree[tree[p].r].maxn[0];
        if(tree[p].minn[0]>tree[tree[p].r].minn[0])tree[p].minn[0]=tree[tree[p].r].minn[0];
        if(tree[p].maxn[1]<tree[tree[p].r].maxn[1])tree[p].maxn[1]=tree[tree[p].r].maxn[1];
        if(tree[p].minn[1]>tree[tree[p].r].minn[1])tree[p].minn[1]=tree[tree[p].r].minn[1];
    }
}
int build(const int l,const int r,const int D){
    if(l>r)return 0;
    register int mid=(l+r)>>1;
    cmp_d=D;std::nth_element(pte+l+1,pte+mid+1,pte+r+1,cmp);
    tree[mid]=pte[mid];
    tree[mid].maxn[0]=tree[mid].minn[0]=tree[mid].d[0];
    tree[mid].maxn[1]=tree[mid].minn[1]=tree[mid].d[1];
    tree[mid].l=build(l,mid-1,!D);
    tree[mid].r=build(mid+1,r,!D);
    update(mid);
    return mid;
}
inline void insert(const int now){
    register int D,p;
    D=0;p=root;
    while(1){
        if(tree[now].maxn[0]>tree[p].maxn[0])tree[p].maxn[0]=tree[now].maxn[0];
        if(tree[now].maxn[1]>tree[p].maxn[1])tree[p].maxn[1]=tree[now].maxn[1];
        if(tree[now].minn[0]<tree[p].minn[0])tree[p].minn[0]=tree[now].minn[0];
        if(tree[now].minn[1]<tree[p].minn[1])tree[p].minn[1]=tree[now].minn[1];
        if(tree[now].d[D]>=tree[p].d[D]){
            if(tree[p].r==0){
                tree[p].r=now;
                return;
            }else p=tree[p].r;
        }else{
            if(tree[p].l==0){
                tree[p].l=now;
                return;
            }else p=tree[p].l;
        }
        D=!D;
    }
}
inline int dist(const int p1,const int px,const int py){
    register int dis=0;
    if(px<tree[p1].minn[0])dis+=tree[p1].minn[0]-px;
    if(px>tree[p1].maxn[0])dis+=px-tree[p1].maxn[0];
    if(py<tree[p1].minn[1])dis+=tree[p1].minn[1]-py;
    if(py>tree[p1].maxn[1])dis+=py-tree[p1].maxn[1];
    return dis;
}
inline void query(const int p){
    register int dl,dr,d0;
    d0=abs(tree[p].d[0]-k2)+abs(tree[p].d[1]-k3);
    if(d0<ans)ans=d0;
    if(tree[p].l)dl=dist(tree[p].l,k2,k3);else dl=0x7f7f7f7f;
    if(tree[p].r)dr=dist(tree[p].r,k2,k3);else dr=0x7f7f7f7f;
    if(dl<dr){
        if(dl<ans)query(tree[p].l);
        if(dr<ans)query(tree[p].r);
    }else{
        if(dr<ans)query(tree[p].r);
        if(dl<ans)query(tree[p].l);
    }
}
template<class T>inline void read(T &res){
    static char ch;T flag=1;
    while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;res=ch-48;
    while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;res*=flag;
}
int main(){
    read(n),read(m);
    register int i,j,cnt=0;
    tree[0].maxn[0]=tree[0].maxn[1]=-0x7f7f7f7f;
    tree[0].minn[0]=tree[0].minn[1]= 0x7f7f7f7f;
    for(i=1;i<=n;++i)read(pte[i].d[0]),read(pte[i].d[1]);
    root=build(1,n,0);
    for(i=1;i<=m;++i){
        read(k1),read(k2),read(k3);
        if(k1==1){
            ++n;
            tree[n].maxn[0]=tree[n].minn[0]=tree[n].d[0]=k2;
            tree[n].maxn[1]=tree[n].minn[1]=tree[n].d[1]=k3;
            insert(n);
            if(++cnt==200000){
                for(j=1;j<=n;j++)pte[j]=tree[j];
                root=build(1,n,0);cnt=0;
            }
        }else{
            ans=0x7f7f7f7f;
            query(root);
            printf("%d\n",ans); 
        }   
    }
    return 0;
}

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章