您的位置:首页 > 其它

BZOJ1941: [Sdoi2010]Hide and Seek kdtree

2017-01-03 15:26 453 查看
题目大意:给定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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: