前言:
前缀和:区间查询O(1),修改O(N);
线段树:区间查询O(lgN),修改O(lgN);
差分数组:区间修改O(1),但是在查询数组中某个位置的数时,就要根据差分数组从前往后递推求值。
一、线段树
自上而下递归的思想。
/**
* 线段树
*/
public class SegementTreePractice2 {
private static Segement root;
class Segement {
// 线段表示的区间[L,R]
int L, R;
// [L, R]内的有效长度value
int value;
Segement left, right;
public Segement(int L, int R, int value) {
this.L = L;
this.R = R;
this.value = value;
}
}
/**
* 构建线段树
*/
private Segement buildTree(int[] arr, int left, int right) {
if (left == right) {
return new Segement(left, right, arr[left]);
}
int mid = (left + right) / 2;
Segement leftNode = buildTree(arr, left, mid);
Segement rightNode = buildTree(arr, mid + 1, right);
Segement node = new Segement(left, right, leftNode.value + rightNode.value);
node.left = leftNode;
node.right = rightNode;
return node;
}
/**
* 根据线段树求 arr[left, right]的大小
*/
private int query(int left, int right, Segement root) {
if (left == root.L && right == root.R) {
return root.value;
}
// rightNode区间能覆盖[left, right]
if (root.right.L <= left && root.right.R >= right) {
return query(left, right, root.right);
}
// leftNode区间能覆盖[left, right]
if (root.left.L <= left && root.left.R >= right) {
return query(left, right, root.left);
}
int mid = (root.L + root.R) / 2;
int leftQuery = query(left, mid, root.left);
int rightQuery = query(mid + 1, right, root.right);
return leftQuery + rightQuery;
}
/**
* arr[index]修改为value,更新线段树
*/
private void update(int index, int value, Segement root) {
if (root.L == root.R) {
if (root.L == index) {
root.value = value;
}
return;
}
// index在左区间还是右区间
if (root.left.L <= index && root.left.R >= index) {
update(index, value, root.left);
} else {
update(index, value, root.right);
}
root.value = root.left.value + root.right.value;
}
}
二、差分数组
diff[i]数组的意义:nums[i]与nums[i-1]的差。所以要查询数组中某个位置的数时,就要根据差分数组从头往后递推求值。
int[] getDiff(int[] nums){
int n = nums.length;
int[] diff = new int[n + 1];
diff[0] = nums[0];
for (int i = 1; i < n; i++) {
diff[i] = nums[i] - nums[i - 1];
}
}
如果想对[i, j]区间加a,那就diff[i]+a, diff[j+1]-a;
如果想对[i, j]区间减a,那就diff[i]-a, diff[j+1]+a。