BZOJ1941: [Sdoi2010]Hide and Seek kdtree

题目大意:给定n个点,求其中一个点使得到其它所有点中的最远距离和最近距离差值最小,距离定义为曼哈顿距离。
N<=500000,0<=X,Y<=10^8
用kdtree暴力枚举每一个点即可。注意算距离时不能算自己。
最远距离的估价为max(abs(x-xmin)、abs(x-xmax))+max(abs(y-ymin)、abs(y-ymax))。

#include<cstdio>
#include<algorithm>
using namespace std;
typedef int pnt[2];
inline int dis(pnt a,pnt b)
{
    return abs(a[0]-b[0])+abs(a[1]-b[1]);
}
struct node
{
    pnt v,mn,mx;
    node *l,*r;
    node(int x,int y):l(0),r(0)
    {
        v[0]=mn[0]=mx[0]=x,
        v[1]=mn[1]=mx[1]=y;
    }
    static const int inf=0x7fffffff;
    inline void up()
    {
        if(l)
        {
            mn[0]=min(mn[0],l->mn[0]);
            mn[1]=min(mn[1],l->mn[1]);
            mx[0]=max(mx[0],l->mx[0]);
            mx[1]=max(mx[1],l->mx[1]);
        }
        if(r)
        {
            mn[0]=min(mn[0],r->mn[0]);
            mn[1]=min(mn[1],r->mn[1]);
            mx[0]=max(mx[0],r->mx[0]);
            mx[1]=max(mx[1],r->mx[1]);
        }
    }
    inline int min_dis(pnt p)
    {
        if(!this) return inf;
        int res=0;
        if(p[0]<mn[0]) res+=mn[0]-p[0];
        else if(mx[0]<p[0]) res+=p[0]-mx[0];
        if(p[1]<mn[1]) res+=mn[1]-p[1];
        else if(mx[1]<p[1]) res+=p[1]-mx[1];
        return res;
    }
    inline int max_dis(pnt p)
    {
        return this?max(abs(p[0]-mn[0]),abs(mx[0]-p[0]))+max(abs(p[1]-mn[1]),abs(mx[1]-p[1])):-inf;
    }
    void get_min(pnt p,int &ans)
    {
        if(!this) return;
        if(p[0]!=v[0]||p[1]!=v[1]) ans=min(ans,dis(p,v));
        int ldis=l->min_dis(p),rdis=r->min_dis(p);
        if(ldis<rdis)
        {
            if(ldis<ans) l->get_min(p,ans);
            if(rdis<ans) r->get_min(p,ans);
        }
        else
        {
            if(rdis<ans) r->get_min(p,ans);
            if(ldis<ans) l->get_min(p,ans);
        }
    }
    void get_max(pnt p,int &ans)
    {
        if(!this) return;
        if(p[0]!=v[0]||p[1]!=v[1]) ans=max(ans,dis(p,v));
        int ldis=l->max_dis(p),rdis=r->max_dis(p);
        if(ldis>rdis)
        {
            if(ldis>ans) l->get_max(p,ans);
            if(rdis>ans) r->get_max(p,ans);
        }
        else
        {
            if(rdis>ans) r->get_max(p,ans);
            if(ldis>ans) l->get_max(p,ans);
        }
    }
};
typedef unsigned long long ll;
inline bool cmp0(const ll &a,const ll &b)
{
    return int(a)<int(b);
}
inline bool cmp1(const ll &a,const ll &b)
{
    return int(a>>32)<int(b>>32);
}
struct kdtree
{
    node *rt;
    static node* build(ll *l,ll *r,bool k)
    {
        if(l==r) return 0;
        ll* mid=l+(r-l>>1);
        nth_element(l,mid,r,k?cmp1:cmp0);
        node *kre=new node(int(*mid),int((*mid)>>32));
        kre->l=build(l,mid,!k);
        kre->r=build(mid+1,r,!k);
        kre->up();
        return kre;
    }
    kdtree(ll a[],int len):rt(build(a,a+len,0)){}
    inline int query_min(int x,int y)
    {
        int ans=node::inf;
        pnt p={x,y};
        rt->get_min(p,ans);
        return ans;
    }
    inline int query_max(int x,int y)
    {
        int ans=-node::inf;
        pnt p={x,y};
        rt->get_max(p,ans);
        return ans;
    }
};
int n;
ll __p[500000];
int main()
{
    scanf("%d",&n);
    unsigned int x;
    for(int i=0;i<n;++i)
    {
        scanf("%llu%u",__p+i,&x);
        __p[i]|=ll(x)<<32;
    }
    kdtree tr(__p,n);
    int ans=node::inf;
    for(int i=0;i<n;++i)
    {
        int mid=tr.query_min(int(__p[i]),int(__p[i]>>32));
        int mad=tr.query_max(int(__p[i]),int(__p[i]>>32));
        if(mad-mid<ans) ans=mad-mid;
    }
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值