题意:有N个小松鼠,它们的家用一个点x,y表示,两个点的距离定义为:点(x,y)和它周围的8个点即上下左右四个点和对角的四个点,距离为1。现在N个松鼠要走到一个松鼠家去,求走过的最短距离。
其实题目中定义的距离就是切比雪夫距离,我们用一个神奇的变换搞成曼哈顿距离(bzoj3210),对于一个i,快速计算其它点到它的曼哈顿距离,前缀和就可以了。
Tips:这题肯定是原来的点,连奇偶都不用判了
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=100000+10;
struct node
{
int x,y;
}a[maxn];
int x[maxn],y[maxn],n;
long long sumx[maxn],sumy[maxn],ans=(long long)100000000*(long long)100000000;
int find1(int v)
{
int l=1,r=n;
while(l<=r)
{
int mid=(l+r)>>1;
if(x[mid]==v) return mid;
if(x[mid]<v) l=mid+1;
if(x[mid]>v) r=mid-1;
}
}
int find2(int v)
{
int l=1,r=n;
while(l<=r)
{
int mid=(l+r)>>1;
if(y[mid]==v) return mid;
if(y[mid]<v) l=mid+1;
if(y[mid]>v) r=mid-1;
}
}
int main()
{
//freopen("3170.in","r",stdin);
//freopen("3170.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int c,d;scanf("%d%d",&c,&d);
a[i].x=c+d;a[i].y=c-d;
x[i]=c+d;y[i]=c-d;
}
sort(x+1,x+n+1);
sort(y+1,y+n+1);
for(int i=1;i<=n;i++)
{
sumx[i]=sumx[i-1]+x[i];
sumy[i]=sumy[i-1]+y[i];
}
for(int i=1;i<=n;i++)
{
int px=find1(a[i].x),py=find2(a[i].y);
long long res=(long long)px*a[i].x-sumx[px]+(sumx[n]-sumx[px])-(long long)(n-px)*a[i].x;
res+=(long long)py*a[i].y-sumy[py]+(sumy[n]-sumy[py])-(long long)(n-py)*a[i].y;
ans=min(ans,res);
}
ans/=2;
printf("%lld\n",ans);
return 0;
}