zoukankan      html  css  js  c++  java
  • bzoj4520

    KD-tree+堆

    多年大坑

    KD-tree已经是半年前学的了,忘记了。这道题当时一直T,今天重新抄了一遍,A了

    KD-tree过程:1.建树:每次依次按x,y划分平面,像二叉搜索树一样建树,每个点维护一些东西;

    2.查询:直接查太暴力了,我们用估价函数减值,每个点维护最小最大的x和y,每次计算能够造成的最大距离,如果有价值就递归。注意关于dl,dr的大小判断,这里query顺序不一样,因为先query大的会使大的先进堆,这样更快一些,相当于一个剪枝。其实KD-tree就是一个暴力剪枝的过程。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll inf = 1e18;
    const int N = 1e5 + 5;
    int n, k, root, d;
    struct data {
        ll mx_x, mn_x, mx_y, mn_y, x, y, lc, rc;
        bool friend operator < (const data &a, const data &b) {
            if(d == 0) return a.x == b.x ? a.y < b.y : a.x < b.x;
            if(d == 1) return a.y == b.y ? a.x < b.x : a.y < b.y;
        }
    } a[N];
    priority_queue<ll, vector<ll>, greater<ll> > q;
    ll sqr(ll x)
    {
        return x * x;
    }
    ll dis(int k, ll x, ll y)
    {
        return max(sqr(a[k].mn_x - x), sqr(a[k].mx_x - x)) + max(sqr(a[k].mn_y - y), sqr(a[k].mx_y - y));
    }
    void update(int x)
    {
        a[x].mn_x = min(a[x].x, min(a[a[x].lc].mn_x, a[a[x].rc].mn_x));
        a[x].mx_x = max(a[x].x, max(a[a[x].lc].mx_x, a[a[x].rc].mx_x));
        a[x].mn_y = min(a[x].y, min(a[a[x].lc].mn_y, a[a[x].rc].mn_y));
        a[x].mx_y = max(a[x].y, max(a[a[x].lc].mx_y, a[a[x].rc].mx_y));
    }
    int build(int l, int r, int now)
    {
        if(l > r) return 0;
        int mid = (l + r) >> 1;
        d = now;
        nth_element(a + l, a + mid, a + r + 1);
        a[mid].mx_x = a[mid].mn_x = a[mid].x;
        a[mid].mx_y = a[mid].mn_y = a[mid].y;
        a[mid].lc = build(l, mid - 1, now ^ 1);
        a[mid].rc = build(mid + 1, r, now ^ 1);
        update(mid);
        return mid;
    }
    void query(int k, ll x, ll y)
    {
        ll tmp = sqr(x - a[k].x) + sqr(y - a[k].y), dl = a[k].lc ? dis(a[k].lc, x, y) : -inf, dr = a[k].rc ? dis(a[k].rc, x, y) : -inf;
        if(tmp > q.top()) q.pop(), q.push(tmp);
        if(dl < dr)
        {
            if(dr > q.top()) query(a[k].rc, x, y);
            if(dl > q.top()) query(a[k].lc, x, y);
        }
        else
        {
            if(dl > q.top()) query(a[k].lc, x, y);
            if(dr > q.top()) query(a[k].rc, x, y);
        }
    }
    int main()
    {
        scanf("%d%d", &n, &k);
        a[0].mn_x = inf;
        a[0].mx_x = -inf;
        a[0].mn_y = inf;
        a[0].mx_y = -inf;
        for(int i = 1; i <= n; ++i) scanf("%d%d", &a[i].x, &a[i].y);
        root = build(1, n, 0);
        for(int i = 1; i <= 2 * k; ++i) q.push(0);
        for(int i = 1; i <= n; ++i) query(root, a[i].x, a[i].y);
        printf("%lld
    ", q.top());
        return 0;
    }
    View Code
  • 相关阅读:
    《软件方法》读书笔记2
    《代码阅读方法与实践》读书笔记3
    课堂讨论记录
    《代码阅读方法与实践》读书笔记2
    [洛谷] P1948 [USACO08JAN]Telephone Lines S(二分+SPFA)
    2020 CCPC秦皇岛 正式赛题解
    [洛谷] P3146 [USACO16OPEN]248 G (区间DP)
    [进阶指南] 最大子序和
    [训练] 图的K步移动最大收获
    [计蒜客] 受力平衡(组合数学 + 乘法逆元)
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7868625.html
Copyright © 2011-2022 走看看