【BZOJ2648】SYJ摆棋子 KD-Tree

KD-Tree这样缩写看起来有一种莫名的喜感23333

建树的时候和k远点对那个“最远+欧几里得KD-Tree”距离没什么区别,但是查询的时候“最近+曼哈顿KD-Tree”还是有一些区别

首先,KDT上的一个节点代表一个矩形方块,当我们做估价函数的时候,如果被查询点的某一维夹在矩形方块的某一维之间,那么这一维的估价值就是0,而不是到这一维两个边界的距离的较小值。因为我们的估价函数实际上是假设这个矩形的每一个方格上都有点存在,如果取边界可能不是最优。

/************************************************************** 
    Problem: 2648 
    User: RicardoWang 
    Language: C++ 
    Result: Accepted 
    Time:13032 ms 
    Memory:32528 kb 
****************************************************************/
  
#include<cstdlib> 
#include<cstdio> 
#include<iostream> 
#include<cstring> 
#include<cmath> 
#include<algorithm> 
#include<queue> 
#include<vector> 
using namespace std; 
#define maxn 500005 
#define oo 999999999 
void _read(int &x) 
{ 
    char ch=getchar(); bool flag=false; x=0; 
    while(ch<'0' || ch>'9'){if(ch=='-')flag=true; ch=getchar();} 
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} if(flag)x=-x; return ; 
} 
struct P 
{ 
    int d[2]; 
}A[2*maxn],t; 
int Q,n,m,rt,chi[2*maxn][2]; 
bool mycmp(P x,P y) 
{ 
    if(x.d[Q]==y.d[Q])return x.d[Q^1]<y.d[Q^1]; 
    else return x.d[Q]<y.d[Q]; 
} 
int minv[2*maxn][2],maxv[2*maxn][2]; 
void pushup(int now) 
{ 
    for(int i=0;i<2;i++) 
    { 
        minv[now][i]=min(A[now].d[i],min(minv[chi[now][0]][i],minv[chi[now][1]][i])); 
        maxv[now][i]=max(A[now].d[i],max(maxv[chi[now][0]][i],maxv[chi[now][1]][i])); 
    } 
    return ; 
} 
void build(int &now,int L,int R,int k) 
{ 
    int mid=(L+R)>>1; now=mid; chi[now][0]=chi[now][1]=0; 
    Q=k; if(L!=R)nth_element(A+L,A+mid,A+R+1,mycmp); 
    if(mid!=L) build(chi[now][0],L,mid-1,k^1); 
    if(mid!=R) build(chi[now][1],mid+1,R,k^1); 
    pushup(now); 
    return ; 
} 
void Insert(int now,int x,int k) 
{ 
    int p=now,d; 
    while(p) 
    { 
        minv[p][0]=min(minv[p][0],A[x].d[0]);minv[p][1]=min(minv[p][1],A[x].d[1]); 
        maxv[p][0]=max(maxv[p][0],A[x].d[0]);maxv[p][1]=max(maxv[p][1],A[x].d[1]); 
        d=(A[x].d[k]>=A[p].d[k]); 
        if(chi[p][d]) 
        { 
            p=chi[p][d]; 
            k=k^1; 
        } 
        else
        { 
            chi[p][d]=x; 
            break; 
        } 
    } 
    return ; 
} 
int ans; 
int Abs(int x) 
{ 
    return x<0 ? -x : x ; 
} 
int getdis(P x,P y) 
{ 
    return Abs(x.d[0]-y.d[0])+Abs(x.d[1]-y.d[1]); 
} 
int get(int x) 
{ 
    if(!x)return oo; 
    int ans=0; 
    for(int i=0;i<2;i++) 
    { 
        ans+=max(0,minv[x][i]-t.d[i])+max(0,t.d[i]-maxv[x][i]); 
    } 
    return ans; 
} 
void query(int now) 
{ 
    int dd=getdis(A[now],t),dl=get(chi[now][0]),dr=get(chi[now][1]); 
    if(dd<ans)ans=dd; 
    if(dl<dr) 
    { 
        if(dl<ans && chi[now][0])query(chi[now][0]); 
        if(dr<ans && chi[now][1])query(chi[now][1]); 
    } 
    else
    { 
        if(dr<ans && chi[now][1])query(chi[now][1]); 
        if(dl<ans && chi[now][0])query(chi[now][0]); 
    } 
    return ; 
} 
void Init() 
{ 
    _read(n);_read(m);  
    for(int i=1;i<=n;i++) 
    { 
        _read(A[i].d[0]); _read(A[i].d[1]); 
    } 
    minv[0][0]=minv[0][1]=oo; 
    maxv[0][0]=maxv[0][1]=-oo; 
    build(rt,1,n,0); 
    return ; 
} 
void work() 
{ 
    char op; 
    int cct=0; 
    for(int i=1;i<=m;i++) 
    { 
        op=getchar();while(op!='1' && op!='2')op=getchar(); 
        if(op=='1') 
        { 
            cct++; 
            n++; _read(A[n].d[0]); _read(A[n].d[1]); 
            chi[n][0]=chi[n][1]=0; 
            minv[n][0]=maxv[n][0]=A[n].d[0];minv[n][1]=maxv[n][1]=A[n].d[1]; 
            Insert(rt,n,0); 
        } 
        else
        { 
            ans=oo; 
            _read(t.d[0]); _read(t.d[1]); 
            query(rt); 
            printf("%d\n",ans); 
        } 
  
    } 
    return ; 
} 
int main() 
{ 
    //freopen("in.txt","r",stdin); 
    Init(); 
    work(); 
    return 0; 
}


 

你可能感兴趣的:(【BZOJ2648】SYJ摆棋子 KD-Tree)