原题地址
Kdtree的带插入最邻近点查询.
轮流划分维度+暴力插入AC了,而且时间排名还比较靠前…
AC code:
#include
#include
using namespace std;
const int K=2;
const int N=1000010;
const int INF=1<<29;
int n,m,mn,tot,flg;
struct Poi{
int d[K];
Poi() {}
Poi(int x,int y) {d[0]=x;d[1]=y;}
friend bool operator<(Poi x,Poi y){
return x.d[flg]2];
}pool[N];
struct Kdtree{
nod *root;
Kdtree(){
build(&root,1,n,0);
}
void update(nod *p){
for(int i=0;imxd[i]=p->mnd[i]=p->poi.d[i];
if(p->ch[0]!=NULL){
p->mxd[i]=max(p->mxd[i],p->ch[0]->mxd[i]);
p->mnd[i]=min(p->mnd[i],p->ch[0]->mnd[i]);
}
if(p->ch[1]!=NULL){
p->mxd[i]=max(p->mxd[i],p->ch[1]->mxd[i]);
p->mnd[i]=min(p->mnd[i],p->ch[1]->mnd[i]);
}
}
}
int mindis(nod *p,Poi poi){
int sum=0;
for(int i=0;iif(poi.d[i]mnd[i]) sum+=p->mnd[i]-poi.d[i];
else if(poi.d[i]>p->mxd[i]) sum+=poi.d[i]-p->mxd[i];
}
return sum;
}
void build(nod **p,int L,int R,int flag){
if(L>R) return ;
*p=&pool[tot++];
if(L==R){
(*p)->poi=a[L];
for(int i=0;i (*p)-> mxd[i]=(*p)->mnd[i]=a[L].d[i];
return ;
}
int M=(L+R)>>1;
flg=flag;
nth_element(a+L,a+M,a+R+1);
(*p)->poi=a[M];
build(&(*p)->ch[0],L,M-1,(flag+1)%K);
build(&(*p)->ch[1],M+1,R,(flag+1)%K);
update(*p);
}
void insert(nod **p,Poi poi,int flag){
if(*p==NULL){
*p=&pool[tot++];
(*p)->poi=poi;
for(int i=0;i (*p)-> mxd[i]=(*p)->mnd[i]=poi.d[i];
return ;
}
if(poi.d[flag]<=(*p)->poi.d[flag]) insert(&(*p)->ch[0],poi,(flag+1)%K);
else insert(&(*p)->ch[1],poi,(flag+1)%K);
update(*p);
}
void query(nod *p,Poi poi){
int dis0=abs(p->poi.d[0]-poi.d[0])+abs(p->poi.d[1]-poi.d[1]),dis[2];
if(dis0 mn=dis0;
if(p->ch[0]!=NULL) dis[0]=mindis(p->ch[0],poi);
if(p->ch[1]!=NULL) dis[1]=mindis(p->ch[1],poi);
bool t=dis[0]>dis[1];
if(p->ch[t]!=NULL&&dis[t] query(p->ch[t],poi);
t^=1;
if(p->ch[t]!=NULL&&dis[t] query(p->ch[t],poi);
}
};
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=0;j
scanf("%d",&a[i].d[j]);
Kdtree T;
for(int i=1;i<=m;i++){
int t,x,y;
scanf("%d%d%d",&t,&x,&y);
if(t==1) T.insert(&T.root,Poi(x,y),0);
else{
mn=INF;
T.query(T.root,Poi(x,y));
printf("%d\n",mn);
}
}
return 0;
}