二分 贪心
先二分答案,变成边长为 L L 的三个正方形能否覆盖所有点。
我们先求出目前未被覆盖的所有点组成的最小矩形。因为角上的点肯定要被覆盖,所以不妨贪心地枚举前两个正方形覆盖哪一个角,最后一个正方形直接判断。
代码:
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 20005
using namespace std;
int n,a[N],b[N],f[N];
char readc(){
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
if (l==r) return EOF; return *l++;
}
int _read(){
int x=0,f=1; char ch=readc();
while (!isdigit(ch)) { if (ch=='-') f=-1; ch=readc(); }
while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
return x*f;
}
bool pd(int p,int t){
if (t>3) return false;
int l=2e9,d=l,r=-l,u=r;
for (int i=1;i<=n;i++)
if (!f[i]){
l=min(a[i],l),r=max(a[i],r);
d=min(b[i],d),u=max(b[i],u);
}
if (r-l<=p&&u-d<=p) return true;
//枚举角,记得判断后撤销操作
for (int i=1;i<=n;i++)
f[i]+=(a[i]-l<=p&&u-b[i]<=p);
if (pd(p,t+1)) return true;
for (int i=1;i<=n;i++){
f[i]-=(a[i]-l<=p&&u-b[i]<=p);
f[i]+=(a[i]-l<=p&&b[i]-d<=p);
}
if (pd(p,t+1)) return true;
for (int i=1;i<=n;i++){
f[i]-=(a[i]-l<=p&&b[i]-d<=p);
f[i]+=(r-a[i]<=p&&u-b[i]<=p);
}
if (pd(p,t+1)) return true;
for (int i=1;i<=n;i++){
f[i]-=(r-a[i]<=p&&u-b[i]<=p);
f[i]+=(r-a[i]<=p&&b[i]-d<=p);
}
if (pd(p,t+1)) return true;
for (int i=1;i<=n;i++)
f[i]-=(r-a[i]<=p&&b[i]-d<=p);
return false;
}
int main(){
n=_read(); int l=0,r=2e9;
for (int i=1;i<=n;i++)
a[i]=_read(),b[i]=_read();
while (l<=r){
memset(f,false,sizeof(f));
int mid=(long long)l+r>>1;
if (pd(mid,1)) r=mid-1;
else l=mid+1;
}
return printf("%d\n",l),0;
}