Luogu

BZOJ

分析

首先,显然要二分答案。

考虑怎么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;
}

版权属于:小宇宙

转载时须注明出处及本声明

最后修改:2019 年 09 月 24 日 10 : 07 PM