• BZOJ2716 天使玩偶


    之前写过CDQ + 线段树的, 被惨烈地卡常卡了下来...
    所以决定改写KD-tree
    这里先放个代码占个坑, 后面再写教程吧.

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #include <climits>
    #include <cmath>
      
    namespace Zeonfai
    {
        inline int getInt()
        {
            int a = 0, sgn = 1;
            char c;
      
            while(! isdigit(c = getchar()))
                if(c == '-')
                    sgn *= -1;
      
            while(isdigit(c))
                a = a * 10 + c - '0', c = getchar();
      
            return a * sgn;
        }
      
        inline void _print(int a)
        {
            if(! a)
                return;
      
            _print(a / 10);
            putchar('0' + a % 10);
        }
      
        inline void println(int a)
        {
            if(a < 0)
                putchar('-'), a *= -1;
      
            if(! a)
                putchar('0');
      
            _print(a);
            putchar('
    ');
        }
    }
      
    const int N = (int)5e5, M = (int)5e5;
    int n, m;
    int dmn;
      
    struct point
    {
        int x, y;
          
        inline point() {}
      
        inline point(int _x, int _y)
        {
            x = _x, y = _y;
        }
      
        inline int friend operator <(const point &a, const point &b)
        {
            if(dmn == 0)
                return a.x < b.x;
            else
                return a.y < b.y;
        }
    };
      
    point pos[N + M];
      
    struct KDtree
    {
        struct node
        {
            node *suc[2];
            point p, bnd[2];
      
            inline node(const point &_p)
            {
                bnd[0] = bnd[1] = p = _p, suc[0] = suc[1] = NULL;
            }
      
            inline void update()
            {
                bnd[0] = bnd[1] = p;
      
                for(int i = 0; i < 2; ++ i)
                    if(suc[i] != NULL)
                    {
                        bnd[0].x = std::min(suc[i]->bnd[0].x, bnd[0].x), bnd[0].y = std::min(suc[i]->bnd[0].y, bnd[0].y);
                        bnd[1].x = std::max(suc[i]->bnd[1].x, bnd[1].x), bnd[1].y = std::max(suc[i]->bnd[1].y, bnd[1].y);
                    }
            }
        };
      
        node *rt;
      
        node* build(int L, int R, int D)
        {
            if(L > R)
                return NULL;
      
            int mid = L + R >> 1;
            dmn = D;
            std::nth_element(pos + L, pos + mid, pos + R + 1);
            node *u = new node(pos[mid]);
            u->suc[0] = build(L, mid - 1, D ^ 1);
            u->suc[1] = build(mid + 1, R, D ^ 1);
            u->update();
            return u;
        }
      
        inline void build()
        {
            rt = build(0, n - 1, 0);
        }
      
        node* insert(node *u, const point &p, int D)
        {
            if(u == NULL)
            {
                u = new node(p);
                return u;
            }
      
            dmn = D;
              
            if(p < u->p)
                u->suc[0] = insert(u->suc[0], p, D ^ 1);
            else
                u->suc[1] = insert(u->suc[1], p, D ^ 1);
      
            u->update();
            return u;
        }
      
        inline void insert(const point &p)
        {
            rt = insert(rt, p, 0);
        }
      
        int ans;
      
        inline int getDistance(const point &a, const point &b)
        {
            return abs(a.x - b.x) + abs(a.y - b.y);
        }
      
        inline int getDistance(const point &p, node *u)
        {
            if(u == NULL)
                return INT_MAX;
      
            int res = 0;
      
            if(p.x < u->bnd[0].x || p.x > u->bnd[1].x)
                res += p.x < u->bnd[0].x ? u->bnd[0].x - p.x : p.x - u->bnd[1].x;
      
            if(p.y < u->bnd[0].y || p.y > u->bnd[1].y)
                res += p.y < u->bnd[0].y ? u->bnd[0].y - p.y : p.y - u->bnd[1].y;
      
            return res;
        }
      
        void query(node *u, const point &p)
        {
            if(u == NULL)
                return;
      
            ans = std::min(ans, getDistance(p, u->p));
            int k = getDistance(p, u->suc[0]) > getDistance(p, u->suc[1]);
      
            if(getDistance(p, u->suc[k]) < ans)
                query(u->suc[k], p);
      
            if(getDistance(p, u->suc[k ^ 1]) < ans)
                query(u->suc[k ^ 1], p);
        }
      
        inline int query(const point &p)
        {
            ans = INT_MAX;
            query(rt, p);
            return ans;
        }
    }KDT;
      
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("BZOJ2716.in", "r", stdin);
        freopen("BZOJ2716KDT.out", "w", stdout);
        #endif
      
        using namespace Zeonfai;
      
        n = getInt(), m = getInt();
      
        for(int i = 0; i < n; ++ i)
            pos[i].x = getInt(), pos[i].y = getInt();
      
        KDT.build();
      
        while(m --)
        {
            int tp = getInt(), x = getInt(), y = getInt();
      
            if(tp == 1)
                KDT.insert(pos[n ++] = point(x, y));
            else
                println(KDT.query(point(x, y)));
        }
    }
    
  • 相关阅读:
    什么是同源策略,什么是跨域,如何跨域,Jsonp/CORS跨域
    Scrapy
    爬虫
    Falsk-信号
    python函数中把列表(list)当参数时的"入坑"与"出坑"
    SQLAlchemy基本使用(Flask中)
    列表生成式&生成器表达式
    javascript数据结构——队列
    javascript数据结构——栈
    js数组去重的几种方法
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/6916753.html
Copyright © 2020-2023  润新知