public class SegmentTree<E>{
private E[] data;
private E[] tree;
private Merger<E> merge;
public SegmentTree(E[] arr, Merger<E> merge) {
this.merge = merge;
data = (E[]) new Object[arr.length];
tree = (E[]) new Object[4 * arr.length];
for (int i = 0; i < arr.length; i++) {
data[i] = arr[i];
}
buildSegmentTree(0, 0, arr.length-1);
}
private void buildSegmentTree(int index, int l, int r) {
if (l == r) {
tree[index] = data[l];
return;
}
int mid = l + (r - l) / 2;
buildSegmentTree(leftChild(index), l, mid);
buildSegmentTree(rightChild(index), mid + 1, r);
tree[index] = merge.merge(tree[leftChild(index)], tree[rightChild(index)]);
}
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);
}
private E query(int index, int l, int r, int queryL, int queryR) {
if (l == queryL && r == queryR) {
return tree[index];
}
int mid = l + (r-l)/2;
if (queryL > mid) {
return query(rightChild(index), mid + 1, r, queryL, queryR);
} else if (queryR <= mid) {
return query(leftChild(index), l, mid, queryL, queryR);
}
E leftResult = query(leftChild(index), l, mid, queryL, mid);
E rightResult = query(rightChild(index), mid+1, r, mid+1, queryR);
return merge.merge(leftResult, rightResult);
}
public void set(int index, E e) {
data[index] = e;
set(0, 0, data.length-1, index, e);
}
private void set(int treeIndex, int l, int r, int index, E e) {
if (l == r)
tree[treeIndex] = e;
int mid = l + (r-l)/2;
if (index <= mid) {
set(leftChild(treeIndex), l , mid, index, e);
} else {
set(rightChild(treeIndex), mid+1, r, index, e);
}
tree[treeIndex] = merge.merge(tree[leftChild(treeIndex)], tree[rightChild(treeIndex)]);
}
private int leftChild(int index) {
return 2 * index + 1;
}
private int rightChild(int index) {
return 2 * index + 2;
}
}
Merger
public interface Merger<E> {
E merge(E a, E b);
}