Description
某人在山上种了N棵小树苗。冬天来了,温度急速下降,小树苗脆弱得不堪一击,于是树主人想用一些塑料薄膜把这些小树遮盖起来,经过一番长久的思考,他决定用3个L*L的正方形塑料薄膜将小树遮起来。我们不妨将山建立一个平面直角坐标系,设第i棵小树的坐标为(Xi,Yi),3个L*L的正方形的边要求平行与坐标轴,一个点如果在正方形的边界上,也算作被覆盖。当然,我们希望塑料薄膜面积越小越好,即求L最小值。
Input
第一行有一个正整数N,表示有多少棵树。接下来有N行,第i+1行有2个整数Xi,Yi,表示第i棵树的坐标,保证不会有2个树的坐标相同。
Output
一行,输出最小的L值。
Sample Input
4
0 1
0 -1
1 0
-1 0
Sample Output
1
HINT
100%的数据,-1,000,000,000<=Xi,Yi<=1,000,000,000
100%的数据,N<=20000
Source
答案满足单调性,所以直接二分答案。判定放薄膜的时候,显然最优方案就是薄膜的四角中的某一角在一棵树上(可以枚举),如果放了两次以后,薄膜能覆盖相距最远的两棵树,即返回1。
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cctype>
#define INF 1000000000
using namespace std;
const int N=20010;
struct data{int x[N],y[N],n;}map;
void in(int &x)
{
x=0;int f=1;char t=getchar();
while(!isdigit(t)){if(t=='-')f=-1;t=getchar();}
while(isdigit(t)){x=x*10+t-48;t=getchar();}
x*=f;
}
void chuli(data &a,int x1,int y1,int x2,int y2)
{
int now=0;
for (int i=1;i<=a.n;++i)
if ((a.x[i]<x1)or(a.x[i]>x2)or(a.y[i]<y1)or(a.y[i]>y2))
{
++now;
a.x[now]=a.x[i];
a.y[now]=a.y[i];
}
a.n=now;
}
void work(data &a,int flag,int x)
{
int x1=INF,y1=INF,x2=-INF,y2=-INF;
for (int i=1;i<=a.n;++i)
{
x1=min(x1,a.x[i]);y1=min(y1,a.y[i]);
x2=max(x2,a.x[i]);y2=max(y2,a.y[i]);
}
if (flag==1) chuli(a,x1,y1,x1+x,y1+x);
if (flag==2) chuli(a,x2-x,y1,x2,y1+x);
if (flag==3) chuli(a,x1,y2-x,x1+x,y2);
if (flag==4) chuli(a,x2-x,y2-x,x2,y2);
}
bool can(int l)
{
for (int x=1;x<=4;++x)
for (int y=1;y<=4;++y)
{
data tmp;tmp.n=map.n;
for (int i=1;i<=tmp.n;++i)
tmp.x[i]=map.x[i],tmp.y[i]=map.y[i];
work(tmp,x,l);//第一次
work(tmp,y,l);//第二次
if (tmp.n==0) return 1;
int x1=INF,y1=INF,x2=-INF,y2=-INF;
for (int i=1;i<=tmp.n;++i)
{
x1=min(x1,tmp.x[i]);y1=min(y1,tmp.y[i]);
x2=max(x2,tmp.x[i]);y2=max(y2,tmp.y[i]);
}
if ((x2-x1<=l)and(y2-y1<=l)) return 1;
}
return 0;
}
int main()
{
in(map.n);
for (int i=1;i<=map.n;++i)
in(map.x[i]),in(map.y[i]);
int head=1,tail=INF;
while(head<tail)
{
int mid=(head+tail)>>1;
if (can(mid)) tail=mid;
else head=mid+1;
}
printf("%d",head);
return 0;
}