-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFenwickTree.java
107 lines (97 loc) · 2.39 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
package gfg.ds.advanced.fenwick_tree;
/**
* NOTE: Index are 1-based
*/
public class FenwickTree {
public int[] values;
public int n;
public FenwickTree(int[] arr, int n) {
// Oth index is a dummy index.
this.n = n;
this.values = new int[n + 1];
build(arr);
}
/** t=n*log(n) */
private void build(int[] arr) {
for (int i = 0; i < n; i++) {
update(i + 1, arr[i]);
}
}
/** t=O(log n) */
public void update(int index, int increment) {
if (index == 0) {
return;
}
while (index < n + 1) {
values[index] += increment;
index += index & (-index);
}
}
/** t=O(log n) */
public int rq(int leftLimit, int rightLimit) {
assert leftLimit <= rightLimit;
if (leftLimit == rightLimit) {
return valueAt(leftLimit);
}
return query(rightLimit) - query(leftLimit - 1);
}
/** t=O(log n) */
public int query(int index) {
if (index == 0) {
return 0;
}
int sum = 0;
while (index > 0) {
sum += values[index];
index -= index & (-index);
}
return sum;
}
/** Can be implemented as query(index)- query(index-1) */
public int valueAt(int index) {
// let index is a1b` where b` consists of all zeroes
int sum = values[index];
// a0b`
int parent = index - (index & (-index));
// a1b` - 1 = a0b; b consists of all ones
index--;
// their is some point where all ones are removed and z is reached.
while (index != parent) {
sum -= values[index];
index -= index & (-index);
}
return sum;
}
public void scale(int c) {
for (int i = 0; i < n + 1; i++) {
values[i] /= c;
}
}
/**
* It returns 1 based index
*
* @param freqSum cumulative sum for which Fenwick Tree's index is needed.
*/
public int findIndexWithFreqSum(int freqSum) {
// greatest bit of max index; right most node of the 1st level of the tree.
int bitmask = (int) Math.pow(2, (int) (Math.log10(n + 1) / Math.log10(2)));
int index = 0;
while (bitmask != 0) {
int tempIndex = index + bitmask;
bitmask >>= 1;
if (tempIndex > n + 1) {
continue;
}
if (freqSum == values[tempIndex]) {
return tempIndex;
} else if (freqSum > values[tempIndex]) {
index = tempIndex;
freqSum -= values[tempIndex];
}
}
if (freqSum != 0) {
return -1;
}
return index;
}
}