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

 

转载于:https://www.cnblogs.com/Jessie-/p/10481054.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值