kd-tree 模板 Bzoj2648: SJY摆棋子
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; }