zoukankan      html  css  js  c++  java
  • KD-Tree解决空间最短距离的利器

    KD-Tree解决空间最短距离的利器

    本文作者:Caozhijie

    /**************************************************************
        Problem: 2648
        User: Cardinal
        Language: C++
        Result: Accepted
        Time:14476 ms
        Memory:40356 kb
    ****************************************************************/
    
    #include <cstdio>
    #include <cstring>
    #include <climits>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    #define Min(a, b) ((a)<(b)?(a):(b))
    #define Max(a, b) ((a)>(b)?(a):(b))
    #define Abs(x) ((x)>0?(x):-(x))
    
    #define N 500010
    #define M 500010
    int n, m;
    
    struct Point {
        int x, y;
        Point(int _x = 0, int _y = 0):x(_x),y(_y){}
        void set(int _, int __) {
            x = _, y = __;
        }
    }P[N + M];
    int Dis(const Point &A, const Point &B) {
        return Abs(A.x - B.x) + Abs(A.y - B.y);
    }
    
    bool sign;
    inline bool cmp(const Point &A, const Point &B) {
        if (sign)
            return A.x < B.x || (A.x == B.x && A.y < B.y);
        else
            return A.y < B.y || (A.y == B.y && A.x < B.x);
    }
    
    struct Node {
        Node *l, *r;
        int x[2], y[2];
        Point p;
    
        void SetP(const Point &P) {
            p = P;
            x[0] = x[1] = P.x;
            y[0] = y[1] = P.y;
        }
        int Dis(const Point &p) const {
            int res = 0;
            if (p.x < x[0] || p.x > x[1])
                res += (p.x < x[0]) ? x[0] - p.x : p.x - x[1];
            if (p.y < y[0] || p.y > y[1])
                res += (p.y < y[0]) ? y[0] - p.y : p.y - y[1];
            return res;
        }
        void up(Node *B) {
            x[0] = Min(x[0], B->x[0]);
            x[1] = Max(x[1], B->x[1]);
            y[0] = Min(y[0], B->y[0]);
            y[1] = Max(y[1], B->y[1]);
        }
    }mem[N + M], *C = mem, Tnull, *null = &Tnull;
    
    Node *Build(int tl, int tr, bool d) {
        if (tl > tr)
            return null;
    
        int mid = (tl + tr) >> 1;
        sign = d;
        std::nth_element(P + tl + 1, P + mid + 1, P + tr + 1, cmp);
    
        Node *q = C++;
        q->SetP(P[mid]);
        q->l = Build(tl, mid - 1, d ^ 1);
        q->r = Build(mid + 1, tr, d ^ 1);
        if (q->l != null)
            q->up(q->l);
        if (q->r != null)
            q->up(q->r);
        return q;
    }
    
    #define INF 0x3f3f3f3f
    int res;
    void Ask(Node *q, const Point &p) {
        res = Min(res, Dis(q->p, p));
        int DisL = q->l != null ? q->l->Dis(p) : INF;
        int DisR = q->r != null ? q->r->Dis(p) : INF;
        if (DisL < DisR) {
            if (q->l != null)
                Ask(q->l, p);
            if (DisR < res && q->r != null)
                Ask(q->r, p);
        }
        else {
            if (q->r != null)
                Ask(q->r, p);
            if (DisL < res && q->l != null)
                Ask(q->l, p);
        }
    }
    
    void Insert(Node *root, const Point &p) {
        Node *q = C++;
        q->l = q->r = null;
        q->SetP(p);
    
        sign = 0;
        while(1) {
            root->up(q);
            if (cmp(q->p, root->p)) {
                if (root->l == null) {
                    root->l = q;
                    break;
                }
                else
                    root = root->l;
            }
            else {
                if (root->r == null) {
                    root->r = q;
                    break;
                }
                else
                    root = root->r;
            }
            sign ^= 1;
        }
    }
    
    int main() {
        #ifndef ONLINE_JUDGE
        //freopen("tt.in", "r", stdin);
        //freopen("tt.out", "w", stdout);
        #endif
    
        scanf("%d%d", &n, &m);
    
        register int i;
        int ope, x, y;
        for(i = 1; i <= n; ++i) {
            scanf("%d%d", &x, &y);
            P[i] = Point(x, y);
        }
    
        Node* root = Build(1, n, 0);
    
        while(m--) {
            scanf("%d%d%d", &ope, &x, &y);
            if (ope == 1)
                Insert(root, Point(x, y));
            else {
                res = INF;
                Ask(root, Point(x, y));
                printf("%d
    ", res);
            }
        }
    
        return 0;
    }
  • 相关阅读:
    java开发规范总结_代码编码规范
    java开发规范总结_代码注释规范
    Android简单例子——IpHone样式AlertDialog
    Java的split方法说明
    Android简单例子——AlertDialog
    Android增加监听的三种实现方式
    Android学习笔记(SQLite的简单使用)
    【公告】新博客、新地址,欢迎交换友链
    【公告】博客迁移中,暂停更新...
    【System】Install chromium os in vmware workstation
  • 原文地址:https://www.cnblogs.com/cww97/p/12349341.html
Copyright © 2011-2022 走看看