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;
}
View Code

 

posted @ 2019-03-06 07:49  Jessiejzy  阅读(131)  评论(0编辑  收藏  举报