模板:求平面最近点
#include<bits/stdc++.h>
using namespace std;
const long long N=200010,INF=0x3f3f3f3f3f3f3f3f;
inline void upmx(long long &a,const long long b){if(b>a) a=b;}
inline void upmn(long long &a,const long long b){if(b<a) a=b;}
inline void upmn2(long long &a,const long long b,long long id){
if(b<a) idd=id,a=b;
}
long long D;
struct nd{
long long id,l,r,mn[2],mx[2],d[2];
bool operator<(const nd&a)const{
return d[D]<a.d[D];
}
}t[N],a[N],now;
long long mn;
inline long long sqr(long long x){
return x*x;
}
inline long long getdis1(const nd&a,const nd&b){
return sqr(a.d[0]-b.d[0])+sqr(a.d[1]-b.d[1]);
}
inline long long getdis2(nd&a,nd&b){
long long d1=max(max(b.mn[0]-a.d[0],a.d[0]-b.mx[0]),0ll);
long long d2=max(max(b.mn[1]-a.d[1],a.d[1]-b.mx[1]),0ll);
return d1*d1+d2*d2;
}
void pushup(long long o){
long long l=t[o].l,r=t[o].r;
for(long long i=0;i<2;i++){
t[o].mn[i]=t[o].d[i],t[o].mx[i]=t[o].d[i];
if(l) upmn(t[o].mn[i],t[l].mn[i]) , upmx(t[o].mx[i],t[l].mx[i]);
if(r) upmn(t[o].mn[i],t[r].mn[i]) , upmx(t[o].mx[i],t[r].mx[i]);
}
}
long long build(long long L,long long R,long long d){
D=d;
long long M=L+R>>1;
nth_element(a+L,a+M,a+R+1);
t[M]=a[M];
if(L<M) t[M].l=build(L,M-1,d^1);
if(R>M) t[M].r=build(M+1,R,d^1);
pushup(M);
return M;
}
void query(long long o){
if(!o) return;
if(now.id!=t[o].id) upmn2(mn,getdis1(now,t[o]),t[o].id);
long long dl=0,dr=0;
if(t[o].l) dl=getdis2(now,t[t[o].l]);
if(t[o].r) dr=getdis2(now,t[t[o].r]);
if(dl<dr){
if(dl<mn) query(t[o].l);
if(dr<mn) query(t[o].r);
}else{
if(dr<mn) query(t[o].r);
if(dl<mn) query(t[o].l);
}
}
long long root,n;
void debug_kdtree(){
long long n;
scanf("%lld",&n);
for(long long i=1;i<=n;i++){
scanf("%lld%lld",&a[i].d[0],&a[i].d[1]);
a[i].id=i;
}
long long root=build(1,n,0);
for(long long i=1;i<=n;i++){
mn=INF;
now=a[i];
query(root);
cout<<mn<<endl;
}
}