题目:
题解:
天啦噜SDOI竟然出KD-tree裸题
注意求最远距离、最近距离的dis的用途:
最远的dismax:管辖区间内的点达到这个目标点的最多要用的距离(可能)
最近的dismin:管辖区间内的点达到这个目标点的最少要用的距离(可能),除非ta出界了,所有的点都要加上这个距离
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#define INF 1e9
using namespace std;
struct hh{int d[2],l,r,mn[2],mx[2];}t[500005];
int root,maxx,minn,cmpd,x,y,n;
int cmp(const hh &a,const hh &b)
{
return (a.d[cmpd]<b.d[cmpd] || (a.d[cmpd]==b.d[cmpd] && a.d[!cmpd]<b.d[!cmpd]));
}
void updata(int now)
{
int lc=t[now].l,rc=t[now].r;
if (lc)
{
t[now].mn[0]=min(t[now].mn[0],t[lc].mn[0]);
t[now].mn[1]=min(t[now].mn[1],t[lc].mn[1]);
t[now].mx[0]=max(t[now].mx[0],t[lc].mx[0]);
t[now].mx[1]=max(t[now].mx[1],t[lc].mx[1]);
}
if (rc)
{
t[now].mn[0]=min(t[now].mn[0],t[rc].mn[0]);
t[now].mn[1]=min(t[now].mn[1],t[rc].mn[1]);
t[now].mx[0]=max(t[now].mx[0],t[rc].mx[0]);
t[now].mx[1]=max(t[now].mx[1],t[rc].mx[1]);
}
}
int build(int l,int r,int D)
{
cmpd=D;
int mid=(l+r)>>1;
nth_element(t+l+1,t+mid+1,t+r+1,cmp);
t[mid].mn[0]=t[mid].mx[0]=t[mid].d[0];
t[mid].mn[1]=t[mid].mx[1]=t[mid].d[1];
if (l!=mid) t[mid].l=build(l,mid-1,!D);
if (r!=mid) t[mid].r=build(mid+1,r,!D);
updata(mid); return mid;
}
int dismin(int now)
{
int d=0;
if (x>t[now].mx[0]) d+=x-t[now].mx[0];
if (x<t[now].mn[0]) d+=t[now].mn[0]-x;
if (y>t[now].mx[1]) d+=y-t[now].mx[1];
if (y<t[now].mn[1]) d+=t[now].mn[1]-y;
return d;
}
void askmin(int now)
{
int d0,dl,dr;
d0=abs(t[now].d[0]-x)+abs(t[now].d[1]-y);
if (d0) minn=min(minn,d0);
if (t[now].l) dl=dismin(t[now].l);else dl=INF;
if (t[now].r) dr=dismin(t[now].r);else dr=INF;
if (dl<dr)
{
if (dl<minn) askmin(t[now].l);
if (dr<minn) askmin(t[now].r);
}
else
{
if (dr<minn) askmin(t[now].r);
if (dl<minn) askmin(t[now].l);
}
}
int dismax(int now)
{
int d;
d+=max(abs(t[now].mn[0]-x),abs(t[now].mx[0]-x));
d+=max(abs(t[now].mn[1]-y),abs(t[now].mx[1]-y));
return d;
}
void askmax(int now)
{
int d0,dl,dr;
d0=abs(t[now].d[0]-x)+abs(t[now].d[1]-y);
maxx=max(maxx,d0);
if (t[now].l) dl=dismax(t[now].l);else dl=0;
if (t[now].r) dr=dismax(t[now].r);else dr=0;
if (dl>dr)
{
if (dl>maxx) askmax(t[now].l);
if (dr>maxx) askmax(t[now].r);
}
else
{
if (dr>maxx) askmax(t[now].r);
if (dl>maxx) askmax(t[now].l);
}
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d%d",&t[i].d[0],&t[i].d[1]);
root=build(1,n,0);int ans=INF;
for (int i=1;i<=n;i++)
{
x=t[i].d[0]; y=t[i].d[1];
maxx=0; minn=INF;
askmin(root);
askmax(root);
ans=min(ans,maxx-minn);
}
printf("%d",ans);
}