zoukankan      html  css  js  c++  java
  • 挑战程序设计2 KD树

    Range Query - Range Search (kD Tree)

    Time Limit : 1 sec, Memory Limit : 262144 KB 
    Japanese version is here

    Range Search (kD Tree)

    The range search problem consists of a set of attributed records S to determine which records from Sintersect with a given range.

    For n points on a plane, report a set of points which are within in a given range. Note that you do not need to consider insert and delete operations for the set.

    Input

    n
    x0 y0
    x1 y1
    :
    xn−1 yn−1
    q
    sx0 tx0 sy0 ty0
    sx1 tx1 sy1 ty1
    :
    sxq−1 txq−1 syq−1 tyq−1
    

    The first integer n is the number of points. In the following n lines, the coordinate of the i-th point is given by two integers xi and yi.

    The next integer q is the number of queries. In the following q lines, each query is given by four integers,sxitxisyityi.

    Output

    For each query, report IDs of points such that sxi ≤ x ≤ txi and syi ≤ y ≤ tyi. The IDs should be reported in ascending order. Print an ID in a line, and print a blank line at the end of output for the each query.

    Constraints

    • 0 ≤ n ≤ 500,000
    • 0 ≤ q ≤ 20,000
    • -1,000,000,000 ≤ xysxtxsyty ≤ 1,000,000,000
    • sx ≤ tx
    • sy ≤ ty
    • For each query, the number of points which are within the range is less than or equal to 100.

    Sample Input 1

    6
    2 1
    2 2
    4 2
    6 2
    3 3
    5 4
    2
    2 4 0 4
    4 10 2 5
    

    Sample Output 1

    0
    1
    2
    4
    
    2
    3
    5

    题意:给定二维平面内n个点的坐标,查询规定区域内的点的坐标

     思路:kD树的运用

    实现代码:

    #define _CRT_SECURE_NO_DEPRECATE
    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    #include<cstring>
    #include<set>
    #include<string>
    #include<queue>
    #include<cmath>
    using namespace std;
    #define INF 0x3f3f3f3f
    const int N_MAX = 500000;
    int n,np=0;
    struct point {
        int x, y,id;
        point() {}
        point(int x,int y):x(x),y(y) {}
        bool operator <(const point &p) const{
            return id < p.id;
        }
    }P[N_MAX];
    vector<point>vec;//别忘清空
    
    struct KD_tree {
    
        int L, R, location;//location代表树中当前的节点在原来序列中的位置
        KD_tree() {}
        KD_tree(int L,int R,int location):L(L),R(R),location(location) {}
    }T[N_MAX];
    bool cmp_x(const point &a,const point&b) {
        return a.x < b.x;
    }
    bool cmp_y(const point &a, const point&b) {
        return a.y < b.y;
    }
    
    int make2DTree(int l,int r,int depth) {//区间[l,r)
        if (!(l < r))return -1;
        int mid = (l+r) / 2;
        if (depth & 1)sort(P + l, P + r, cmp_y);
        else sort(P + l, P + r, cmp_x);
        int t = np++;
        T[t].location = mid;
        T[t].L = make2DTree(l, mid, depth + 1);
        T[t].R = make2DTree(mid + 1, r, depth + 1);
        return t;
    }
    
    void find(int v,int sx,int sy,int tx,int ty,int depth) {//判断节点v是否在区域内
        int x = P[T[v].location].x;
        int y = P[T[v].location].y;
        if (x >= sx&&x <= tx&&y >= sy&&y <= ty) {
            vec.push_back(P[T[v].location]);
        }
        if (!(depth & 1)) {
            if (T[v].L != -1 && x >= sx) {
                find(T[v].L, sx, sy, tx, ty, depth + 1);
            }
            if (T[v].R != -1 && x <= tx) {
                find(T[v].R, sx, sy, tx, ty, depth + 1);
            }
        }
        else{
            if (T[v].L != -1 && y >= sy) {
                find(T[v].L, sx, sy, tx, ty, depth + 1);
            }
            if (T[v].R != -1 && y <= ty) {
                find(T[v].R, sx, sy, tx, ty, depth + 1);
            }
        }
    }
    
    
    
    int main() {
        while (scanf("%d",&n)!=EOF) {
        
            np = 0;
            for (int i = 0; i < n;i++) {
                scanf("%d%d",&P[i].x,&P[i].y);
                P[i].id = i;
            }
            int root = make2DTree(0, n, 0);
            cout <<"root:"<<root << endl;
            int q;
            scanf("%d",&q);
            while (q--) {
                vec.clear();
                int sx, tx, sy, ty;
                scanf("%d%d%d%d",&sx,&tx,&sy,&ty);
                find(root, sx, sy, tx, ty, 0);
                sort(vec.begin(), vec.end());
                for (int i = 0; i < vec.size();i++) {
                    printf("%d
    ",vec[i].id);
                }
                puts("");
            }
        }
        return 0;
    }
  • 相关阅读:
    ADSL PPPoE出错详解及宽带连接中的一些错误代码含义
    2007年世界顶级防火墙排名(附下载地址)
    Asp.net Mvc问题索引
    .NET 操作GPRS Model的类库 ATSMS
    .NET 3.5多个工程编译的DOS命令
    Google Chrome浏览器JS执行效率惊人 实测比IE快十几倍
    FTP文件同步工具(FTP_File_Synchronizer) 源代码
    [转载] ORACLE中SQL查询优化研究
    ext的grid导出为excel 方法
    数据库分页SQL语句
  • 原文地址:https://www.cnblogs.com/ZefengYao/p/7768659.html
Copyright © 2011-2022 走看看