2020-06-03 22:18:17 +00:00
---
2020-06-15 23:19:07 +00:00
id: bit
2020-06-04 05:39:49 +00:00
title: "Binary Indexed Trees"
2020-06-04 01:42:57 +00:00
author: Benjamin Qi
2020-06-05 00:21:03 +00:00
prerequisites:
-
- Silver - Prefix Sums
2020-06-03 22:18:17 +00:00
---
2020-06-04 21:42:30 +00:00
A **Binary Indexed Tree** allows you to perform the following tasks in $O(\log N)$ time each on an array of size $N$:
2020-06-03 03:18:02 +00:00
2020-06-04 14:28:47 +00:00
- Update the element at a single position (point).
2020-06-16 01:44:03 +00:00
- Query the sum of a prefix of the array.
2020-06-03 03:18:02 +00:00
2020-06-04 14:28:47 +00:00
<!-- END DESCRIPTION -->
2020-06-03 03:18:02 +00:00
2020-06-04 14:28:47 +00:00
## Binary Indexed Tree
2020-06-03 03:18:02 +00:00
2020-06-04 21:42:30 +00:00
Aka **Fenwick Tree** .
2020-06-03 03:18:02 +00:00
2020-06-04 14:28:47 +00:00
### Sample Problems
2020-06-03 03:18:02 +00:00
* [CSES Range Sum Queries II ](https://cses.fi/problemset/task/1648 )
2020-06-03 20:16:33 +00:00
* can also do range XOR queries w/ update
2020-06-03 03:18:02 +00:00
* [SPOJ Inversion Counting ](https://www.spoj.com/problems/INVCNT/ )
2020-06-04 14:28:47 +00:00
### Tutorials
2020-06-03 03:18:02 +00:00
2020-06-03 03:42:17 +00:00
* CPH 9.2 (very good)
2020-06-03 03:18:02 +00:00
* [CSAcademy BIT ](https://csacademy.com/lesson/fenwick_trees ) (also very good)
* [cp-algorithms Fenwick Tree ](https://cp-algorithms.com/data_structures/fenwick.html )
2020-06-03 03:42:17 +00:00
* extends to range increment and range query, although this is not necessary for gold
2020-06-03 03:18:02 +00:00
* [Topcoder BIT ](https://www.topcoder.com/community/data-science/data-science-tutorials/binary-indexed-trees/ )
My implementation can be found [here ](https://github.com/bqi343/USACO/blob/master/Implementations/content/data-structures/1D%20Range%20Queries%20(9.2 )/BIT%20(9.2).h), and can compute range sum queries for any number of dimensions.
2020-06-03 14:17:07 +00:00
## Indexed Set
2020-06-03 03:18:02 +00:00
2020-06-03 14:17:07 +00:00
In the special case where all elements of the array are either zero or one (which is the case for several gold problems), users of C++ will find [indexed set ](https://github.com/bqi343/USACO/blob/master/Implementations/content/data-structures/STL%20(5 )/IndexedSet.h) useful. Using this, we can solve "Inversion Counting" in just a few lines (with template). `Tree<int>` behaves mostly the same way as `set<int>` with the additional functions
* `order_of_key(x)` : counts the number of elements in the indexed set that are strictly less than `x` .
* `find_by_order(k)` : similar to `find` , returns the iterator corresponding to the `k` -th lowest element in the set (0-indexed).
See the link for more examples of usage.
2020-06-03 03:18:02 +00:00
```cpp
2020-06-03 14:17:07 +00:00
#include <bits/stdc++.h>
using namespace std;
2020-06-03 03:18:02 +00:00
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
template < class T > using Tree = tree< T , null_type , less < T > ,
2020-06-03 03:42:17 +00:00
rb_tree_tag, tree_order_statistics_node_update>;
2020-06-03 03:18:02 +00:00
int main() {
2020-06-03 14:17:07 +00:00
int T; cin >> T;
for (int i = 0; i < T ; + + i ) {
int n; cin >> n;
Tree< int > TS; long long numInv = 0;
for (int j = 0; j < n ; + + j ) {
int x; cin >> x;
numInv += j-TS.order_of_key(x); // gives # elements before it > x
TS.insert(x);
2020-06-03 03:42:17 +00:00
}
2020-06-03 14:17:07 +00:00
cout < < numInv << " \n";
2020-06-03 03:42:17 +00:00
}
2020-06-03 03:18:02 +00:00
}
```
2020-06-03 03:56:59 +00:00
Note that if it were not the case that all elements of the input array were distinct, then this code would be incorrect since `Tree<int>` would remove duplicates. Instead, we would use an indexed set of pairs (`Tree< pair < int , int > >`), where the first element of each pair would denote the value while the second would denote the array position.
2020-06-03 14:17:07 +00:00
## Practice Problems
2020-06-03 03:18:02 +00:00
* USACO Gold
2020-06-03 03:42:17 +00:00
* The first three problems are just variations on inversion counting.
2020-06-03 03:18:02 +00:00
* [Haircut ](http://www.usaco.org/index.php?page=viewproblem2&cpid=1041 )
* [Balanced Photo ](http://www.usaco.org/index.php?page=viewproblem2&cpid=693 )
* [Circle Cross ](http://www.usaco.org/index.php?page=viewproblem2&cpid=719 )
* [Sleepy Cow Sort ](http://usaco.org/index.php?page=viewproblem2&cpid=898 )
2020-06-03 03:42:17 +00:00
* as far as I know, all gold problems have had only one possible output ...
2020-06-03 03:18:02 +00:00
* [Out of Sorts (harder?) ](http://www.usaco.org/index.php?page=viewproblem2&cpid=837 )
* Other Problems:
2020-06-04 03:26:53 +00:00
* [USACO Plat Mincross ](http://www.usaco.org/index.php?page=viewproblem2&cpid=720 )
2020-06-03 03:42:17 +00:00
* [Mega Inversions ](https://open.kattis.com/problems/megainversions )
* also just inversion counting
* [Out of Sorts (USACO Silver) ](http://usaco.org/index.php?page=viewproblem2&cpid=834 )
* aka [Sorting Steps ](https://csacademy.com/contest/round-42/task/sorting-steps/ ) [](42)
2020-06-04 03:26:53 +00:00
* Of course, this doesn't require anything other than sorting but fast range sum queries may make this easier.
* [Twin Permutations ](https://www.hackerearth.com/practice/data-structures/advanced-data-structures/fenwick-binary-indexed-trees/practice-problems/algorithm/mancunian-and-twin-permutations-d988930c/description/ )
2020-06-08 19:51:58 +00:00
* Offline 2D queries can be done with a 1D data structure