树状数组 或 二叉索引树 (Binary Indexed Tree),又以其发明者命名为Fenwick树,最早由Peter M. Fenwick于1994年以A New Data Structure for Cumulative Frequency Tables为题发表在SOFTWARE PRACTICE AND EXPERIENCE。其初衷是解决数据压缩里的累积频率(Cumulative Frequency)的计算问题,现多用于高效计算数列的前缀和,区间和。
单点更新 1 2 3 4 5 6 void update (int x, int val) { while (x <= N) { bit[x] += val; x += lowbit(x); } }
求最低位1 巧妙地利用了负数是以 补码 (反码 + 1)的形式存储,将原数字和它的补码 按位与 得到最低位的 1。
1 2 3 int lowbit (int x) { return x & -x; }
求前缀和 1 2 3 4 5 6 7 8 int query (int x) { int ans = 0 ; while (x > 0 ) { ans += bit[x]; x -= lowbit(x); } return ans; }
求区间和 1 2 3 int query (int a, int b) { return query(b) - query(a - 1 ); }
测试代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 package 数据结构;public class BitTree { static int N; static int [] bit; public static void main (String[] args) { int [] nums = new int []{1 , 2 , 3 , 4 , 5 }; N = nums.length; bit = new int [N + 1 ]; for (int i = 1 ; i <= N; i++) { update(i, nums[i - 1 ]); } System.out.println("前缀和:" + query(4 )); System.out.println("区间和:" + query(2 , 4 )); } public static int query (int x) { int ans = 0 ; while (x > 0 ) { ans += bit[x]; x -= lowbit(x); } return ans; } public static int query (int a, int b) { return query(b) - query(a - 1 ); } public static void update (int x, int val) { while (x <= N) { bit[x] += val; x += lowbit(x); } } public static int lowbit (int x) { return x & -x; } }