Finding Hotels(2017ICPC青島現場K題+K-D Tree)

Finding Hotels

在前車之鑑的基礎上,真好,又是1A1A

題意:

在二維平面上給定NN個帶權點;MM個詢問,每次詢問最近的權值小於某一給定值的點。

思路:

  1. 依舊用K-D Tree進行暴力+剪枝。
  2. 首先將NN個點建好K-D Tree,然後對每個詢問,暴力查詢。
  3. 考慮K-D Tree的通用優化思想:對於某個根節點,在剪枝的情況下最好只遍歷它的一個子樹!
  4. 先搞定當前節點,然後看看詢問節點在當前節點的考察維度的左邊還是右邊,然後就先遍歷所在的那一邊;關鍵剪枝: 如果詢問點與當前點的考察維度的座標差值就已經大於當前答案距離了,顯然當前節點的另外一個子樹(子空間)就不需要遍歷了!畢竟對於另外一個子空間考慮兩個維度時,距離顯然會大於當前答案距離了(這裏講的很繞,但畫一下圖就很清晰了)。
  5. 上述一個剪枝就可以直接AC了,這裏還可以考慮另外一個剪枝進行加速:如果當前子空間的最小權值都大於給定權值,顯然就不用進入啦。

代碼

#include "bits/stdc++.h"
#define hhh printf("hhh\n")
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
using namespace std;
typedef long long ll;
typedef pair<int,int> pr;
inline int read() {int x=0,f=1;char c=getchar();while(c!='-'&&(c<'0'||c>'9'))c=getchar();if(c=='-')f=-1,c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return f*x;}

const int maxn = 2e5+10;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const double eps = 1e-7;

int N, M, Dim, tot, rt;
int ls[maxn], rs[maxn], mi[maxn];

struct P{
    int x[2], c, id;
    friend bool operator < (const P &a, const P &b) {
        return a.x[Dim]<b.x[Dim];
    }
    inline ll dis(const P &rhs) {
        return ll(x[0]-rhs.x[0])*(x[0]-rhs.x[0])+ll(x[1]-rhs.x[1])*(x[1]-rhs.x[1]);
    }
    void print() {
        cout<<x[0]<<" "<<x[1]<<" "<<c<<endl;
    }
}p[maxn], tmp[maxn], q;

pair<ll,P> ans;

void push_up(int now) {
    mi[now]=p[now].c;
    if(ls[now]) mi[now]=min(mi[now],mi[ls[now]]);
    if(rs[now]) mi[now]=min(mi[now],mi[rs[now]]);
}

void build(int l, int r, int dim, int &now) {
    if(l>r) { now=0; return; }
    now=++tot;
    int m=(l+r)/2;
    Dim=dim; nth_element(tmp+l,tmp+m,tmp+r+1); p[now]=tmp[m];
    build(l,m-1,dim^1,ls[now]); build(m+1,r,dim^1,rs[now]);
    push_up(now);
}

void query(int dim, int now) {
    if(!now) return;
    ll d0=p[now].dis(q);
    int lt=ls[now], rt=rs[now];
    if(q.x[dim]>=p[now].x[dim]) swap(lt,rt);
    if(ans.first==-1||d0<ans.first||(d0==ans.first&&p[now].id<ans.second.id)) {
        if(p[now].c<=q.c) ans.first=d0, ans.second=p[now];
    }
    if(lt&&mi[lt]<=q.c) query(dim^1,lt);
    ll tp=q.x[dim]-p[now].x[dim];
    if(rt&&mi[rt]<=q.c&&(ans.first==-1||tp*tp<=ans.first)) query(dim^1,rt);
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    memset(mi,inf,sizeof(inf));
    int T; cin>>T;
    while(T--) {
        cin>>N>>M;
        for(int i=1; i<=N; ++i) cin>>tmp[i].x[0]>>tmp[i].x[1]>>tmp[i].c, tmp[i].id=i;
        tot=0; build(1,N,0,rt);
        for(int i=1; i<=M; ++i) {
            cin>>q.x[0]>>q.x[1]>>q.c;
            ans.first=-1;
            query(0,rt);
            ans.second.print();
        }
        for(int i=1; i<=N; ++i) ls[i]=rs[i]=0, mi[i]=inf;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章