以log(n)的时间求矩形内的点
设想这么一个简单的问题,在一个平面上有n个点,给定一个矩形,问位于矩形内的点有哪些。
这个问题的简单思路非常简单,每次遍历所有点,看其是否在给定的矩形中。时间复杂度呢?单次查询的时间就是一次遍历的时间,也就是O(n),但如果给定的点基本不变,但查询量特别大,每次查询都要以O(n)的复杂度。能不能把给定的数据预处理一下,然后以后每次查询的复杂度降低呢?
一个基本的思路是把相邻的点用最小包围矩形包起来,然后再递归地处理这些矩形,以更大的最小包围矩形包围这些相邻的矩形。下图是个简单的例子:
在查询一个矩形内的所有点时,先再矩形和树的根求交,如果没有交集,说明矩形内没有点。否则说明矩形内可能包含有给定的点,于是就把矩形与根的儿子求交,这样递归下去即可。通过这种方法,我们在建树的时候,用了O(n)的时间,再以后每次查询的时候,大概是log(n)的时间
现在的难题是:如果判断两个点是否相邻?用他们之间的距离来作为标准肯定不合适
希尔伯特距离和希尔伯特树(http://en.wikipedia.org/wiki/Hilbert_R-tree)在这里可以得到很好的应用。什么是希尔伯特距离?
我们把一个给定区域按如下方式来划分,划分完成后,每个点到原点处的线段长度就是希尔伯特距离。如在H2中,点2的希尔伯特距离是2,点6的希尔伯特距离是6.
现在我们把给定的所有点的希尔伯特距离都算出来,然后根据希尔伯特距离来将它们作升序排序,然后就可以建树了
如何算希尔伯特距离呢?暴力方法肯定不行,有个比较好的方法如下:
- For all points, find max_x and max_y.
- Find the max of max_x and max_y and call this max_xy.
- If max_xy is a power of two, leave it. Else make it the next higher power of two.
- For each point:
1. Initialize w to be max_xy / 2. Dist = 0.
2. Find the quadrant on a hilbert curve that the point isin.
3. Dist += (quadrant * w * w)
4. w becomes w / 2
5. Calculate xnew and ynew according to the formulas
6. Repeat steps 2 to 5 until w becomes 0
|
Quadrant |
x_new |
y_new |
|
0 |
y |
x |
|
1 |
x |
y - w |
|
2 |
x - w |
y - w |
|
3 |
w - y - 1 |
w * 2 - x - 1 |
/**
* Find the Hilbert order (=vertex index) for the given grid cell
* coordinates.
* @param x cell column (from 0)
* @param y cell row (from 0)
* @param r resolution of Hilbert curve (grid will have Math.pow(2,r)
* rows and cols)
* @return Hilbert order
*/
public static int encode(int x, int y, int r) { int mask = (1 << r) - 1;
int hodd = 0;
int heven = x ^ y;
int notx = ~x & mask;
int noty = ~y & mask;
int temp = notx ^ y; int v0 = 0, v1 = 0;
for (int k = 1; k < r; k++) {
v1 = ((v1 & heven) | ((v0 ^ noty) & temp)) >> 1;
v0 = ((v0 & (v1 ^ notx)) | (~v0 & (v1 ^ noty))) >> 1;
}
hodd = (~v0 & (v1 ^ x)) | (v0 & (v1 ^ noty)); return interleaveBits(hodd, heven);
} /**
* Interleave the bits from two input integer values
* @param odd integer holding bit values for odd bit positions
* @param even integer holding bit values for even bit positions
* @return the integer that results from interleaving the input bits
*
* @todo: I'm sure there's a more elegant way of doing this !
*/
private static int interleaveBits(int odd, int even) {
int val = 0;
// Replaced this line with the improved code provided by Tuska
// int n = Math.max(Integer.highestOneBit(odd), Integer.highestOneBit(even));
int max = Math.max(odd, even);
int n = 0;
while (max > 0) {
n++;
max >>= 1;
} for (int i = 0; i < n; i++) {
int bitMask = 1 << i;
int a = (even & bitMask) > 0 ? (1 << (2*i)) : 0;
int b = (odd & bitMask) > 0 ? (1 << (2*i+1)) : 0;
val += a + b;
} return val;
}
之后的建树和搜索就不用多介绍了
以log(n)的时间求矩形内的点的更多相关文章
- LightOj1366 - Pair of Touching Circles(求矩形内圆的对数)
题目链接:http://lightoj.com/volume_showproblem.php?problem=1366 题意:一个H*W的矩形,现在要放入两个外切的圆,问能放多少对这样的圆,其中圆心和 ...
- 25.按要求编写一个Java应用程序: (1)编写一个矩形类Rect,包含: 两个属性:矩形的宽width;矩形的高height。 两个构造方法: 1.一个带有两个参数的构造方法,用于将width和height属性初化; 2.一个不带参数的构造方法,将矩形初始化为宽和高都为10。 两个方法: 求矩形面积的方法area() 求矩形周长的方法perimeter() (2)通过继承Rect类编写一个具有
package zhongqiuzuoye; //自己写的方法 public class Rect { public double width; public double height; Rect( ...
- lightOJ 1366 Pair of Touching Circles(统计矩形内相切圆对)
题目链接:http://lightoj.com/volume_showproblem.php?problem=1366 题意:给出一个矩形,在内部画两个圆A和B使得AB都完全在矩形内且AB相切且AB的 ...
- POJ 1410 Intersection(判断线段交和点在矩形内)
Intersection Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 9996 Accepted: 2632 Desc ...
- HDU4622:Reincarnation(后缀数组,求区间内不同子串的个数)
Problem Description Now you are back,and have a task to do: Given you a string s consist of lower-ca ...
- 洛谷P2241-统计方形-矩形内计算长方形和正方形的数量
洛谷P2241-统计方形 题目描述: 有一个 \(n \times m\) 方格的棋盘,求其方格包含多少正方形.长方形(不包含正方形). 思路: 所有方形的个数=正方形的个数+长方形的个数.对于任意一 ...
- Android判断当前系统时间是否在指定时间的范围内(免消息打扰)
/** * 判断当前系统时间是否在指定时间的范围内 * * @param beginHour * 开始小时,例如22 * @param beginMin * 开始小时的分钟数,例如30 * @para ...
- HDU 1828 / POJ 1177 Picture --线段树求矩形周长并
题意:给n个矩形,求矩形周长并 解法:跟求矩形面积并差不多,不过线段树节点记录的为: len: 此区间线段长度 cover: 此区间是否被整个覆盖 lmark,rmark: 此区间左右端点是否被覆盖 ...
- UVA 11983 Weird Advertisement --线段树求矩形问题
题意:给出n个矩形,求矩形中被覆盖K次以上的面积的和. 解法:整体与求矩形面积并差不多,不过在更新pushup改变len的时候,要有一层循环,来更新tree[rt].len[i],其中tree[rt] ...
随机推荐
- 使用DNSPod域名解析
1 在GoDaddy域名注册商 注册域名 https://sg.godaddy.com/zh/ 2 登陆DNSPod https://www.dnspod.cn 3 选择域名解析 添加域名 4 添加记 ...
- JavaScript DOM大纲
DOM 定义了访问和操作HTML文档的标准方法 访问(查找标签) ---- 直接查找 document.getElementById(“idname”) document.getElementsByT ...
- OpenVAS漏洞扫描基础教程之连接OpenVAS服务
OpenVAS漏洞扫描基础教程之连接OpenVAS服务 连接OpenVAS服务 当用户将OpenVAS工具安装并配置完后,用户即可使用不同的客户端连接该服务器.然后,对目标主机实施漏洞扫描.在本教程中 ...
- 机器学习之路: python 朴素贝叶斯分类器 MultinomialNB 预测新闻类别
使用python3 学习朴素贝叶斯分类api 设计到字符串提取特征向量 欢迎来到我的git下载源代码: https://github.com/linyi0604/MachineLearning fro ...
- ARM 中必须明白的几个概念
文章具体介绍了关于ARM的22个常用概念. 1.ARM中一些常见英文缩写解释 MSB:最高有效位: LSB:最低有效位: AHB:先进的高性能总线: VPB:连接片内外设功能的VLSI外设总线: EM ...
- windows svn 客户端连不上linux svn server
采坑记录:linux服务器上svn://127.0.0.1可以正常使用,windows客户端远程连接不上,说明是端口号的问题. linux正常配置了iptables开启了3690端口,连接不上. 干脆 ...
- 模型构建<1>:模型评估-分类问题
对模型的评估是指对模型泛化能力的评估,主要通过具体的性能度量指标来完成.在对比不同模型的能力时,使用不同的性能度量指标可能会导致不同的评判结果,因此也就意味着,模型的好坏只是相对的,什么样的模型是较好 ...
- 【ZOJ】3740:Water Level【DP】
Water Level Time Limit: 2 Seconds Memory Limit: 65536 KB Hangzhou is a beautiful city, especial ...
- Codeforces Round #355 (Div. 2) A. Vanya and Fence 水题
A. Vanya and Fence 题目连接: http://www.codeforces.com/contest/677/problem/A Description Vanya and his f ...
- unity热更新
Unity3D 学习笔记4 —— UGUI+uLua游戏框架 C#Light 和 uLua的对比第二弹 在Unity中使用Lua脚本:语言层和游戏逻辑粘合层处理 Ulua_toLua_基本案例 Uni ...