---
id: PURS
title: "Point Update Range Sum"
author: Benjamin Qi
prerequisites: 
 - Silver - Prefix Sums
description: Introducing Binary Indexed Trees & Indexed Sets (C++ only).
frequency: 3
---

import { Problem } from "../models";

export const metadata = {
  problems: {
    sample: [
      new Problem("YS", "Point Add Range Sum", "point_add_range_sum", "Easy", false, ["PURS"], ""),
      new Problem("CSES", "Range Sum Queries II", "1648", "Easy", false, ["PURS"], "Can also do range XOR queries w/ update."),
      new Problem("SPOJ", "Inversion Counting", "INVCNT", "Easy", false, ["PURS"]),
    ],
    practice: [
      new Problem("CSES", "List Removals", "1749", "Easy", false, undefined, "easy with indexed set"),
      new Problem("CSES", "Salary Queries", "1144", "Easy", false, undefined, "easy with indexed set"),
      new Problem("CSES", "Range Update Queries", "1651", "Easy", false, undefined, "not harder than point update range query"),
      new Problem("CSES", "Increasing Subsequence II", "1748", "Easy", false, undefined, ""),
      new Problem("CSES", "Intersection Points", "1740", "Easy", false, undefined, ""),
      new Problem("Kattis", "Mega Inversions", "megainversions", "Easy", false, undefined, "also just inversion counting"),
      new Problem("HackerEarth", "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/", "Easy", false, undefined, "Offline 2D queries can be done with a 1D data structure"),
      new Problem("CSES", "Distinct Values Queries", "1734", "Normal", false, undefined, "Do queries in increasing order of $a$."),
      new Problem("CSES", "Robot Path", "1742", "Hard", false, undefined, ""),
    ],
    usaco: [
      new Problem("Gold", "Haircut", "1041", "Easy", false, undefined, ""),
      new Problem("Gold", "Balanced Photo", "693", "Easy", false, undefined, ""),
      new Problem("Gold", "Circle Cross", "719", "Easy", false, undefined, ""),
      new Problem("Gold", "Sleepy Cow Sort", "898", "Easy", false, undefined, "All USACO problems (aside from some special exceptions) have only one possible output."),
      new Problem("Plat", "Mincross", "720", "Easy", false, undefined, ""),
      new Problem("Silver", "Out of Sorts", "834", "Normal", false, undefined, "aka Sorting Steps: https://csacademy.com/contest/round-42/task/sorting-steps/ -  Of course, this doesn't require anything other than sorting but fast range sum queries may make this easier."),
      new Problem("Gold", "Out of Sorts", "837", "Hard", false, undefined, ""),
      new Problem("Old Gold", "Cow Hopscotch", "532", "Hard", false, [], ""),
      new Problem("Plat", "Out of Sorts", "840", "Hard", false, [], ""),
    ],
  }
};

## Binary Indexed Tree

<problems-list problems={metadata.problems.sample} />

A *Binary Indexed Tree* (aka *Fenwick 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.

### Resources

<resources>
  <resource source="CSA" title="Fenwick Trees" url="fenwick_trees" starred>interactive</resource>
  <resource source="CPH" title="9.2, 9.4 - Binary Indexed Tree" starred>similar to above</resource>
  <resource source="cp-algo" title="Fenwick Tree" url="data_structures/fenwick.html">also similar to above</resource>
  <resource source="TC" title="Binary Indexed Trees" url="binary-indexed-trees"></resource>
</resources>

### Implementations

<resources>
  <resource source="CF" title="mouse_wireless - Multi-dimensional BITs with Templates" url="https://codeforces.com/blog/entry/64914" starred></resource>
  <resource source="Benq" title="BIT" url="https://github.com/bqi343/USACO/blob/master/Implementations/content/data-structures/1D%20Range%20Queries%20(9.2)/BIT%20(9.2).h">based off above</resource>
</resources>

## Finding $k$-th Element

Suppose that we want a data structure that supports all the operations as a `set` in C++ in addition to the following:

  * `order_of_key(x)`: counts the number of elements in the 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).


### Indexed Set

Luckily, such a built-in data structure already exists in C++.

<resources>
  <resource source="CF" url="blog/entry/11080" title="adamant - Policy Based Data Structures" starred> </resource>
  <resource source="Benq" url="https://github.com/bqi343/USACO/blob/master/Implementations/content/data-structures/STL%20(5)/IndexedSet.h" title="Indexed Set"></resource>
</resources>

Using this, we can solve "Inversion Counting" in just a few lines (with template).

<spoiler title="INVCNT with Indexed Set">

```cpp
#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";
	}
}
```

</spoiler>

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 position of the value in the array.

### Using a BIT

Assumes all updates are in the range $[1,N]$.

<resources>
  <resource source="CF" url="blog/entry/11275" title="adamant - About Ordered Set" starred> log N </resource>
  <resource source="GFG" url="order-statistic-tree-using-fenwick-tree-bit" title="Order Statistic Tree using BIT"> log^2 N </resource>
</resources>

## Practice Problems

<problems-list problems={metadata.problems.practice} />

## USACO Problems

Haircut, Balanced Photo, and Circle Cross are just variations on inversion counting.

<problems-list problems={metadata.problems.usaco} />
