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;
    }
    
  • 相关阅读:
    COM编程入门
    DirectShow Filter 开发典型例子分析 ——字幕叠加 (FilterTitleOverlay)1
    互联网的三大巨头 百度 阿里巴巴 腾讯(BAT)
    入侵Tomcat服务器一次实战
    TinyXML:一个优秀的C++ XML解析器
    Apache POI (JAVA处理Office文档的类库)
    MediaInfo源代码分析 4:Inform()函数
    MediaInfo源代码分析 3:Open()函数
    洛谷 P3905 道路重建
    CF16A Flag
  • 原文地址:https://www.cnblogs.com/wljss/p/13092964.html
Copyright © 2011-2022 走看看