Orthogonal Problems

aka 正交问题

input: set PP of nn points

goal: process PP in a DS​

query: axis-aligned rectangle rr

orthogonal range counting: number of points in rr

orthogonal range reporting: list of points in rr

3-sided queries: 3 boundaries

Rectangle stabbing

aka 穿刺矩形

input: set PP of nn rectangles

goal: process PP in a DS

query: a point qq

output: list of rectangles containing qq

1D Orthogonal Range Searching

input: set PP of nn points in 1D

goal: process PP in a DS

query: axis-aligned rectangle rr\rightarrow an interval

solution

balanced BST + linked list

O(n)O(n) space and O(logn)O(\log n) time to count, O(logn+k)O(\log n+k) time to report

query interval covered by logn\log n canonical sets 规范集.

可以证明任意一个区间包含的规范集个数是 logn\log n 数量级的。

canonical set: subset contained in the subtree of a node of the BST

规范集:BST 中特定节点的子树中包含的元素集。它包括节点子树中的所有元素。

更简单一点的解释就是,规范集是一颗完整的子树。

vv highest node that splits the interval

cover the part of the interval to left and right of vv with O(logn)O(\log n) canonical sets

left ww child of vv:

  1. outside interval: move right
  2. inside interval: move left, add right can. set to cover.

cover the part of the interval to left and right of vv with O(logn)O(\log n) canonical sets

total size of the canonical sets: O(nlogn)O(n\log n)

Range Trees

input: set PP of nn points in 2D

goal: process PP in a data structure

query: axis-alligned rectangle rr

building the DS:

  1. a BST TT on PP ordered by x-coordinates
  2. a BST T(S)T(S) for every canonical set SS of TT ordered by y-coordinates

树套树:二叉搜索树套二叉搜索树?

T(S)T(S) is called a secondary DS.

canonical sets of T(S)T(S) are called secondary canonical sets.

answering query r=[x1,x2]×[y1,y2]r=[x_1,x_2]\times[y_1,y_2]:

  1. cover [x1,x2][x_1,x_2] with l=O(logn)l=O(\log n) canonical sets S1,,SlS_1,\cdots,S_l from TT
  2. for each SiS_i, cover [y1,y2][y_1,y_2] with O(logn)O(\log n) secondary canonical sets.

query time: O(log2n)O(\log^2n) (n is number of secondary canonical sets)

space analysis: ST(S)=SO(S)=O(nlogn)\sum_S|T(S)|=\sum_SO(|S|)=O(n\log n)

Range Trees in Higher Dimensions

input: set PP of nn points

goal: process PP in a DS

query: axis-aligned rectangle rr

assume, we have a DS Ad\mathcal A_d with Sd(n)S_d(n) space and Qd(n)Q_d(n) query time for d-dimensional rectangles

Sd(n)=O(nlogd1n)Qd(n)=O(logdn)S_d(n)=O(n\log^{d-1}n)\\ Q_d(n)=O(\log^dn)

RTd+1(P)RT_{d+1}(P):

  1. partition PP into 2 subsets P1,P2P_1,P_2 of n2\lfloor\frac{n}{2}\rfloor and n2\lceil\frac{n}{2}\rceil using a hyperplane hh perpendicular 垂直 to the d+1d+1 dimension
  2. project P1P_1 onto hh and store the projected points in a DS Ad(P1)\mathcal A_d(P_1)
  3. project P2P_2 onto hh and store the projected points in a DS Ad(P2)A_d(P_2)
  4. recurse on P1,P2P_1,P_2

Sd+1(n)=O(2Sd(n2))+2Sd+1(n2)=O(Sd(n))+2Sd+1(n2)=O(lognSd(n))S_{d+1}(n)=O(2S_d(\frac{n}{2}))+2S_{d+1}(\frac{n}{2})\\ =O(S_d(n))+2S_{d+1}(\frac{n}{2})\\ =O(\log nS_d(n))

Queryd+1(q)_{d+1}(q):

  1. if qq completely to one side of hh then recurse on either P1P_1 or P2P_2
  2. else
    • let q=q×[l,r]q=q'\times[l,r]
    • QueryULd+1(q×(,r])UL_{d+1}(q'\times(-\infty,r]) on P1P_1
    • QueryULd+1(q×[l,+)UL_{d+1}(q'\times[l,+\infty) on P2P_2

降为:在二分时,能保证子树不会超过这个范围。

QueryULd+1(q)UL_{d+1}(q):

  1. let q=q×(,r]q=q'\times(-\infty,r]
  2. if q completely to left of hh then recurse on P2P_2
  3. else
    • QueryULd+1(q×(,r])UL_{d+1}(q'\times(-\infty,r]) on P1P_1
    • Queryd(q)_d(q') on the projection of P2P_2 on hh

Qd+1(n)=O(2Qd+1UL(n2))=O(Qd+1UL(n))Qd+1UL(n)=Qd+1UL(n2)+Qd(n)O(lognQd(n))Q_{d+1}(n)=O(2Q_{d+1}^{UL}(\frac{n}{2}))=O(Q_{d+1}^{UL}(n))\\ Q_{d+1}^{UL}(n)=Q_{d+1}^{UL}(\frac{n}{2})+Q_d(n)\Rightarrow O(\log nQ_d(n))

Priority Search Tree

input: set PP of nn points

goal: process PP in a DS

query: 3-sided rectangle [x1,x2]×[y,)[x_1,x_2]\times[y,\infty)

output: list of points in the query

PST(P)PST(P):

  1. pp\leftarrow point in PP with highest y-coordinate
  2. Pln12P_l\leftarrow\lfloor\frac{n-1}{2}\rfloor points of P{p}P-\{p\} with smallest x-coordinate
  3. Pr=P(Pl{p})P_r=P-(P_l\cup\{p\})
  4. create a node vv, sotre pp at v.pv.p, the x-coordinate of the dividing line at v.dv.d.
  5. left child of vPST(Pl)v\leftarrow PST(P_l)
  6. right child of vPST(Pr)v\leftarrow PST(P_r)
  7. return vv

O(n)O(n) space

3SQuery(v,q)3SQuery(v,q):

  1. if v.pv.p below qq then return
  2. if v.pv.p inside qq then output v.pv.p
  3. if qq is to the left of v.dv.d then 3SQuery(v.l,q)3SQuery(v.l,q)
  4. else if qq is to the right of v.dv.d then 3SQuery(v.r,q)3SQuery(v.r,q)
  5. else
    • 3SQuery(vl,q)3SQuery(v_l,q)

    • 3SQuery(vr,q)3SQuery(v_r,q)

      in fact, 3S3S there is 2S2S.

      因为保证了子树的范围不会超

2SQuery(v,q)2SQuery(v,q):

  1. if v.pv.p below qq then return
  2. if v.pv.p inside qq then output v.pv.p
  3. if qq is to the left of v.dv.d then 2SQuery(v.l,q)2SQuery(v.l,q)
  4. else if qq is to the right of v.dv.d then 2SQuery(v.r,q)2SQuery(v.r,q)
  5. else
    • 2SQuery(vl,q)2SQuery(v_l,q)
    • 2SQuery(vr,q)2SQuery(v_r,q)

in fact, a 2-sided query + a 1-sided query = 3-sided query

{T3(n)=O(1)+T3(n2)T3(n)=O(1)+2T2(n2){T2(n)=O(1)+T2(n2)T2(n)=O(1)+T2(n2)+T1(n2)T1(n)=O(output size)T2(n)=O(logn+k)T3(n)=O(logn+k)\begin{cases} T_3(n)=O(1)+T_3(\frac{n}{2})\\ T_3(n)=O(1)+2T_2(\frac{n}{2}) \end{cases} \\ \begin{cases} T_2(n)=O(1)+T_2(\frac{n}{2})\\ T_2(n)=O(1)+T_2(\frac{n}{2})+T_1(\frac{n}{2}) \end{cases} \\ T_1(n)=O(\text{output size})\\ T_2(n)=O(\log n+k)\\ T_3(n)=O(\log n+k)

O(n)O(n) space, O(logn+k)O(\log n+k) query time