bzoj3170: [Tjoi2013]松鼠聚会
题目描述:
有 $N$ 个小松鼠,它们的家用一个点 $x,y$ 表示,两个点的距离定义为:点 $(x,y)$ 和它周围的 $8$ 个点即上下左右四个点和对角的四个点,距离为 $1$ 。现在 $N$ 个松鼠要走到一个松鼠家去,求走过的最短距离。
思路:
这题主要就是切比雪夫距和曼哈顿距离的转换。
对于点 $(x,y)$ 的切比雪夫距离会等于 $(\frac{x+y}{2},\frac{x-y}{2})$ 。我们把距离转换,两次操作分别按 $x,y$ 排序,统计每个点到所有点的距离和。
以下代码:
#include<bits/stdc++.h> #define il inline #define LL long long #define _(d) while(d(isdigit(ch=getchar()))) using namespace std; const int N=1e5+5; int n;LL f1[N],f2[N]; struct node{ int v,id; }x[N],y[N]; il int read(){ int x,f=1;char ch; _(!)ch=='-'?f=-1:f;x=ch^48; _()x=(x<<1)+(x<<3)+(ch^48); return f*x; } bool cmp(node t1,node t2){ return t1.v<t2.v; } int main() { n=read(); if(n<=1){puts("0");return 0;} for(int i=1;i<=n;i++){ int a=read(),b=read(); x[i]=(node){a+b,i}; y[i]=(node){a-b,i}; } sort(x+1,x+1+n,cmp);sort(y+1,y+1+n,cmp); LL s1=0,s2=0; for(int i=1;i<=n;i++)s2+=x[i].v; for(int i=1;i<=n;i++){ s2-=x[i].v; f1[x[i].id]=1ll*(i-1)*x[i].v-s1+s2-1ll*(n-i)*x[i].v; s1+=x[i].v; } s1=0,s2=0; for(int i=1;i<=n;i++)s2+=y[i].v; for(int i=1;i<=n;i++){ s2-=y[i].v; f2[y[i].id]=1ll*(i-1)*y[i].v-s1+s2-1ll*(n-i)*y[i].v; s1+=y[i].v; } LL ans=1e18; for(int i=1;i<=n;i++)ans=min(ans,f1[i]+f2[i]); ans>>=1ll; printf("%lld\n",ans); return 0; }