Solution
可以看出是二分,关键在于如何设计check
用一个最小的矩形将所有数包含在内,则三个正方形满足要求的必要非充分条件为覆盖矩形的每条边
但矩形有四条边,而只有三个正方形,于是有一个正方形在角上
于是有了简便的判断方法
Code
#include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> using namespace std; const int N=2e4+10; int x[N],y[N],n,inf=0x3f3f3f3f,vis[N]; void add(int a,int b,int c,int d,int id) { for(int i=1;i<=n;i++) if(!vis[i] && x[i]>=a && x[i]<=c && y[i]>=b && y[i]<=d) vis[i]=id; } void cut(int id) { for(int i=1;i<=n;i++) if(vis[i]==id) vis[i]=0; } bool check(int pos,int L) { int lx=inf,rx=-inf,ly=inf,ry=-inf; for(int i=1;i<=n;i++) { if(vis[i]) continue; 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(pos==3) return 0; add(lx,ly,lx+L,ly+L,pos); if(check(pos+1,L)) return 1; cut(pos); add(lx,ry-L,lx+L,ry,pos); if(check(pos+1,L)) return 1; cut(pos); add(rx-L,ly,rx,ly+L,pos); if(check(pos+1,L)) return 1; cut(pos); add(rx-L,ry-L,rx,ry,pos); if(check(pos+1,L)) return 1; cut(pos); return 0; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]); int l=0,r=2e9; while(l<r) { int mid=(l+r)>>1; memset(vis,0,sizeof(vis)); if(check(1,mid)) r=mid; else l=mid+1; } printf("%d\n",l); return 0; }