bzoj1052: [HAOI2007]覆盖问题(二分+构造)
Posted Sakits
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1052: [HAOI2007]覆盖问题(二分+构造)相关的知识,希望对你有一定的参考价值。
貌似又写出了常数挺优(至少不劣)的代码>v< 930+人AC #49
写了个O(nlogn)貌似比一些人O(n)还快2333333
这题还是先二分答案,check比较麻烦
显然正方形一定以最左上或最右上或最左下或最右下的点为端点来盖,盖了一个之后再拿一个枚举剩下的点作为四个端点来盖,最后一个直接判断剩下的点能不能一次性盖就好了
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<algorithm> #define ll long long using namespace std; const int maxn=20010,inf=1e9; typedef int poi[maxn]; poi x,y; int n,m,l,r,mid,mxx,mxy,mnx,mny; void read(int &k) { int f=1;k=0;char c=getchar(); while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar(); while(c<=‘9‘&&c>=‘0‘)k=k*10+c-‘0‘,c=getchar(); k*=f; } void getmax(poi x,poi y,int tot,int &mxx,int &mxy,int &mnx,int &mny) { mxx=mxy=-inf;mnx=mny=inf; for(int i=1;i<=tot;i++) { mxx=max(mxx,x[i]);mnx=min(mnx,x[i]); mxy=max(mxy,y[i]);mny=min(mny,y[i]); } } bool check(poi x,poi y,int tot,int dep) { int mxx,mxy,mnx,mny,tot2; if(dep>2) { getmax(x,y,tot,mxx,mxy,mnx,mny); return max(mxx-mnx,mxy-mny)<=mid; } getmax(x,y,tot,mxx,mxy,mnx,mny); tot2=0;poi x2,y2; for(int i=1;i<=tot;i++) if(x[i]>mnx+mid||y[i]<mxy-mid)x2[++tot2]=x[i],y2[tot2]=y[i]; if(check(x2,y2,tot2,dep+1))return 1; tot2=0; for(int i=1;i<=tot;i++) if(x[i]<mxx-mid||y[i]<mxy-mid)x2[++tot2]=x[i],y2[tot2]=y[i]; if(check(x2,y2,tot2,dep+1))return 1; tot2=0; for(int i=1;i<=tot;i++) if(x[i]>mnx+mid||y[i]>mny+mid)x2[++tot2]=x[i],y2[tot2]=y[i]; if(check(x2,y2,tot2,dep+1))return 1; tot2=0; for(int i=1;i<=tot;i++) if(x[i]<mxx-mid||y[i]>mny+mid)x2[++tot2]=x[i],y2[tot2]=y[i]; if(check(x2,y2,tot2,dep+1))return 1; return 0; } int main() { read(n); for(int i=1;i<=n;i++)read(x[i]),read(y[i]); getmax(x,y,n,mxx,mxy,mnx,mny); l=1;r=max(mxx-mnx,mxy-mny); while(l<r) { mid=(l+r)>>1; if(check(x,y,n,1))r=mid; else l=mid+1; } printf("%d\n",l); return 0; }
以上是关于bzoj1052: [HAOI2007]覆盖问题(二分+构造)的主要内容,如果未能解决你的问题,请参考以下文章