bzoj 3170: [Tjoi 2013]松鼠聚会

3170: [Tjoi 2013]松鼠聚会

Description

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

Input

第一行给出数字N,表示有多少只小松鼠。0<=N<=10^5
下面N行,每行给出x,y表示其家的坐标。
-10^9<=x,y<=10^9

Output

表示为了聚会走的路程和最小为多少。

Sample Input

6
-4 -1
-1 -2
2 -4
0 2
0 3
5 -2

Sample Output

20
题解:
直接搞o(n)的算法吧。。
首先这题的距离应该是dis(x,y)=max{|x-y|,|x+y|};
这是切比雪夫距离,可以去网上搜搜它与曼哈顿距离的转化,就是把(x,y)变为((x-y)/2,(x+y)/2)
方便起见,我没有除2,最后输出答案的时候再除就行了。。
然后就是乱搞了,按某个轴排个序,再求每个点到其他点距离的前缀和,后缀和。搞2遍。。
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
const int N=500005;
struct node
{
    ll a,b;
    int id;
}p[N];
int n,i,x,y;
ll ans,lx[N],ly[N],rx[N],ry[N];
bool cmpx(const node&x,const node&y)
{
    return x.a<y.a;
}
bool cmpy(const node&x,const node&y)
{
    return x.b<y.b;
}
int main()
{
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d%d",&x,&y);
        p[i].a=x-y;
        p[i].b=x+y;
        p[i].id=i;
    }
    sort(p+1,p+n+1,cmpx);
    for(i=1;i<=n;i++)
        lx[p[i].id]=lx[p[i-1].id]+(p[i].a-p[i-1].a)*(i-1);
    for(i=n;i>=1;i--)
        rx[p[i].id]=rx[p[i+1].id]+(p[i+1].a-p[i].a)*(n-i);
    sort(p+1,p+n+1,cmpy);
    for(i=1;i<=n;i++)
        ly[p[i].id]=ly[p[i-1].id]+(p[i].b-p[i-1].b)*(i-1);
    for(i=n;i>=1;i--)
        ry[p[i].id]=ry[p[i+1].id]+(p[i+1].b-p[i].b)*(n-i);
    ans=1e16;
    for(i=1;i<=n;i++)
        ans=min(ans,lx[i]+rx[i]+ly[i]+ry[i]);
    cout<<ans/2;
    return 0;
}

 

posted @ 2016-05-21 20:41  lwq12138  阅读(461)  评论(0编辑  收藏  举报