KD-Tree這樣縮寫看起來有一種莫名的喜感23333
建樹的時候和k遠點對那個“最遠+歐幾里得KD-Tree”距離沒什麼區別,但是查詢的時候“最近+曼哈頓KD-Tree”還是有一些區別
首先,KDT上的一個節點代表一個矩形方塊,當我們做估價函數的時候,如果被查詢點的某一維夾在矩形方塊的某一維之間,那麼這一維的估價值就是0,而不是到這一維兩個邊界的距離的較小值。因爲我們的估價函數實際上是假設這個矩形的每一個方格上都有點存在,如果取邊界可能不是最優。
/**************************************************************
Problem: 2648
User: RicardoWang
Language: C++
Result: Accepted
Time:13032 ms
Memory:32528 kb
****************************************************************/
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define maxn 500005
#define oo 999999999
void _read(int &x)
{
char ch=getchar(); bool flag=false; x=0;
while(ch<'0' || ch>'9'){if(ch=='-')flag=true; ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} if(flag)x=-x; return ;
}
struct P
{
int d[2];
}A[2*maxn],t;
int Q,n,m,rt,chi[2*maxn][2];
bool mycmp(P x,P y)
{
if(x.d[Q]==y.d[Q])return x.d[Q^1]<y.d[Q^1];
else return x.d[Q]<y.d[Q];
}
int minv[2*maxn][2],maxv[2*maxn][2];
void pushup(int now)
{
for(int i=0;i<2;i++)
{
minv[now][i]=min(A[now].d[i],min(minv[chi[now][0]][i],minv[chi[now][1]][i]));
maxv[now][i]=max(A[now].d[i],max(maxv[chi[now][0]][i],maxv[chi[now][1]][i]));
}
return ;
}
void build(int &now,int L,int R,int k)
{
int mid=(L+R)>>1; now=mid; chi[now][0]=chi[now][1]=0;
Q=k; if(L!=R)nth_element(A+L,A+mid,A+R+1,mycmp);
if(mid!=L) build(chi[now][0],L,mid-1,k^1);
if(mid!=R) build(chi[now][1],mid+1,R,k^1);
pushup(now);
return ;
}
void Insert(int now,int x,int k)
{
int p=now,d;
while(p)
{
minv[p][0]=min(minv[p][0],A[x].d[0]);minv[p][1]=min(minv[p][1],A[x].d[1]);
maxv[p][0]=max(maxv[p][0],A[x].d[0]);maxv[p][1]=max(maxv[p][1],A[x].d[1]);
d=(A[x].d[k]>=A[p].d[k]);
if(chi[p][d])
{
p=chi[p][d];
k=k^1;
}
else
{
chi[p][d]=x;
break;
}
}
return ;
}
int ans;
int Abs(int x)
{
return x<0 ? -x : x ;
}
int getdis(P x,P y)
{
return Abs(x.d[0]-y.d[0])+Abs(x.d[1]-y.d[1]);
}
int get(int x)
{
if(!x)return oo;
int ans=0;
for(int i=0;i<2;i++)
{
ans+=max(0,minv[x][i]-t.d[i])+max(0,t.d[i]-maxv[x][i]);
}
return ans;
}
void query(int now)
{
int dd=getdis(A[now],t),dl=get(chi[now][0]),dr=get(chi[now][1]);
if(dd<ans)ans=dd;
if(dl<dr)
{
if(dl<ans && chi[now][0])query(chi[now][0]);
if(dr<ans && chi[now][1])query(chi[now][1]);
}
else
{
if(dr<ans && chi[now][1])query(chi[now][1]);
if(dl<ans && chi[now][0])query(chi[now][0]);
}
return ;
}
void Init()
{
_read(n);_read(m);
for(int i=1;i<=n;i++)
{
_read(A[i].d[0]); _read(A[i].d[1]);
}
minv[0][0]=minv[0][1]=oo;
maxv[0][0]=maxv[0][1]=-oo;
build(rt,1,n,0);
return ;
}
void work()
{
char op;
int cct=0;
for(int i=1;i<=m;i++)
{
op=getchar();while(op!='1' && op!='2')op=getchar();
if(op=='1')
{
cct++;
n++; _read(A[n].d[0]); _read(A[n].d[1]);
chi[n][0]=chi[n][1]=0;
minv[n][0]=maxv[n][0]=A[n].d[0];minv[n][1]=maxv[n][1]=A[n].d[1];
Insert(rt,n,0);
}
else
{
ans=oo;
_read(t.d[0]); _read(t.d[1]);
query(rt);
printf("%d\n",ans);
}
}
return ;
}
int main()
{
//freopen("in.txt","r",stdin);
Init();
work();
return 0;
}