zkw线段树(Zkw Segment Tree)是线段树的升级版,其功能与传统的线段树相同,可以维护一个长度为n的数组,用O(log n)的时间复杂度更新元素,用O(log n)的时间复杂得到区间和。相比于传统线段树的递归实现,zkw线段树只要使用循环即可实现,并且代码行数更少,执行效率更好。
线段树有两个操作:
1 void update(int i, int delta):更新数组中下标为i的元素的值,将其值加delta
2 int get(int min, int max):得到区间[min, max]和
时间复杂度:更新和求区间和操作都是O(log n)
空间复杂度:O(n)
传统的线段树是自顶向下的,从根结点出发到叶子结点再回到根结点,而zkw线段树是自底向上的,直接从叶子结点出发到达根结点。
java代码实现:
/**
* 1
* / \
* 2 3
* / \ / \
* 4 5 6 7
* / \ / \ / \ / \
* 8 9 10 11 12 13 14 15
*/
public class ZkwSegmentTree {
private int[] nodes;
private int size;
private int firstLeaf;
public ZkwSegmentTree(int size) {
this.size = size;
for (firstLeaf = 1; firstLeaf < size; firstLeaf <<= 1);
nodes = new int[firstLeaf + size];
}
public ZkwSegmentTree(int[] a) {
size = a.length;
for (firstLeaf = 1; firstLeaf < size; firstLeaf <<= 1);
nodes = new int[firstLeaf + size];
System.arraycopy(a, 0, nodes, firstLeaf, size);
for (int ni = firstLeaf - 1; ni > 0; ni--) {
int left = ni << 1, right = ni << 1 | 1;
nodes[ni] = (left < nodes.length ? nodes[left] : 0) + (right < nodes.length ? nodes[right] : 0);
}
}
public void update(int i, int delta) {
for (int ni = firstLeaf + i; ni > 0; ni >>= 1) nodes[ni] += delta;
}
public int get(int i) {
return nodes[firstLeaf + i];
}
public int get(int min, int max) {
int sum = 0, left = firstLeaf + min, right = firstLeaf + max;
for (; left < right; left >>= 1, right >>= 1) {
if ((left & 1) == 1) sum += nodes[left++];
if ((right & 1) == 0) sum += nodes[right--];
}
if (left == right) sum += nodes[left];
return sum;
}
}
rust代码实现:
/**
* 1
* / \
* 2 3
* / \ / \
* 4 5 6 7
* / \ / \ / \ / \
* 8 9 10 11 12 13 14 15
*/
pub struct ZkwSegmentTree {
nodes: Vec<i32>,
size: usize,
first_leaf: usize,
}
impl ZkwSegmentTree {
pub fn new(size: usize) -> Self {
let mut first_leaf = 1;
while first_leaf < size {
first_leaf <<= 1;
}
let nodes = vec![0; first_leaf + size];
ZkwSegmentTree { nodes, size, first_leaf }
}
pub fn from(a: Vec<i32>) -> Self {
let size = a.len();
let mut first_leaf = 1;
while first_leaf < size {
first_leaf <<= 1;
}
let mut nodes = vec![0; first_leaf + size];
for i in 0..size {
nodes[first_leaf + i] = a[i];
}
for ni in (1..first_leaf).rev() {
let left = ni << 1;
let right = ni << 1 | 1;
nodes[ni] = nodes.get(left).unwrap_or(&0) + nodes.get(right).unwrap_or(&0)
}
ZkwSegmentTree { nodes, size, first_leaf }
}
pub fn update(&mut self, i: usize, delta: i32) {
let mut ni = self.first_leaf + i;
while ni > 0 {
self.nodes[ni] += delta;
ni >>= 1;
}
}
pub fn get(&self, i: usize) -> i32 {
self.nodes[self.first_leaf + i]
}
pub fn sum(&self, min: usize, max: usize) -> i32 {
let mut sum = 0;
let mut left = self.first_leaf + min;
let mut right = self.first_leaf + max;
while left < right {
if (left & 1) == 1 {
sum += self.nodes[left];
left += 1;
}
if (right & 1) == 0 {
sum += self.nodes[right];
right -= 1;
}
left >>= 1;
right >>= 1;
}
if left == right {
sum += self.nodes[left];
}
sum
}
}
源代码地址:GitHub - SSSxCCC/Algorithm: Implement some data structures and algorithm.