BZOJ 3170: [Tjoi 2013]松鼠聚会

来源:互联网 发布:邮币卡行情分析软件 编辑:程序博客网 时间:2024/03/29 16:36

题意:有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
原创粉丝点击