kd-tree 模板 Bzoj2648: SJY摆棋子

时间:2021-02-12 20:49:21

https://blog.aor.sd.cn/archives/445

 

 

#include<bits/stdc++.h>
#define lc (ch[x][0])
#define rc (ch[x][1])
using namespace std;
const int maxn=2e6+4;
int n,m,cnt,ans;
int mn[maxn][2],mx[maxn][2],ch[maxn][2],sz[maxn];
int nthdir;
struct Point{
    int pos[2];
    int& operator [](int x){
        return pos[x];
    }
    bool operator < (const Point &t) const {
        return pos[nthdir] < t.pos[nthdir];
    }
    int operator - (const Point &t) const {
        return abs(pos[0]-t.pos[0])+abs(pos[1]-t.pos[1]);
    }
    Point(int x,int y){
        pos[0]=x;pos[1]=y;
    }
    Point(){};
}p[maxn];
inline void pushup(int x){
    for(int i=0;i<=1;i++){
        mn[x][i]=mx[x][i]=p[x][i];
        if(lc){
            mn[x][i]=min(mn[x][i],mn[lc][i]);
            mx[x][i]=max(mx[x][i],mx[lc][i]);
        }
        if(rc){
            mn[x][i]=min(mn[x][i],mn[rc][i]);
            mx[x][i]=max(mx[x][i],mx[rc][i]);
        }
    }
    sz[x]=sz[lc]+sz[rc]+1;
}
inline int build(int l,int r,int dir){
    nthdir=dir;
    int x=(l+r)>>1;
    nth_element(p+l,p+x,p+r+1);
    mn[x][0]=mx[x][0]=p[x][0];
    mn[x][1]=mx[x][1]=p[x][1];
    if(l<x) lc=build(l,x-1,dir^1);
    if(r>x) rc=build(x+1,r,dir^1);
    pushup(x);return x;
}
inline void insert(int x,Point P,int dir){
    if(P[dir]<p[x][dir]){
        if(lc) insert(lc,P,dir^1);
        else{
            lc=++cnt;p[cnt]=P;
            mn[cnt][0]=mx[cnt][0]=P[0];
            mn[cnt][1]=mx[cnt][1]=P[1];
        }
    }else{
        if(rc) insert(rc,P,dir^1);
        else{
            rc=++cnt;p[cnt]=P;
            mn[cnt][0]=mx[cnt][0]=P[0];
            mn[cnt][1]=mx[cnt][1]=P[1];
        }
    }
    pushup(x);
}
inline int calc(int x,Point P){
    return max(0,mn[x][0]-P[0])+max(0,mn[x][1]-P[1])+max(0,P[0]-mx[x][0])+max(0,P[1]-mx[x][1]);
}
inline void query(int x,Point P){
    ans=min(ans,P-p[x]);
    int l=0x3f3f3f3f,r=0x3f3f3f3f;
    if(lc) l=calc(lc,P);
    if(rc) r=calc(rc,P);
    if(l<r){
        if(l<ans) query(lc,P);
        if(r<ans) query(rc,P);
    }else{
        if(r<ans) query(rc,P);
        if(l<ans) query(lc,P);
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d%d",&p[i][0],&p[i][1]);
    cnt=n;
    int rt=build(1,n,0);
    while(m--){
        int opt,x,y;scanf("%d%d%d",&opt,&x,&y);
        if(opt&1) insert(rt,Point(x,y),0);
        else{
            ans=0x3f3f3f3f;
            query(rt,Point(x,y));
            printf("%d\n",ans);
        }
    }
    return 0;
}