BZOJ 3170: [Tjoi 2013]松鼠聚会

题意:有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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值