K-DTree學習

應用於K維數據的快速查找,好比橫座標,縱座標,價格……,本模板以16青島區域賽K題爲例 —— 三維K - D Tree 模板
咱們應該都見過平衡樹吧,那就是1-D樹,變成k維以後,咱們連續分割1 - k維,而後繼續分割,實現快速查找,畫圖的時候就可以理解這個數據結構了
n個旅館 x,y,csot
m個用戶 x,y,limitcost
問你每一個用戶在能夠接受的價格內距離最近的旅館是哪一個

#define deep 3 // K-D樹的維度
#define inf (1e18) //用ll防止開根號,形成浮點偏差
using namespace std;
typedef long long ll;
const int maxn = 2e5+2e3;
int retid;//最優的旅館選擇編號
ll ans;//判斷距離最小值
int loc;//當前進行的維度
int n,m;//n個旅館,m個顧客
struct node{
    int id;
    int data[deep];
    //對各個維度都從小到大排序
    bool operator < (const node &b) const{
        if(data[loc] < b.data[loc])
            return 1;
        return 0;
    }
}P[maxn],tmp[maxn],Now,Aim;//P數組排序,tmp數組副本做爲輸出
void creat_KDtree(int l,int r,int flor){
    if(l >= r){
        return;
    }
    int mid = (l + r) >> 1;
    loc = flor % deep;
nth_element(P+l,P+mid,P+r+1);
/*把p+mid元素放在中間位置,使其左邊元素比它小,右邊比它大
nth_element(first,nth,last)
first,last 第一個和最後一個迭代器,也能夠直接用數組的位置。
nth,要定位的第n個元素,能對它進行隨機訪問.
將第n_th元素放到它該放的位置上,左邊元素都小於它,右邊元素都大於它.*/
    creat_KDtree(l,mid-1,flor+1);
    creat_KDtree(mid+1,r,flor+1);
}
void judge(int x)//根據題意的判斷函數{
    Now = P[x];
    if(Now.data[2] > Aim.data[2])
        return;
    ll dis = (Now.data[0] - Aim.data[0]) * (Now.data[0] - Aim.data[0]) + (Now.data[1] - Aim.data[1]) * (Now.data[1] - Aim.data[1]);
    if(dis < ans || dis == ans && Now.id < retid){
        ans = dis;
        retid = Now.id;
    }
}
void Find(int l,int r,int flor)//也是根據題意來寫{
    loc = flor % deep;
    if(l >= r){
        if(l == r)
            judge(l);
        return;
    }
    int mid = (l + r) >> 1;
    judge(mid);
    Now = P[mid];
    if(loc == 2){
        if(Now.data[loc] >= Aim.data[loc])
            Find(l,mid-1,flor+1);
        else{
            Find(l,mid-1,flor+1);
            Find(mid+1,r,flor+1);
        }
    }
    else{
        int len = Now.data[loc] - Aim.data[loc];
        if(len >= 0){
            Find(l,mid-1,flor+1);
            if(((ll)len * len) < ans){
                Find(mid+1,r,flor+1);
            }
        }
        else{
            Find(mid+1,r,flor+1);
            if(((ll)len * len) < ans){
                Find(l,mid-1,flor+1);
            }
        }
    }
}
相關文章
相關標籤/搜索