动态连续区间和查询,Binary Index Tree 算法

来源:互联网 发布:java web论坛 编辑:程序博客网 时间:2024/06/06 10:41

给定N元数组A[0]...A[N-1],设计一个数据结构,支持两种操作:

1. add(i,v) 将A[i]元素值增加v,下标i区间为[0..N-1]

2. sum(L,R) 查询连续区间和 A[L] + A[L+1] + ... + A[R], 下标L,R区间为[0..N-1]

二叉索引树 Binary Index Tree 支持动态连续区间和的查询,BIT含有N个结点,每个结点存储一段区间的和。每次更新数组A的一个元素,只需要更新BIT中的LogN个结点;每次查询A的前缀区间和,只需要查询BIT中的LogN个节点;

BIT树用数组表示,下标区间为[1..N],左孩子i其父结点为i+lowbit(i),右孩子i其父节点为i-lowbit(i),每个BIT结点i代表的区间和为A[i-lowbit(i)+1] + A[i-lowbit(i)+2] + ... + A[i]。其中lowbit(i)=i&(-i)即i的最低非0位代表的值(1,2,4,8,...)。

package ProgrammingContest;public class BinaryIndexTree {private int N = 0;private int[] A = null;private int[] C = null;public BinaryIndexTree(int[] A) {this.A = A;N = A.length;init(A);}// 更新一个元素,下标范围[0..N-1]private void add(int i, int v) {i++; // 下标范围转换为[1..N]while (1 <= i && i <= N) {C[i] += v;i += lowBit(i);}}// 取一个元素,下标范围[0..N-1]public int get(int i) {return A[i];}// 初始化BinaryIndexTree即数组Cpublic void init(int[] A) {C = new int[A.length + 1];for (int i = 0; i < C.length; i++)C[i] = 0;for (int i = 0; i < A.length; i++) {add(i, A[i]);}}private int lowBit(int x) {return x & (-x);}// 设置A[i], 下标范围[0..N-1]public void set(int i, int v) {int delta = v - A[i];A[i] = v;add(i, delta);}// 求前缀和A[0]+...+A[i]public int sum(int i) {i++; // 下标范围转换为[1..N]int sum = 0;while (i >= 1) {sum += C[i];i -= lowBit(i);}return sum;}// 查询区间[L,R]所有元素的和,下标范围[0..N-1]public int query(int L, int R) {int res = sum(R) - sum(L) + A[L];return res;}// 测试public static void main(String[] args) {int[] x = { 2, 1, 3, 4, 5 };BinaryIndexTree bit = new BinaryIndexTree(x);for ( int i = 0; i< x.length; i++ ) {System.out.println(bit.query(0, i));}}}



原创粉丝点击