This repository has been archived on 2022-06-22. You can view files and clone it, but cannot push or open issues or pull requests.
usaco-guide/content/5_Gold/PURS.md
Benjamin Qi 84cc6bcebd + PAPS
2020-06-22 21:00:35 -04:00

4.9 KiB

id title author prerequisites description
PURS Point Update Range Sum Benjamin Qi
Silver - Prefix Sums
Binary Indexed Trees & Indexed Sets

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

Tutorials

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 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.

#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