查询区间 [queryL, queryR] 上被赋予的意义
- 将问题转化为一个递归问题:在以treeIndex为根的对应区间为 [l, r] 的线段树中,查询区间 [queryL, queryR]被赋予的意义;
// 返回区间[queryL, queryR]的值
public E query(int queryL, int queryR){
if(queryL < 0 || queryL >= data.length ||
queryR < 0 || queryR >= data.length || queryL > queryR)
throw new IllegalArgumentException("Index is illegal.");
return query(0, 0, data.length - 1, queryL, queryR);
}
-
更小规模的同一个问题是:在以leftTreeIndex为根的表示区间 [l, mid] 的线段树中,或以rightTreeIndex为根的表示区间为 [mid + 1, r] 的线段树中,查询区间 [quertL, queryR] 被赋予的意义;
- 当区间 [queryL, queryR] 完全在 [l, mid] 中,则在以leftTreeIndex为根表示区间 [l, mid] 的线段树中查询区间 [queryL, queryR] 被赋予的意义;
- 当区间 [queryL, queryR] 完全在 [mid + 1, r] 中,则在以rightTreeIndex为根的表示区间 [mid + 1, r] 的线段树中查询区间 [queryL, queryR] 被赋予的意义;
- 当区间 [queryL, queryR] 跨越leftTreeIndex和rightTreeIndex表示的区间时:
- 在以leftTreeIndex为根的表示区间 [l, mid] 的线段树中查询区间 [queryL, mid] 被赋予的意义leftResult;
- 在以rightTreeIndex为根的表示区间 [mid + 1, r] 的线段树中查询区间 [mid + 1, queryR] 被赋予的意义rightResult;
- 合并leftResult和rightResult,即为在以treeInde为根的表示表示区间 [l, r] 的线段树中查询区间 [queryL, queryR] 被赋予的意义;
-
不能再缩小的基本问题是:查询的区间 [queryL, queryR] 正好就是treeIndex表示的区间,即l == queryL && r == queryR,那么查询的结果就是tree[treeIndex]的值;
// 在以treeIndex为根的线段树中[l...r]的范围里,搜索区间[queryL...queryR]的值
private E query(int treeIndex, int l, int r, int queryL, int queryR){
if(l == queryL && r == queryR)
return tree[treeIndex];
int mid = l + (r - l) / 2;
// treeIndex的节点分为[l...mid]和[mid+1...r]两部分
int leftTreeIndex = leftChild(treeIndex);
int rightTreeIndex = rightChild(treeIndex);
if(queryL >= mid + 1)
return query(rightTreeIndex, mid + 1, r, queryL, queryR);
else if(queryR <= mid)
return query(leftTreeIndex, l, mid, queryL, queryR);
// 查询区间左边界在leftTreeIndex表示的区间,右边界在rightTreeIndex表示的区间
E leftResult = query(leftTreeIndex, l, mid, queryL, mid);
E rightResult = query(rightTreeIndex, mid + 1, r, mid + 1, queryR);
return merger.merge(leftResult, rightResult);
}
网友评论