模板—K-D-tree(P2479 [SDOI2010]捉迷藏)

  1 #include<algorithm>
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cmath>
  5 #define LL long long
  6 #define MAXN 1000100
  7 using namespace std;
  8 inline LL min(LL a,LL b){return a<b?a:b;}
  9 int n,cmpid;
 10 struct point
 11 {   
 12     int x[2];
 13     friend bool operator < (point a,point b)
 14     {return a.x[cmpid]<b.x[cmpid];}
 15 }p[MAXN];
 16 struct tree
 17 {
 18     point p;
 19     int mn[2],mx[2],l,r;
 20     #define l(x) tr[x].l
 21     #define r(x) tr[x].r
 22     #define p(x) tr[x].p
 23 }tr[MAXN];
 24 int Dis(point a,point b)
 25 {
 26     return abs(a.x[0]-b.x[0])+abs(a.x[1]-b.x[1]);
 27 }
 28 int min_dis(tree a,point b)
 29 {
 30     int x=max(a.mn[0]-b.x[0],0)+max(b.x[0]-a.mx[0],0);
 31     int y=max(a.mn[1]-b.x[1],0)+max(b.x[1]-a.mx[1],0);    
 32     return x+y;
 33 }
 34 int max_dis(tree a,point b)
 35 {
 36     int x=max(abs(a.mx[0]-b.x[0]),abs(b.x[0]-a.mn[0]));
 37     int y=max(abs(a.mx[1]-b.x[1]),abs(b.x[1]-a.mn[1]));
 38     return x+y;
 39 }
 40 struct KDtree
 41 {
 42     int root,tot,ans;
 43     #define INF 0x7fffffff
 44     void ask_max(point a,int x,int k)
 45     {
 46         if(!x)return;int tem;
 47         if((tem=Dis(p(x),a))>ans)ans=tem;
 48         int l=l(x),r=r(x);
 49         if(a.x[k]<p(x).x[k])swap(l,r);
 50         if(max_dis(tr[l],a)>ans)ask_max(a,l,k^1);
 51         if(max_dis(tr[r],a)>ans)ask_max(a,r,k^1);
 52     }
 53     int ask_max(point a)
 54     {
 55         ans=-INF;
 56         ask_max(a,root,0);
 57         return ans;
 58     }
 59     void ask_min(point a,int x,int k)
 60     {    
 61         if(!x)return;int tem;
 62         if((tem=Dis(p(x),a))<ans&&tem!=0)ans=tem;
 63         int l=l(x),r=r(x);
 64         if(a.x[k]>p(x).x[k])swap(l,r);//如果a在x有右半区间,先向右搜索。
 65         if(min_dis(tr[l],a)<ans)ask_min(a,l,k^1);
 66         if(min_dis(tr[r],a)<ans)ask_min(a,r,k^1);
 67     }
 68     int ask_min(point a)
 69     {
 70         ans=INF;
 71         ask_min(a,root,0);
 72         return ans;
 73     }
 74     void updata(int x)
 75     {
 76         if(!x)return;
 77         if(l(x))
 78             tr[x].mn[0]=min(tr[x].mn[0],tr[l(x)].mn[0]),
 79             tr[x].mn[1]=min(tr[x].mn[1],tr[l(x)].mn[1]),
 80             tr[x].mx[0]=max(tr[x].mx[0],tr[l(x)].mx[0]),
 81             tr[x].mx[1]=max(tr[x].mx[1],tr[l(x)].mx[1]);
 82         if(r(x))
 83             tr[x].mn[0]=min(tr[x].mn[0],tr[r(x)].mn[0]),    
 84             tr[x].mn[1]=min(tr[x].mn[1],tr[r(x)].mn[1]),
 85             tr[x].mx[0]=max(tr[x].mx[0],tr[r(x)].mx[0]),
 86             tr[x].mx[1]=max(tr[x].mx[1],tr[r(x)].mx[1]);
 87     }
 88     void build(int &x,int l,int r,int k)
 89     {
 90         if(l>r)return;
 91         x=++tot;int mid=(l+r)>>1;
 92         cmpid=k;
 93         nth_element(p+l,p+mid,p+r+1);
 94         p(x)=p[mid];
 95         tr[x].mn[0]=tr[x].mx[0]=p(x).x[0];
 96         tr[x].mn[1]=tr[x].mx[1]=p(x).x[1];
 97         build(l(x),l,mid-1,k^1);
 98         build(r(x),mid+1,r,k^1);
 99         updata(x);
100     }
101     void build()
102     {
103         tot=0;
104         build(root,1,n,0);
105     }
106 }T;
107 signed main()
108 {    
109     cin>>n;
110     for(int i=1;i<=n;i++)    
111         cin>>p[i].x[0]>>p[i].x[1];
112     T.build();    
113     LL ans=INF;
114     for(int i=1;i<=n;i++)
115     {
116         ans=min(ans,T.ask_max(p[i])-T.ask_min(p[i]));
117     }
118     cout<<ans<<endl;
119 }
120     
View Code

 放一下‘天使玩偶’的标程:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
using namespace std;
int n,m,cmpid;
struct point
{
    int x[2];
    friend bool operator < (point a,point b)
    {return a.x[cmpid]<b.x[cmpid];}
}p[510000];
struct tree
{
    point p;
    int mx[2],mn[2],l,r;
    #define l(x) tr[x].l
    #define r(x) tr[x].r
    #define p(x) tr[x].p
}tr[10000000];
int dis(point a,point b){return abs(a.x[0]-b.x[0])+abs(a.x[1]-b.x[1]);}
int min_dis(tree a,point b)
{
    int x=max(a.mn[0]-b.x[0],0)+max(b.x[0]-a.mx[0],0);
    int y=max(a.mn[1]-b.x[1],0)+max(b.x[1]-a.mx[1],0);
    return x+y;
}
struct KD_tree
{
    int root,tot,ans;
    #define INF 0x7fffffff
    void ask_min(point a,int x,int k)
    {
        if(!x)return;int tem;
        if((tem=dis(p(x),a))<ans)ans=tem;
        int l=l(x),r=r(x);
        if(a.x[k]>p(x).x[k])swap(l,r);
        if(min_dis(tr[l],a)<ans)ask_min(a,l,k^1);
        if(min_dis(tr[r],a)<ans)ask_min(a,r,k^1);
    }
    int ask_min(point a)
    {
        ans=INF;ask_min(a,root,0);
        return ans;
    }
    void updata(int x)
    {
        if(!x)return;
        if(l(x))
            tr[x].mn[0]=min(tr[x].mn[0],tr[l(x)].mn[0]),
            tr[x].mn[1]=min(tr[x].mn[1],tr[l(x)].mn[1]),
            tr[x].mx[0]=max(tr[x].mx[0],tr[l(x)].mx[0]),
            tr[x].mx[1]=max(tr[x].mx[1],tr[l(x)].mx[1]);
        if(r(x))
            tr[x].mn[0]=min(tr[x].mn[0],tr[r(x)].mn[0]),
            tr[x].mn[1]=min(tr[x].mn[1],tr[r(x)].mn[1]),
            tr[x].mx[0]=max(tr[x].mx[0],tr[r(x)].mx[0]),
            tr[x].mx[1]=max(tr[x].mx[1],tr[r(x)].mx[1]);
    }
    void build(int &x,int l,int r,int k)
    {
        if(l>r)return;
        x=++tot;int mid=(l+r)>>1;
        cmpid=k;
        nth_element(p+l,p+mid,p+r+1);
        p(x)=p[mid];
        tr[x].mn[0]=tr[x].mx[0]=p(x).x[0];
        tr[x].mn[1]=tr[x].mx[1]=p(x).x[1];
        build(l(x),l,mid-1,k^1);
        build(r(x),mid+1,r,k^1);
        updata(x);
    }
    void build(){tot=0;build(root,1,n,0);}
    void insert(point a,int &x,int k)
    {
        if(!x)
        {
            x=++tot;p(x)=a;
            tr[x].mn[0]=tr[x].mx[0]=p(x).x[0];
            tr[x].mn[1]=tr[x].mx[1]=p(x).x[1];
            return;
        }
        if(a.x[k]<p(x).x[k])insert(a,l(x),k^1);
        else insert(a,r(x),k^1);
        updata(x);
    }
    void insert(point a){insert(a,root,0);}
}T;
signed main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>p[i].x[0]>>p[i].x[1];
    T.build();int t,x,y;
    for(int i=1;i<=m;i++)
    {    
        cin>>t>>x>>y;
        if(t==1)T.insert((point){x,y});
        else cout<<T.ask_min((point){x,y})<<endl;;
    }
}
原文地址:https://www.cnblogs.com/Al-Ca/p/11297379.html