码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ_3170_[Tjoi2013]松鼠聚会_切比雪夫距离+前缀和

时间:2018-02-21 23:04:21      阅读:193      评论:0      收藏:0      [点我收藏+]

标签:n+1   blog   amp   names   mic   mes   tmp   stdio.h   上下左右   

BZOJ_3170_[Tjoi2013]松鼠聚会_切比雪夫距离+前缀和

题意:有N个小松鼠,它们的家用一个点x,y表示,两个点的距离定义为:点(x,y)和它周围的8个点即上下左右四个点和对角的四个点,距离为1。现在N个松鼠要走到一个松鼠家去,求走过的最短距离。

 

分析:

这啥奇怪的距离表示啊。推了一下发现是max{ abs(x[i] - x[j]),abs(y[i] - y[j] }。然后就不会了。

看题姐:这个东西叫切比雪夫距离,可以和曼哈顿距离转化。

把坐标变成(x[i]-y[i])/2,(x[i]+y[i])/2,求一遍曼哈顿距离,展开再分类讨论一下发现和上面那个式子是等价的。

太强了太强了。

曼哈顿距离就好办了。可以对x轴y轴分别求前缀和。

快速求出任意一点到其他所有点的距离:x[i]*(i-1)-s[i-1]+s[n]-s[i]-(n-i)*x[i](s为前缀和。)

 

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 100050
#define LL long long
struct A{
    int id,x,y;
}a[N];
int n;
LL xx[N],yy[N],ans,s[N];
bool cmp1(const A &g,const A &h){
    return g.x<h.x;
}
bool cmp2(const A &g,const A &h){
    return g.y<h.y;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        a[i].id=i;
        scanf("%d%d",&a[i].x,&a[i].y);
        int tmp=a[i].x;
        a[i].x=a[i].x+a[i].y;
        a[i].y=tmp-a[i].y;
    }
    sort(a+1,a+n+1,cmp1);
    for(int i=1;i<=n;i++){
        s[i]=s[i-1]+a[i].x;
    }
    for(int i=1;i<=n;i++){
        xx[a[i].id]=1ll*a[i].x*(i-1)-s[i-1]+s[n]-s[i]-1ll*(n-i)*a[i].x;
    }
    sort(a+1,a+n+1,cmp2);
    for(int i=1;i<=n;i++){
        s[i]=s[i-1]+a[i].y;
    }
    LL ans=1ll<<60;
    for(int i=1;i<=n;i++){
        yy[a[i].id]=1ll*a[i].y*(i-1)-s[i-1]+s[n]-s[i]-1ll*(n-i)*a[i].y;
        ans=min(ans,xx[a[i].id]+yy[a[i].id]);
    }
    printf("%lld\n",ans>>1);
}	

 

BZOJ_3170_[Tjoi2013]松鼠聚会_切比雪夫距离+前缀和

标签:n+1   blog   amp   names   mic   mes   tmp   stdio.h   上下左右   

原文地址:https://www.cnblogs.com/suika/p/8457660.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!