package com.interview.basics.search;
import com.interview.utils.MathUtil;
/**
* Created_By: stefanie
* Date: 15-1-19
* Time: 下午7:55
*/
public class SegmentTree<T> {
public static interface Operator<T>{
public T operate(T a, T b);
public T init(int idx, T[] input);
}
Operator<T> operator;
T[] input;
T[] tree;
public SegmentTree(T[] input, Operator<T> operator){
this.operator = operator;
this.input = input;
int depth = (int) MathUtil.log(input.length, 2) + 1;
int treeSize = (int) Math.pow(2, depth) * 2;
tree = (T[]) new Object[treeSize];
initialize(0, 0, input.length - 1);
}
private void initialize(int node, int begin, int end){
if(begin == end){
tree[node] = operator.init(begin, input);
return;
}
int mid = begin + (end - begin)/2;
int left = node * 2 + 1;
int right = node * 2 + 2;
initialize(left, begin, mid);
initialize(right, mid + 1, end);
tree[node] = operator.operate(tree[left], tree[right]);
}
public T query(int low, int high){
return query(0, low, high, 0, input.length - 1);
}
private T query(int node, int low, int high, int begin, int end){
if(high < begin || low > end) return null;
if(begin >= low && end <= high) return tree[node];
int mid = begin + (end - begin)/2;
T left = query(2 * node + 1, low, high, begin, mid);
T right = query(2 * node + 2, low, high, mid + 1, end);
if (left == null) return right;
if (right == null) return left;
return operator.operate(left, right);
}
}