KDtree模板

模板题:luogu4169  有个点要吸氧才能过

#include<bits/stdc++.h>
using namespace std;
const double alpha=0.8;
const int M=3;
const int N=3000010;
const int inf=0x3f3f3f3f;
int WD=2,now;
int cnt,ans;
int Q[N],B,A;
int n,m,root;
int bad,badfa,badwd;
struct Point{
    int x[M];
}P[N];
struct Tree{
    int l,r;
    int siz;
    int MIN[M],MAX[M];
    Point p; 
}T[N];
bool operator <(Point A,Point B){
    return A.x[now]<B.x[now];
}
int newpoint(Point p){
    int pos=0;
    if(B)pos=Q[B--];
    else pos=++cnt;
    T[pos].l=T[pos].r=T[pos].siz=0;
    T[pos].p=p;
    return pos;
}
void update(int pos){
    for(int i=0;i<WD;i++){
        T[pos].MAX[i]=T[pos].MIN[i]=T[pos].p.x[i];
        if(T[pos].l){
            T[pos].MIN[i]=min(T[pos].MIN[i],T[T[pos].l].MIN[i]);
            T[pos].MAX[i]=max(T[pos].MAX[i],T[T[pos].l].MAX[i]);
        }
        if(T[pos].r){
            T[pos].MIN[i]=min(T[pos].MIN[i],T[T[pos].r].MIN[i]);
            T[pos].MAX[i]=max(T[pos].MAX[i],T[T[pos].r].MAX[i]);
        }
    }
    T[pos].siz=T[T[pos].l].siz+T[T[pos].r].siz+1;
    return;
}
int build(int l,int r,int wd){
    if(l>r)return 0;
    int mid=(l+r)/2;
    now=wd;
    nth_element(P+l,P+mid,P+r+1);
    int pos=newpoint(P[mid]);
    T[pos].l=build(l,mid-1,(wd+1)%WD);
    T[pos].r=build(mid+1,r,(wd+1)%WD);
    update(pos);
    return pos;
}
bool check(int pos){
    if(1ll*T[pos].siz*alpha<1ll*T[T[pos].l].siz)return 0;
    if(1ll*T[pos].siz*alpha<1ll*T[T[pos].r].siz)return 0;
    return 1;
}
void pia(int pos,int num){
    if(T[pos].l)pia(T[pos].l,num);
    P[++A]=T[pos].p;
    Q[++B]=pos;
    if(T[pos].r)pia(T[pos].r,T[T[pos].l].siz+1+num);
}
void rebuild(){
    if(!bad)return;
    int next=(T[badfa].r==bad?1:0),last=bad;
    A=0;pia(bad,0);bad=build(1,A,badwd);
    if(next==0)T[badfa].l=bad;
    else T[badfa].r=bad;
    if(last==root)root=bad;
}
int Ins(int pos,Point p,int wd,int fa){
    if(!pos){
        pos=newpoint(p);
        update(pos);
        return pos;
    }
    if(p.x[wd]<T[pos].p.x[wd]){
        T[pos].l=Ins(T[pos].l,p,(wd+1)%WD,pos);
    }else{
        T[pos].r=Ins(T[pos].r,p,(wd+1)%WD,pos);    
    }
    update(pos);
    if(!check(pos)){
        bad=pos;
        badfa=fa;
        badwd=wd;
    }
    return pos;
}
void Insert(Point p){
    bad=badfa=0;
    root=Ins(root,p,0,0);
    rebuild();
}
int dist(Point A,Point B){
    int res=0;
    for(int i=0;i<WD;i++)res+=abs(A.x[i]-B.x[i]);
    return res;
}
int getdist(Point A,int pos){
    int res=0;
    for(int i=0;i<WD;i++){
        res+=max(0,A.x[i]-T[pos].MAX[i]);
        res+=max(0,T[pos].MIN[i]-A.x[i]);
    }
    return res;
}
void query(int pos,Point p){
    ans=min(ans,dist(p,T[pos].p));
    int Ldist=inf,Rdist=inf;
    if(T[pos].l)Ldist=getdist(p,T[pos].l);
    if(T[pos].r)Rdist=getdist(p,T[pos].r);
    if(Ldist<Rdist){
        if(Ldist<ans)query(T[pos].l,p);
        if(Rdist<ans)query(T[pos].r,p);
    }else{
        if(Rdist<ans)query(T[pos].r,p);
        if(Ldist<ans)query(T[pos].l,p);    
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        int X,Y;
        scanf("%d%d",&X,&Y);
        P[i].x[0]=X;
        P[i].x[1]=Y;
    }
    root=build(1,n,0);
    for(int i=1;i<=m;i++){
        Point tmp;
        int opt;
        scanf("%d%d%d",&opt,&tmp.x[0],&tmp.x[1]);
        if(opt==1){
            Insert(tmp);
        }else{
            ans=inf;
            query(root,tmp);
            printf("%d\n",ans);
        }
    }
}
KDtree

 

posted @ 2020-02-02 17:29  passione  阅读(170)  评论(0编辑  收藏  举报