Description
有N个小松鼠,它们的家用一个点x,y表示,两个点的距离定义为:点(x,y)和它周围的8个点即上下左右四个点和对角的四个点,距离为1。现在N个松鼠要走到一个松鼠家去,求走过的最短距离。
Input
第一行给出数字N,表示有多少只小松鼠。0<=N<=10^5
下面N行,每行给出x,y表示其家的坐标。
-10^9<=x,y<=10^9
Output
表示为了聚会走的路程和最小为多少。
Sample Input
6
-4 -1
-1 -2
2 -4
0 2
0 3
5 -2
-4 -1
-1 -2
2 -4
0 2
0 3
5 -2
Sample Output
20
HINT
……好菜啊才会切比雪夫距离……
根据题意可以斜走,那么(x1,y1)(x2,y2)之间的距离就是max(|x1-x2|,|y1-y2|)
然后……我就不会了= =
百度了一下发现这个东西叫做切比雪夫距离……
然后它可以转化成曼哈顿距离去的。
具体过程差不多就是拆成4个,取max这样子
反正推出来是(x,y)变成((x-y)/2,(x+y)/2)
然后距离就变成了两点之间的曼哈顿距离。
如何统计其它点到这个点的曼哈顿距离……
只要统计比x小的和与个数、比x大的和与个数就可以算出x到其它所有点的距离之和,
y同理,,不难理解吧……
就是说x和y是独立的……然后分开来求就通过去掉绝对值来搞。。
那么这个乱搞就好了……
树状数组什么的还要离散化,直接排序+二分水水掉……
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int
N=100005;
int n;
ll Y[N],sumx[N],sumy[N];
struct node{ll l,r;}X[N];
bool cmp(node p,node q){return p.l<q.l;}
void Pre(){
int t1,t2;
for (int i=1;i<=n;i++){
scanf("%d%d",&t1,&t2);
X[i].l=t1-t2,X[i].r=t1+t2;
Y[i]=X[i].r;
}
sort(X+1,X+1+n,cmp),sort(Y+1,Y+1+n);
sumx[0]=0LL,sumy[0]=0LL;
for (int i=1;i<=n;i++) sumx[i]=sumx[i-1]+X[i].l;
for (int i=1;i<=n;i++) sumy[i]=sumy[i-1]+Y[i];
}
ll solve(){
ll ans=1e18;
for (int i=1;i<=n;i++){
ll t=X[i].l*(i-1)-sumx[i-1]+sumx[n]-sumx[i]-X[i].l*(n-i);
int j=lower_bound(Y+1,Y+1+n,X[i].r)-Y;
t+=X[i].r*(j-1)-sumy[j-1]+sumy[n]-sumy[j]-X[i].r*(n-j);
ans=min(ans,t);
}
return ans>>1LL;
}
int main(){
scanf("%d",&n);
Pre();
printf("%lld\n",solve());
return 0;
}