@ysner
2018-07-18T16:40:59.000000Z
字数 2241
阅读 2456
贪心 二分
最小化,使个的正方形能覆盖图上个点。
首先肯定要二分答案,是算不出来的。
然后构建一个覆盖所有点的最小矩形。
注意到每条边至少要一个正方形靠着。
但现在只有个正方形,意味着至少有一个正方形靠着两条边。
靠着相对的两条边?那说明这个图被这个正方形并排着覆盖。
即一定存在靠着相邻两条边(在四角)的正方形。
可以把四种情况都试一遍。
用个覆盖之后又可以重复上面的步骤,以此类推。
然而我因为各种愚蠢错误了一版,如开全局变量(开局部才能保证互不影响)、打错条件与数字。。。
复杂度上限
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#define re register#define il inline#define ll long long#define max(a,b) ((a)>(b)?(a):(b))#define min(a,b) ((a)<(b)?(a):(b))#define fp(i,a,b) for(re int i=a;i<=b;i++)#define fq(i,a,b) for(re int i=a;i>=b;i--)using namespace std;const int N=2e4+100;int n,x[N],y[N];bool vis[N];il ll gi(){re ll x=0,t=1;re char ch=getchar();while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();if(ch=='-') t=-1,ch=getchar();while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();return x*t;}il int solve(re ll l,re ll r,re ll u,re ll d,re int t,re ll L){re bool viss[N]={};fp(i,1,n) viss[i]=vis[i];re int flag=1;fp(i,1,n) if(!vis[i]) flag=0;if(flag) return 1;else if(t>3) return 0;{re int zz=1e9,xx=1e9,yy=-1e9,ss=-1e9;fp(i,1,n) if(x[i]>=l&&y[i]>=d&&x[i]<=l+L&&y[i]<=d+L) vis[i]=1;fp(i,1,n) if(!vis[i]) zz=min(zz,x[i]),yy=max(yy,x[i]),xx=min(xx,y[i]),ss=max(ss,y[i]);if(solve(zz,yy,ss,xx,t+1,L)) return 1;fp(i,1,n) vis[i]=viss[i];}{re int zz=1e9,xx=1e9,yy=-1e9,ss=-1e9;fp(i,1,n) if(x[i]>=l&&y[i]<=u&&x[i]<=l+L&&y[i]>=u-L) vis[i]=1;fp(i,1,n) if(!vis[i]) zz=min(zz,x[i]),yy=max(yy,x[i]),xx=min(xx,y[i]),ss=max(ss,y[i]);if(solve(zz,yy,ss,xx,t+1,L)) return 1;fp(i,1,n) vis[i]=viss[i];}{re int zz=1e9,xx=1e9,yy=-1e9,ss=-1e9;fp(i,1,n) if(x[i]<=r&&y[i]>=d&&x[i]>=r-L&&y[i]<=d+L) vis[i]=1;fp(i,1,n) if(!vis[i]) zz=min(zz,x[i]),yy=max(yy,x[i]),xx=min(xx,y[i]),ss=max(ss,y[i]);if(solve(zz,yy,ss,xx,t+1,L)) return 1;fp(i,1,n) vis[i]=viss[i];}{re int zz=1e9,xx=1e9,yy=-1e9,ss=-1e9;fp(i,1,n) if(x[i]<=r&&y[i]<=u&&x[i]>=r-L&&y[i]>=u-L) vis[i]=1;fp(i,1,n) if(!vis[i]) zz=min(zz,x[i]),yy=max(yy,x[i]),xx=min(xx,y[i]),ss=max(ss,y[i]);if(solve(zz,yy,ss,xx,t+1,L)) return 1;return 0;}}int main(){n=gi();re int zz=1e9,xx=1e9,yy=-1e9,ss=-1e9;fp(i,1,n) x[i]=gi(),y[i]=gi(),zz=min(zz,x[i]),yy=max(yy,x[i]),xx=min(xx,y[i]),ss=max(ss,y[i]);re ll l=1,r=2e9,ans=1;while(l<=r){re ll mid=l+r>>1;memset(vis,0,sizeof(vis));if(solve(zz,yy,ss,xx,1,mid)) ans=mid,r=mid-1;else l=mid+1;}printf("%lld\n",ans);return 0;}
