-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFenwickTree.java
139 lines (127 loc) · 4.62 KB
/
FenwickTree.java
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/**
* This class implements a Fenwick tree data structure.
*
* A Fenwick tree or binary indexed tree is a data structure providing efficient
* methods for calculation and manipulation of the prefix sums of a table of
* values.
*
* For more information: http://en.wikipedia.org/wiki/Fenwick_tree
*
* @author Sebastian Claici
*
*/
public static class FenwickTree {
/*
* The element at position i in a Fenwick tree stores the cumulative
* frequency for the range [i - 2 ^ r + 1, i], where r is the lowest set bit
* in the binary representation of i.
*/
private final int size;
private final int[] tree;
/**
* Constructs a Fenwick tree from init. Each element in the resulting tree
* will hold the cumulative frequency up to that point according to the
* iterator of the Collection.
*
* @param init
* A Collection with the initial values.
*/
public FenwickTree(Collection<Integer> init) {
size = init.size();
tree = new int[init.size() + 1];
int i = 1;
for (Integer value : init)
update(i++, value);
}
/**
* Constructs a Fenwick tree of a specified size. Each element in the tree
* will be initially 0.
*
* @param size
* Size of the tree to be constructed.
*/
public FenwickTree(int size) {
this.size = size;
tree = new int[size + 1];
}
/**
* Queries the cumulative frequency at id.
*
* @param id
* The index (1-based) to query.
* @return An integer representing the cumulative frequency up to id
* (inclusive).
*/
public int query(int id) {
int result = 0;
while (id > 0) {
result += tree[id];
/*
* To query an index, we need all indices that were not included in
* previous intervals of form [i - 2 ^ r + 1, i]. That is, we need
* to find the next lowest number that does not have the lowest bit
* in i set. (id & -id) represents the lowest bit in id; by
* subtracting this we reach the next number we need to query.
*/
id -= (id & -id);
}
return result;
}
/**
* Queries the cumulative frequency in the range [left, right].
*
* @param left
* Leftmost index of the range being queried.
* @param right
* Rightmost index of the range being queried.
* @return An integer representing the cumulative frequency between left and
* right (both inclusive).
*/
public int query(int left, int right) {
return query(right) - query(left - 1);
}
/**
* Updates the value at index id by adding toAdd to it.
*
* @param id
* Index which should be updated.
* @param toAdd
* Amount to add to the element at index id.
*/
public void update(int id, int toAdd) {
while (id <= size) {
tree[id] += toAdd;
/*
* To update an index, we need to update all indices that subsume
* the current range [i - 2 ^ r + 1, i]. That is, we need to find
* the next highest number that has the lowest bit of i unset.
*/
id += (id & -id);
}
}
/**
* Find an index k in the Fenwick tree such that the cumulative frequency up
* to k is exactly equal to sum.
*
* @param sum
* Sum for which an index should be found.
* @return The index (1-based) in the tree where this occurs, or -1 if no
* index satisfies the requirements.
*/
public int find(int sum) {
int bitmask = 1;
for (; bitmask <= size; bitmask *= 2)
;
for (int i = 0; bitmask != 0; bitmask /= 2) {
if (i + bitmask <= size) {
if (tree[i + bitmask] <= sum) {
i += bitmask;
sum -= tree[i];
if (sum == 0)
return i;
}
}
}
return -1;
}
}