1. 定義:
二維下點坐標 ( x , y )
空間里有兩個點( xi , yi ) ( xj , yj )
他們橫坐標距離為 dx = | xi - xj | ,縱坐標距離為 dy = | yi - yj |
他們的切比雪夫距離是橫坐標距離和縱坐標距離中值大的那一個 : max(dx,dy)
曼哈頓距離是橫坐標距離與縱坐標距離的和 : dx+dy
2. 互相轉換:
曼哈頓->切比雪夫:( x , y ) -> ( (x+y/2) , (x-y/2) )
這里用換完后的坐標計算曼哈頓,算出來的是原坐標的切比雪夫距離,下面同理。
切比雪夫->曼哈頓: ( x , y ) -> ( x+y , x-y )
3. 注意的點:
兩個點a,b。a到原點的曼哈頓距離為da,b到原點的曼哈頓距離為db,ab兩點的曼哈頓距離為dab,dab,da,db關系不大。切比雪夫同理。
4. 曼哈頓距離最小生成樹:
5. 題目:
bzoj3170: [Tjoi2013]松鼠聚會
題意:平面上n個點,求所有的點到其中某一個點的切比雪夫距離的最小值。0<=N<=10^5
做法:切比雪夫->曼哈頓,變成了求所有的點到其中某一個點的曼哈頓距離的最小值。
預處理,使得能在o(1)算出某個點到所有點的曼哈頓距離,1~n掃每個點,更新答案即可。
怎么預處理?
單獨考慮x軸時,點k到所有點的距離(x軸上)為(xk-x1)+...+(xk-x(k-1))+(x(k+1)-xk)+...+(xn-xk);
整理一哈~變成了((k-1)-(n-k) )*xk-(x1+...+x(k-1))+(x(k+1)+...+xn)
然后(x1+...+x(k-1))就是可愛的前綴和,(x(k+1)+...+xn)就是萌萌噠后綴和拉~
y軸同理~
坑點:在數據有點大,注意要先減后加,不然爆long long ,然后Inf要開到1e20
代碼:

1 #include <bits/stdc++.h> 2 #define nmax 100005 3 #define inf 1e20 4 5 using namespace std; 6 typedef long long ll; 7 ll qzx[nmax]={0},qzy[nmax]={0},ix[nmax],iy[nmax]; 8 struct px{ 9 ll num,id; 10 bool operator < (const px & a) const { return num<a.num; } 11 }; 12 px x[nmax],y[nmax]; 13 14 int main(){ 15 //freopen("owo.in","r",stdin); 16 ll n,inx,iny,totx=0,toty=0; 17 scanf("%lld",&n); 18 for (int i=1; i<=n; i++) { 19 scanf("%lld%lld",&inx,&iny); 20 x[i].num=(inx+iny); //先不除以2,后面再解決 21 y[i].num=(inx-iny); 22 totx+=x[i].num; 23 toty+=y[i].num; 24 x[i].id=y[i].id=i; 25 } 26 sort(x+1,x+n+1); 27 sort(y+1,y+n+1); 28 for (int i=1; i<=n; i++) { 29 qzx[i]=qzx[i-1]+x[i].num; 30 qzy[i]=qzy[i-1]+y[i].num; 31 ix[x[i].id]=i; 32 iy[y[i].id]=i; 33 } 34 ll ans=inf; 35 for (int i=1; i<=n; i++) { 36 ll tx=0,ty=0,txi=ix[i],tyi=iy[i]; 37 tx-=qzx[txi-1]; 38 tx+=(totx-qzx[txi]); 39 tx+=(x[txi].num*(txi-1-n+txi)); 40 ty-=qzy[tyi-1]; 41 ty+=(toty-qzy[tyi]); 42 ty+=(y[tyi].num*(tyi-1-n+tyi)); 43 ans=min(ans,tx+ty); 44 } 45 cout<<ans/2<<endl; 46 return 0; 47 }