题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1941
题意:给出平面上n个点,找出一点p,使得距离p最近和最远的点的距离之差最小。输出这个差值。
思路: 计算出距离每个点最近的点的距离和最远点的的距离。怎么计算呢?首先我们计算每个点到其左下角的那些点的最近最远距离。只要按照x升序然后y升序,之后将y离散化。一个一个插入到树状数组中。这样的话(x2+y2)-(x1+y1)的差值就是它们的距离。对于其右下角、左上角、右上角乘以(-1,1)(1,-1)(-1,-1)就跟处理左下角一样了。
struct node
{
int x,y,id;
};
node a[N];
int S[2][N],y[N];
int n,f[N][2];
void add(int flag,int x,int t)
{
while(x<N)
{
if(!flag) upMin(S[flag][x],t),x+=x&-x;
else upMax(S[flag][x],t),x+=x&-x;
}
}
int get(int flag,int x)
{
int ans;
if(!flag)
{
ans=INF;
while(x) upMin(ans,S[flag][x]),x-=x&-x;
}
else
{
ans=-INF;
while(x) upMax(ans,S[flag][x]),x-=x&-x;
}
return ans;
}
int cmp(node a,node b)
{
if(a.x!=b.x) return a.x<b.x;
return a.y<b.y;
}
void deal(int sx,int sy)
{
int i;
FOR1(i,n)
{
a[i].x*=sx;
a[i].y*=sy;
y[i]=a[i].y;
}
sort(y+1,y+n+1);
sort(a+1,a+n+1,cmp);
FOR1(i,N-1) S[1][i]=-INF,S[0][i]=INF;
int p,k;
FOR1(i,n)
{
p=lower_bound(y+1,y+n+1,a[i].y)-y;
k=a[i].id;
upMin(f[k][0],a[i].x+a[i].y-get(1,p));
upMax(f[k][1],a[i].x+a[i].y-get(0,p));
add(1,p,a[i].x+a[i].y);
add(0,p,a[i].x+a[i].y);
}
FOR1(i,n)
{
a[i].x*=sx;
a[i].y*=sy;
}
}
int main()
{
RD(n);
int i;
FOR1(i,n) RD(a[i].x,a[i].y),a[i].id=i;
FOR1(i,n) f[i][0]=INF,f[i][1]=-INF;
deal(1,1); deal(1,-1); deal(-1,1); deal(-1,-1);
int ans=INF;
FOR1(i,n) upMin(ans,f[i][1]-f[i][0]);
PR(ans);
}