算法小白日常记录算法与数据结构的学习
线段树 可用于动态求解区间和
若使用前缀和 无法权衡查找和插入的时间复杂度 线段树可以平衡查找和插入时间复杂度为logn
class Segment_Tree {
int[] arr;
int[] tree;
int size;
public Segment_Tree(int[] nums) {
arr = nums;
size = nums.length;
tree = new int[4*size];
build_tree(0, 0, size - 1);
}
public void build_tree(int node, int start, int end) {
if (start == end) {
tree[node] = arr[start];
} else {
int mid = (start + end) / 2;
int left_node = 2 * node + 1;
int right_node = 2 * node + 2;
build_tree(left_node, start, mid);
build_tree(right_node, mid + 1, end);
tree[node] = tree[left_node] + tree[right_node];
}
}
public void update_tree(int node, int start, int end, int idx, int val) {
if (start == end) {
arr[idx] = val;
tree[node] = val;
} else {
int mid = (start + end) / 2;
int left_node = 2 * node + 1;
int right_node = 2 * node + 2;
if (idx >= start && idx <= mid) {
update_tree(left_node, start, mid, idx, val);
} else {
update_tree(right_node, mid + 1, end, idx, val);
}
tree[node] = tree[left_node] + tree[right_node];
}
}
public int query_tree(int node, int start, int end, int L, int R) {
if (R < start || L > end) {
return 0;
} else if ((start == end) || (L <= start && R>=end)) {
return tree[node];
} else {
int mid = (start + end) / 2;
int left_node = 2 * node + 1;
int right_node = 2 * node + 2;
int sum_left = query_tree(left_node, start, mid, L, R);
int sum_right = query_tree(right_node, mid + 1, end, L, R);
return sum_left + sum_right;
}
}
}