zoukankan      html  css  js  c++  java
  • CF44G Shooting Gallery KDtree

    我们考虑用靶子来匹配射击点,可以把靶子按 (z) 从小到大排序后,依次寻找范围内的编号最小的射击点,并将其删除,正确性显然。

    考虑如何优化这个过程,实际上我们的操作分为两种:

    (1.) 在二维平面内找编号最小的点。

    (2.) 在二维平面内删除点。

    可以把射击点建出 (KDtree) ,然后维护查询和删除 ,具体实现可以看代码。

    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #define lson tr[k].ls
    #define rson tr[k].rs
    using namespace std;
    int n, m, root, cnt, nowk, ans;
    const int N = 100010, inf = 1e8;
    int fa[N], pos[N], Ans[N];
    struct mb 
    {
        int xl, yl, xr, yr, z, id;
        friend bool operator <(const mb &a, const mb &b)
        {return a.z < b.z;}
    } B[N];
    struct sj 
    {
        int x, y, id;
        friend bool operator <(const sj &a, const sj &b)
        {return nowk ? a.x < b.x : a.y < b.y;}
    } S[N];
    struct shu 
    {
        int mn, id, x, y, minx, miny, maxx, maxy, ls, rs;
    } tr[N];
    void pushup(int k) 
    {
        tr[k].mn = tr[k].id;
        if (lson) 
        {
            tr[k].mn = min(tr[k].mn, tr[lson].mn);
            tr[k].minx = min(tr[k].minx, tr[lson].minx); tr[k].miny = min(tr[k].miny, tr[lson].miny);
            tr[k].maxx = max(tr[k].maxx, tr[lson].maxx); tr[k].maxy = max(tr[k].maxy, tr[lson].maxy);
        }
        if (rson) 
        {
            tr[k].mn = min(tr[k].mn, tr[rson].mn);
            tr[k].minx = min(tr[k].minx, tr[rson].minx); tr[k].miny = min(tr[k].miny, tr[rson].miny);
            tr[k].maxx = max(tr[k].maxx, tr[rson].maxx); tr[k].maxy = max(tr[k].maxy, tr[rson].maxy);
        }
    }
    void build(int FA, int &k, int l, int r, int KD) 
    {
        if (l > r)return;
        int mid = (l + r) >> 1; k = ++cnt; nowk = KD;
        nth_element(S + l, S + mid, S + r + 1);
        pos[S[mid].id] = k; fa[k] = FA;
        tr[k].id = tr[k].mn = S[mid].id;
        tr[k].x = tr[k].minx = tr[k].maxx = S[mid].x;
        tr[k].y = tr[k].miny = tr[k].maxy = S[mid].y;
        build(k, lson, l, mid - 1, KD ^ 1); build(k, rson, mid + 1, r, KD ^ 1);
        pushup(k);
    }
    void ask(int k, int xl, int yl, int xr, int yr) 
    {
        if (tr[k].maxx < xl || xr < tr[k].minx || tr[k].maxy < yl || yr < tr[k].miny)return;
        if (xl <= tr[k].minx && tr[k].maxx <= xr && yl <= tr[k].miny && tr[k].maxy <= yr) {ans = min(ans, tr[k].mn); return;}
        if (tr[k].id != inf && xl <= tr[k].x && tr[k].x <= xr && yl <= tr[k].y && tr[k].y <= yr) {ans = min(ans, tr[k].id);}
        if (lson)ask(lson, xl, yl, xr, yr);
        if (rson)ask(rson, xl, yl, xr, yr);
    }
    void shan(int x) 
    {
        tr[x].id = inf;
        while (x) 
        {
            pushup(x);
            x = fa[x];
        }
    }
    int main() 
    {
        cin >> n;
        for (int i = 1, xl, xr, yl, yr, z; i <= n; ++i) 
        {
            scanf("%d%d%d%d%d", &xl, &xr, &yl, &yr, &z);
            B[i] = (mb) {xl, yl, xr, yr, z, i};
        }
        cin >> m;
        for (int i = 1; i <= m; ++i)
            scanf("%d%d", &S[i].x, &S[i].y), S[i].id = i;
        build(0, root, 1, m, 0);
        sort(B + 1, B + 1 + n);
        for (int i = 1; i <= n; ++i) 
        {
            ans = inf; ask(root, B[i].xl, B[i].yl, B[i].xr, B[i].yr);
            if (ans != inf) 
            {
                Ans[ans] = B[i].id;
                shan(pos[ans]);
            }
        }
        for (int i = 1; i <= m; ++i)printf("%d
    ", Ans[i]);
        return 0;
    }
    
  • 相关阅读:
    TCP源码—连接建立
    TCP系列02—连接管理—1、三次握手与四次挥手
    TCP系列01—概述及协议头格式
    ubuntu软件管理apt与dpkg
    318. Maximum Product of Word Lengths
    317. Shortest Distance from All Buildings
    316. Remove Duplicate Letters
    315. Count of Smaller Numbers After Self
    314. Binary Tree Vertical Order Traversal
    313. Super Ugly Number
  • 原文地址:https://www.cnblogs.com/wljss/p/13092964.html
Copyright © 2011-2022 走看看