[bzoj3210]花神的浇花集会

题目大意

给你n个点,要你求一个点,横纵坐标是范围在0到100000之间的整数,使得该点到所有给定的点的切比雪夫距离最小。
n≤100000 0≤坐标范围≤100000

预备

首先两个点(x1,y1),(x2,y2)的切比雪夫距离为 max(|x1x2|,|y1y2|)
然后把每个点的坐标变成(x+y,x-y),两个点切比雪夫距离变成了它们的曼哈顿距离。

满分算法

方法就很显然了。把每个坐标转成(x+y,x-y),然后由于求的是曼哈顿距离,可以把答案的横纵坐标分开来求,然后得到一个点(x,y)
然后把这个点坐标转回去就可以了吗?
不行!
答案求的是整点,然而这样求出来的坐标,奇偶性可能不一样,也就是转回去后可能是小数(如样例中求出的答案,转回去坐标是(1.5,1.5))。所以,对于奇偶性相同,直接转回去即可,如果不同,答案就在这个点上下左右四个整点中找。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

const int maxn=100005;

typedef long long LL;

int n,x[maxn],y[maxn],xx[maxn],yy[maxn],ansx,ansy,X,Y;

LL ans,s;

double tx,ty;

int main()
{
    scanf("%d",&n);
    for (int i=0;i<n;i++)
    {
        scanf("%d%d",&x[i],&y[i]);
        xx[i]=x[i]+y[i];
        yy[i]=x[i]-y[i];
    }
    int j=0;
    sort(xx,xx+n);
    sort(yy,yy+n);
    X=xx[n/2]; Y=yy[n/2];
    if ((X+Y)%2==0)
    {
        ansx=(X+Y)/2;
        ansy=(X-Y)/2;
        ans=0;
        for (int i=0;i<n;i++) ans+=max(abs(ansx-x[i]),abs(ansy-y[i]));
        printf("%lld\n",ans);
    }else
    {
        tx=(double)(X+Y)/2;
        ty=(double)(X-Y)/2;
        ans=1e17;
        for (int a=0;a<2;a++)
        {
            int p=tx+a-0.5;
            if (p>=0 && p<=1e5)
            {
                for (int b=0;b<2;b++)
                {
                    int q=ty+b-0.5;
                    if (q>=0 && q<=1e5)
                    {
                        s=0;
                        for (int i=0;i<n;i++) s+=max(abs(p-x[i]),abs(q-y[i]));
                        if (s<ans) ans=s;
                    }
                }
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值