傳送門
用之前的那種估值函數過不去。。
要記錄每個點所包含的最大範圍才過得去,每次查就看查詢點與這個範圍的最小可能距離。搜的時候先搜估值距離小的。
如果插入的點超過一定數量就重構一下,防止過於不平衡,不過貌似並沒有什麼卵用。
#include<bits/stdc++.h>
#define cs const
#define re register
#define lc(x) T[x].son[0]
#define rc(x) T[x].son[1]
cs int maxD=2,N=1e6+10,oo=1e9,rebuild=3e5;
int n,m,t,ans,x,y,INS=0;
namespace IO{
cs int Rlen=1<<22|1;
char buf[Rlen],*p1,*p2;
inline char gc(){return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;}
template<typename T>
inline T get(){
char ch;T x;
while(!isdigit(ch=gc()));x=ch^48;
while(isdigit(ch=gc())) x=((x+(x<<2))<<1)+(ch^48);
return x;
}
inline int gi(){return get<int>();}
}
using IO::gi;
using std::max;
inline void Min(int &x,int y){if(x>y)x=y;}
inline void Max(int &x,int y){if(x<y)x=y;}
namespace KD_tree{
#define mid (l+r>>1)
int tot=0,cmp_d,root=0;
struct node{
int mx[maxD],mn[maxD],val[maxD],son[2];
node(int X=0,int Y=0){
mx[0]=mn[0]=val[0]=X;
mx[1]=mn[1]=val[1]=Y;
son[0]=son[1]=0;
}
}T[N];
inline bool cmp(cs node &a,cs node &b){return a.val[cmp_d]<b.val[cmp_d];}
inline void pushup(int root){
if(lc(root)){
Min(T[root].mn[0],T[lc(root)].mn[0]),Max(T[root].mx[0],T[lc(root)].mx[0]);
Min(T[root].mn[1],T[lc(root)].mn[1]),Max(T[root].mx[1],T[lc(root)].mx[1]);
}
if(rc(root)){
Min(T[root].mn[0],T[rc(root)].mn[0]),Max(T[root].mx[0],T[rc(root)].mx[0]);
Min(T[root].mn[1],T[rc(root)].mn[1]),Max(T[root].mx[1],T[rc(root)].mx[1]);
}
}
inline int build(int l,int r,int div){
if(l>r) return 0;cmp_d=div;
std::nth_element(T+l,T+mid,T+r+1,cmp);
int u=mid;
T[u].son[0]=build(l,mid-1,div^1);
T[u].son[1]=build(mid+1,r,div^1);
return pushup(mid),mid;
}
inline void ins(int &now,int x,int y,int div){
if(!now) return void(T[now=++tot]=node(x,y));
int w=div?y:x;
if(w<T[now].val[div]) ins(T[now].son[0],x,y,div^1);
else ins(T[now].son[1],x,y,div^1);
pushup(now);
}
inline void insert(int x,int y){ins(root,x,y,0);}
inline int dis(cs node &A,int x,int y,int ret=0){
return max(0,A.mn[0]-x)+max(0,A.mn[1]-y)+max(0,x-A.mx[0])+max(0,y-A.mx[1]);
}
inline void ask(int pos,int x,int y){
if(!pos) return;
int dl=oo,dr=oo,curdis=abs(T[pos].val[0]-x)+abs(T[pos].val[1]-y);
Min(ans,curdis);
if(lc(pos)) dl=dis(T[lc(pos)],x,y);
if(rc(pos)) dr=dis(T[rc(pos)],x,y);
if(dl<dr){
if(dl<ans) ask(lc(pos),x,y);
if(dr<ans) ask(rc(pos),x,y);
}
else{
if(dr<ans) ask(rc(pos),x,y);
if(dl<ans) ask(lc(pos),x,y);
}
}
#undef mid
}
using namespace KD_tree;
int main(){
// freopen("3059.in","r",stdin);
n=gi(),m=gi();
for(int i=1;i<=n;++i) x=gi(),y=gi(),T[i]=node(x,y);
root=build(1,n,0),KD_tree::tot=n;
while(m--){
t=gi();
if(t==1){
x=gi(),y=gi(),insert(x,y);
if(++INS==rebuild) root=build(1,tot,0),INS=0;
}
if(t==2) ans=oo,x=gi(),y=gi(),ask(root,x,y),printf("%d\n",ans);
}
}