某人在山上种了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
hzwer的o(n)也是orz了…
其实思路还是蛮简单的,我们先用一个最小矩形框住这些点,因为只有三个正方形,然而有四个角,显然角落上必然有一个,然而挖掉一个正方形以后用剩下的点再框的矩形里同理也有一个正方形在角落上.
我们二分,贪心check,先暴力枚举四个角挖掉两个正方形,再将剩下的点集构成的最小矩形,判断一下是否都小于mid,check枚举中一直找到这样的允许的情况为止.否则false;
#include<stdio.h>
#include<algorithm>
const int maxn=20001;
const int inf=1000000000;
int ans,cnt,lf,rg,mid,n;
inline const int read(){
register int f=1,x=0;
register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return f*x;
}
struct data{
int x[maxn],y[maxn],top;
}a,b;
inline void erase(data &a,int x1,int y1,int x2,int y2){
cnt=0;
for(int i=1;i<=a.top;i++)
if(a.x[i]<x1||a.x[i]>x2||a.y[i]<y1||a.y[i]>y2)
cnt++,a.x[cnt]=a.x[i],a.y[cnt]=a.y[i];
a.top=cnt;
}
inline void calc(data &a,int opt){
int x1=inf,x2=-inf,y1=inf,y2=-inf;
for(int i=1;i<=a.top;i++){
x1=std::min(x1,a.x[i]),x2=std::max(x2,a.x[i]);
y1=std::min(y1,a.y[i]),y2=std::max(y2,a.y[i]);
}
if(opt==1) erase(a,x1,y1,x1+mid,y1+mid);
if(opt==2) erase(a,x2-mid,y1,x2,y1+mid);
if(opt==3) erase(a,x1,y2-mid,x1+mid,y2);
if(opt==4) erase(a,x2-mid,y2-mid,x2,y2);
}
inline bool check(){
data b;
for(int x=1;x<=4;x++)
for(int y=1;y<=4;y++){
b.top=a.top;
for(int i=1;i<=b.top;i++) b.x[i]=a.x[i],b.y[i]=a.y[i];
calc(b,x),calc(b,y);
int x1=inf,x2=-inf,y1=inf,y2=-inf;
for(int i=1;i<=b.top;i++){
x1=std::min(x1,b.x[i]),x2=std::max(x2,b.x[i]);
y1=std::min(y1,b.y[i]),y2=std::max(y2,b.y[i]);
}
if(x2-x1<=mid&&y2-y1<=mid) return true;
}
return false;
}
int main(){
n=read(),a.top=n;
for(register int i=1;i<=n;i++) a.x[i]=read(),a.y[i]=read();
lf=1,rg=inf;
while(lf<=rg){
mid=(lf+rg)>>1;
if(check()) ans=mid,rg=mid-1;
else lf=mid+1;
}
printf("%d\n",ans);
}