玄学分治做法 %%% http://www.cnblogs.com/ccz181078/p/5603283.html
三个点(x1,y1),(x2,y2),(x3,y3)的两两曼哈顿距离和为2(max(x1,x2,x3)+max(y1,y2,y3)-min(x1,x2,x3)-min(y1,y2,y3))
四项三个点 由抽屉原理 必至少有两项是同一个点的
那么最大值就是
max((x+y)max-xmin-ymin,xmax+ymax-(x+y)min,(x-y)max-xmin+ymax,xmax-ymin-(x-y)min)
最小值分治跟最近点对很相似
这里为了防卡 把xy交换了
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int N=100005;
struct Point{
int x,y;
void read(){
::read(x); ::read(y);
}
bool operator < (const Point &B)const {
return x==B.x?y<B.y:x<B.x;
}
}P[N],tmp[N];
int pnt=0;
bool cmp(Point A,Point B){
return A.y==B.y?A.x<B.x:A.y<B.y;
}
inline int Calc(Point A,Point B,Point C){
return max(A.x,max(B.x,C.x))-min(A.x,min(B.x,C.x))+max(A.y,max(B.y,C.y))-min(A.y,min(B.y,C.y));
}
int n;
int Ans=1<<30;
inline void Solve(int l,int r){
if (r-l<15){
for (int i=l;i<=r;i++) for (int j=i+1;j<=r;j++) for (int k=j+1;k<=r;k++) Ans=min(Ans,Calc(P[i],P[j],P[k]));
return;
}
int mid=(l+r)>>1;
Solve(l,mid); Solve(mid,r);
pnt=0;
for (int i=mid;i<=r;i++) if (abs(P[i].x-P[mid].x)<Ans) tmp[++pnt]=P[i]; else break;
for (int i=mid-1;i>=l;i--) if (abs(P[i].x-P[mid].x)<Ans) tmp[++pnt]=P[i]; else break;
sort(tmp+1,tmp+pnt+1,cmp);
int L=1,R;
for (R=3;R<=pnt;R++){
while (abs(tmp[R].y-tmp[L].y)>=Ans) L++;
for (int j=L;j<R;j++)
for (int k=j+1;k<R;k++)
Ans=min(Ans,Calc(tmp[j],tmp[k],tmp[R]));
}
}
int main(){
int xmax,xmin,ymax,ymin,xpymax,xpymin,xmymax,xmymin;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
xmax=ymax=xpymax=xmymax=-1<<30;
xmin=ymin=xpymin=xmymin=1<<30;
read(n);
for (int i=1;i<=n;i++){
P[i].read(); swap(P[i].x,P[i].y);
xmax=max(xmax,P[i].x),xmin=min(xmin,P[i].x);
ymax=max(ymax,P[i].y),ymin=min(ymin,P[i].y);
xpymax=max(xpymax,P[i].x+P[i].y),xpymin=min(xpymin,P[i].x+P[i].y);
xmymax=max(xmymax,P[i].x-P[i].y),xmymin=min(xmymin,P[i].x-P[i].y);
}
printf("%d\n",2*max(max(xpymax-xmin-ymin,xmax+ymax-xpymin),max(xmymax-xmin+ymax,xmax-ymin-xmymin)));
sort(P+1,P+n+1);
Solve(1,n);
printf("%d\n",Ans*2);
return 0;
}
这道题正解是不是线段树啊
我想了想三个点的相对位置 一共七八种吧 好麻烦
不过Claris把坐标转来转去 最终发现不对称的只有两种了
厉害啊
http://www.cnblogs.com/clrs97/p/4872267.html
跟最近点对很相似