分析
首先,显然要二分答案。
考虑怎么check
。
我们把所有点用一个最小的矩形覆盖,显然三个正方形都要接触这个大矩形的边界。
但是有四条边界,却只有三个矩形,所以一定有一个矩形在角上,与两条边界重合。
直接$\texttt{dfs}$就好了。
代码
//It is made by M_sea
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define re register
using namespace std;
inline int read() {
int X=0,w=1; char c=getchar();
while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); }
while (c>='0'&&c<='9') X=X*10+c-'0',c=getchar();
return X*w;
}
const int N=20000+10;
const int INF=0x3f3f3f3f;
int n;
int x[N],y[N],vis[N];
inline void cover(int lx,int rx,int ly,int ry,int id) {
for (re int i=1;i<=n;++i)
if (!vis[i]&&lx<=x[i]&&rx>=x[i]&&ly<=y[i]&&ry>=y[i])
vis[i]=id;
}
inline void uncover(int id) {
for (re int i=1;i<=n;++i)
if (vis[i]==id) vis[i]=0;
}
inline int dfs(int tot,int L) {
int lx=INF,rx=-INF,ly=INF,ry=-INF;
for (re int i=1;i<=n;++i)
if (!vis[i]) {
lx=min(lx,x[i]),rx=max(rx,x[i]);
ly=min(ly,y[i]),ry=max(ry,y[i]);
}
if (max(rx-lx,ry-ly)<=L) return 1;
if (tot==3) return 0;
//打表是OI的一部分
cover(lx,lx+L,ly,ly+L,tot);
if (dfs(tot+1,L)) return 1;
uncover(tot);
cover(lx,lx+L,ry-L,ry,tot);
if (dfs(tot+1,L)) return 1;
uncover(tot);
cover(rx-L,rx,ly,ly+L,tot);
if (dfs(tot+1,L)) return 1;
uncover(tot);
cover(rx-L,rx,ry-L,ry,tot);
if (dfs(tot+1,L)) return 1;
uncover(tot);
return 0;
}
inline int check(int mid) {
memset(vis,0,sizeof(vis));
return dfs(1,mid);
}
int main() {
n=read();
for (re int i=1;i<=n;++i) x[i]=read(),y[i]=read();
int L=0,R=2e9;
while (L<R) {
int mid=(L+R)>>1;
if (check(mid)) R=mid;
else L=mid+1;
}
printf("%d\n",L);
return 0;
}
打表是OI的一部分OωO
这是好久以前写的代码了,现在可能不会这么写了 /kel