题目链接:http://codeforces.com/problemset/problem/314/D
题意:给出平面上一些点的坐标。在平面上画两个相互垂直的直线,且已知一条与x轴夹角45度。画完之后,使得点到直线的距离的最大值最小。距离为|x1-x2|+|y1-y2|。
思路:(1)首先,将坐标轴旋转45度,那么点(x,y)的坐标变为(x-y,x+y)。然后就是画出两条分别平行于xy轴的直线使得距离的最大值最小。其实就是画出一个最小的正方形包含所有点。
(2)我们将所有点按照x升序,用preMin[i],preMax[i]表示前i个点最小、最大的y坐标;sufMin[i]、sufMax[i]表示后i个点最小最大的y坐标。
(3)二分答案d(正方形的边长),对于中间一段的点[j,i](i和j的横坐标差小于等于d),那么我们只要j-1之前和i+1之后的y的最大最小差值在d之内就可以。每次判断可行性O(n)
pair<int,int> a[N];
int n;
int preMin[N],preMax[N],sufMin[N],sufMax[N];
int OK(i64 d)
{
int i,j=1,y1,y2;
FOR1(i,n)
{
while(a[i].first>a[j].first+d) j++;
y1=max(sufMax[i+1],preMax[j-1]);
y2=min(sufMin[i+1],preMin[j-1]);
if(y1-y2<=d) return 1;
}
return 0;
}
int main()
{
RD(n);
int i,x,y;
FOR1(i,n)
{
RD(x,y);
a[i]=MP(x-y,x+y);
}
sort(a+1,a+n+1);
preMin[0]=INF;
preMax[0]=-INF;
FOR1(i,n)
{
preMin[i]=min(preMin[i-1],a[i].second);
preMax[i]=max(preMax[i-1],a[i].second);
}
sufMin[n+1]=INF;
sufMax[n+1]=-INF;
FORL1(i,n)
{
sufMin[i]=min(sufMin[i+1],a[i].second);
sufMax[i]=max(sufMax[i+1],a[i].second);
}
i64 low=0,high=inf,mid,ans;
while(low<=high)
{
mid=(low+high)>>1;
if(OK(mid)) ans=mid,high=mid-1;
else low=mid+1;
}
PR(ans/2.0);
return 0;
}