4.8 KiB
id: PURS title: "Point Update Range Sum" author: Benjamin Qi prerequisites:
- Silver - Prefix Sums
description: ?
Binary Indexed Tree
A Binary Indexed Tree allows you to perform the following tasks in O(\log N)
time each on an array of size N
:
- Update the element at a single position (point).
- Query the sum of a prefix of the array.
Aka Fenwick Tree.
Sample Problems
- CSES Range Sum Queries II
- can also do range XOR queries w/ update
- SPOJ Inversion Counting
Tutorials
- CPH 9.2 (very good)
- CSAcademy BIT (also very good)
- cp-algorithms Fenwick Tree
- extends to range increment and range query, although this is not necessary for gold
- Topcoder BIT
My implementation can be found here, and can compute range sum queries for any number of dimensions.
Finding K-th Element?
Indexed Set
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 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 thanx
.find_by_order(k)
: similar tofind
, returns the iterator corresponding to thek
-th lowest element in the set (0-indexed).
See the link for more examples of usage.
#include <bits/stdc++.h>
using namespace std;
#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>,
rb_tree_tag, tree_order_statistics_node_update>;
int main() {
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);
}
cout << numInv << "\n";
}
}
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.
Practice Problems
- CSES
- List Removals
- easy with indexed set
- Salary Queries
- also easy with indexed set
- Range Update Queries
- range update point query is not harder than point update range query
- Increasing Subsequence II
- Intersection Points
- Distinct Values Queries
- answer queries in increasing order of
a
- answer queries in increasing order of
- Robot Path
- quite annoying
- List Removals
- USACO Gold
- The first three problems are just variations on inversion counting.
- Haircut
- Balanced Photo
- Circle Cross
- Sleepy Cow Sort
- as far as I know, all gold problems have had only one possible output ...
- Out of Sorts (harder?)
- Other Problems:
- USACO Plat Mincross
- Mega Inversions
- also just inversion counting
- Out of Sorts (USACO Silver)
- aka Sorting Steps
- Of course, this doesn't require anything other than sorting but fast range sum queries may make this easier.
- Twin Permutations
- Offline 2D queries can be done with a 1D data structure