挑战程序设计2 KD树
Range Query - Range Search (kD Tree)
Time Limit : 1 sec, Memory Limit : 262144 KBJapanese 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,sxi, txi, syi, tyi.
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 ≤ x, y, sx, tx, sy, ty ≤ 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\n",vec[i].id); } puts(""); } } return 0; }