【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; 
}


 

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