bzoj 1941: [Sdoi2010]Hide and Seek KDtree

来源:互联网 发布:泡泡堂有mac版吗 编辑:程序博客网 时间:2024/05/21 19:36

题意

给出n个点,求每个点到最远点距离-到最近点距离(除自己之外)的最小值。
n<=500000

分析

直接用KDtree找每个点的最远点和最近点即可。
T了一晚上,因为把nth_element函数的位置放错了。

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>using namespace std;const int N=500005;const int inf=1e9;int n,ans,D,root;struct kdt{int mn[2],mx[2],d[2],l,r;}t[N];bool cmp(kdt a,kdt b){    return a.d[D]<b.d[D]||a.d[D]==b.d[D]&&a.d[D^1]<b.d[D^1];}void updata(int x,int y){    t[x].mn[0]=min(t[x].mn[0],t[y].mn[0]);    t[x].mn[1]=min(t[x].mn[1],t[y].mn[1]);    t[x].mx[0]=max(t[x].mx[0],t[y].mx[0]);    t[x].mx[1]=max(t[x].mx[1],t[y].mx[1]);}int build(int l,int r,int dd){    D=dd;int mid=(l+r)/2;    nth_element(t+l,t+mid,t+r+1,cmp);    t[mid].mn[0]=t[mid].mx[0]=t[mid].d[0];    t[mid].mn[1]=t[mid].mx[1]=t[mid].d[1];    if (l<mid) t[mid].l=build(l,mid-1,dd^1),updata(mid,t[mid].l);    if (r>mid) t[mid].r=build(mid+1,r,dd^1),updata(mid,t[mid].r);    return mid;}int get_mn(int d,int x,int y){    int ans=0;    ans+=max(0,x-t[d].mx[0])+max(0,t[d].mn[0]-x);    ans+=max(0,y-t[d].mx[1])+max(0,t[d].mn[1]-y);    return ans;}void findmn(int d,int x,int y){    int w=abs(t[d].d[0]-x)+abs(t[d].d[1]-y),dl=inf,dr=inf;    if (w) ans=min(ans,w);    if (t[d].l) dl=get_mn(t[d].l,x,y);    if (t[d].r) dr=get_mn(t[d].r,x,y);    if (dl<dr)    {        if (dl<ans) findmn(t[d].l,x,y);        if (dr<ans) findmn(t[d].r,x,y);    }    else    {        if (dr<ans) findmn(t[d].r,x,y);        if (dl<ans) findmn(t[d].l,x,y);    }}int get_mx(int d,int x,int y){    int ans=0;    ans+=max(abs(x-t[d].mn[0]),abs(x-t[d].mx[0]));    ans+=max(abs(y-t[d].mn[1]),abs(y-t[d].mx[1]));    return ans;}void findmx(int d,int x,int y){    int w=abs(t[d].d[0]-x)+abs(t[d].d[1]-y),dl=-inf,dr=-inf;    ans=max(ans,w);    if (t[d].l) dl=get_mx(t[d].l,x,y);    if (t[d].r) dr=get_mx(t[d].r,x,y);    if (dl>dr)    {        if (dl>ans) findmx(t[d].l,x,y);        if (dr>ans) findmx(t[d].r,x,y);    }    else    {        if (dr>ans) findmx(t[d].r,x,y);        if (dl>ans) findmx(t[d].l,x,y);    }}int main(){    scanf("%d",&n);    for (int i=1;i<=n;i++) scanf("%d%d",&t[i].d[0],&t[i].d[1]);    root=build(1,n,0);    int Ans=inf;    for (int i=1;i<=n;i++)    {        ans=inf;        findmn(root,t[i].d[0],t[i].d[1]);        int mn=ans;ans=-inf;        findmx(root,t[i].d[0],t[i].d[1]);        Ans=min(Ans,ans-mn);    }    printf("%d",Ans);    return 0;}
0 0
原创粉丝点击