bzoj 1941 kd-tree求最大最小曼哈頓距離

給出平面上n個點,求距離每個點最大距離減最小距離(不算自己)的最小值;(曼哈頓距離)

n<=500000;

#include <iostream>  
#include <algorithm>  
#include <cstring>  
#include <cstdio>  
#include <cmath>  
using namespace std;  
#define ll long long  
#define maxn 600000  
#define inf 2100000000  
int read()  
{  
    int x=0,f=1;char ch=getchar();  
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}  
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}  
    return x*f;  
}  
int x[maxn],y[maxn];  
int D,n,m,rt;  
struct node  
{  
    int d[2],mx[2],mn[2],l,r;  
    friend bool operator < (node aa,node bb)  
    {  
        return aa.d[D]<bb.d[D];  
    }  
}p[maxn];  
int dis(node a,node b)  
{  
        return abs(a.d[1]-b.d[1])+abs(a.d[0]-b.d[0]);  
}  
struct tree  
{  
    node t[maxn],T;  
    int ans;  
    void update(int k){  
        int l=t[k].l,r=t[k].r;  
        for(int i=0;i<2;i++)  
        {  
            t[k].mn[i]=t[k].mx[i]=t[k].d[i];  
            if(l)t[k].mn[i]=min(t[k].mn[i],t[l].mn[i]);  
            if(r)t[k].mn[i]=min(t[k].mn[i],t[r].mn[i]);  
            if(l)t[k].mx[i]=max(t[k].mx[i],t[l].mx[i]);  
            if(r)t[k].mx[i]=max(t[k].mx[i],t[r].mx[i]);  
        }  
    }  
    int build(int l,int r,int now){  
        D=now;  
        int mid=(l+r)>>1;  
        nth_element(p+l,p+mid,p+r+1);  
        t[mid]=p[mid];  
        for(int i=0;i<2;i++)  
            t[mid].mn[i]=t[mid].mx[i]=t[mid].d[i];  
        if(l<mid)t[mid].l=build(l,mid-1,now^1);  
        if(r>mid)t[mid].r=build(mid+1,r,now^1);  
        update(mid);  
        return mid;  
    }  
    int getmn(node a){  
        int ans=0;  
        for(int i=0;i<2;i++)  
        {  
            ans+=max(T.d[i]-a.mx[i],0);  
            ans+=max(a.mn[i]-T.d[i],0);  
        }  
        return ans;  
    }  
    int getmx(node a){  
        int ans=0;  
        for(int i=0;i<2;i++)  
            ans+=max(abs(T.d[i]-a.mx[i]),abs(T.d[i]-a.mn[i]));  
        return ans;  
    }  
   
    void querymx(int x)  
    {  
        int l=t[x].l;  
        int r=t[x].r;  
        int tmp=dis(t[x],T);  
        ans=max(ans,tmp);  
        int ansl=-inf,ansr=-inf;  
        if(l) ansl=getmx(t[l]);  
        if(r) ansr=getmx(t[r]);  
        if(ansl>ansr)  
        {  
            if(ansl>ans) querymx(l);  
            if(ansr>ans) querymx(r);  
        }  
        else  
        {  
            if(ansr>ans) querymx(r);  
            if(ansl>ans) querymx(l);  
        }  
    }  
    void querymn(int x)  
    {  
        int l=t[x].l;  
        int r=t[x].r;  
        int tmp=dis(t[x],T);  
        if(tmp) ans=min(ans,tmp);  
        int ansl=inf,ansr=inf;  
        if(l) ansl=getmn(t[l]);  
        if(r) ansr=getmn(t[r]);  
        if(ansl<ansr)  
        {  
            if(ansl<ans) querymn(l);  
            if(ansr<ans) querymn(r);  
        }  
        else  
        {  
            if(ansr<ans) querymn(r);  
            if(ansl<ans) querymn(l);  
        }  
    }  
    int query(int f,int x,int y)  
    {  
        T.d[0]=x;T.d[1]=y;  
        if(f==0)ans=inf,querymn(rt);  
        else ans=-inf,querymx(rt);  
        return ans;  
    }  
}kd;  
   
int main()  
{  
    n=read();  
    for(int i=1;i<=n;i++)  
    {  
        x[i]=read(),y[i]=read();  
        p[i].d[0]=x[i];p[i].d[1]=y[i];  
    }  
    rt=kd.build(1,n,0);  
    int ans=inf;  
    for(int i=1;i<=n;i++)  
    {  
        int mn=kd.query(0,x[i],y[i]);  
        int mx=kd.query(1,x[i],y[i]);  
        ans=min(ans,mx-mn);  
    }  
    printf("%d\n",ans);  
    return 0;  
}  

發佈了307 篇原創文章 · 獲贊 3 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章