PrevNext
Somewhat Frequent
 0/16

Point Update Range Sum

Authors: Benjamin Qi, Dong Liu, Nathan Gong

Contributors: Andrew Wang, Pramana Saldin

Segment Tree, Binary Indexed Tree, and Order Statistic Tree (in C++).

Most gold range query problems require you to support following tasks in O(logN)\mathcal{O}(\log N) time each on an array of size NN:

  • Update the element at a single position (point).
  • Query the sum of some consecutive subarray.

Both segment trees and binary indexed trees can accomplish this.

Segment Tree

A segment tree allows you to do point update and range query in O(logN)\mathcal{O}(\log N) time each for any associative operation, not just summation.

Resources

You can skip more advanced applications such as lazy propagation for now. They will be covered in platinum.

Resources
CF EDU

basic operations, inversion counting

CSA

Interactive updates.

CPH

Same implementation as AICash below.

CPC

See slides after union-find. Also introduces sqrt bucketing.

cp-algo

"Advanced versions" are covered in Platinum.

CF

simple implementation

KACTL

similar to above

Dynamic Range Minimum Queries

Focus Problem – try your best to solve this problem before continuing!

Recursive Implementation

Time Complexity: O((N+Q)logN)\mathcal{O}((N + Q) \log N)

#include <algorithm>
#include <iostream>
#include <limits>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
/** A data structure that can answer point update & range min queries. */

Iterative Implementation

Though less extensible, this implementation is shorter and has a better constant factor. The ranges it operates on are also end-exclusive, unlike the previous one which is end-inclusive.

Time Complexity: O((N+Q)logN)\mathcal{O}((N + Q) \log N)

#include <algorithm>
#include <iostream>
#include <limits>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
template <class T> class MinSegmentTree {

Dynamic Range Sum Queries

Focus Problem – try your best to solve this problem before continuing!

Recursive Implementation

Time Complexity: O((N+Q)logN)\mathcal{O}((N + Q) \log N)

Compared to the previous implementation, all we need to change are DEFAULT and how we combine the elements.

#include <algorithm>
#include <iostream>
#include <limits>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
Code Snippet: Segment Tree (Click to expand)

Iterative Implementation

Time Complexity: O((N+Q)logN)\mathcal{O}((N + Q) \log N)

#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
Code Snippet: Segment Tree (Click to expand)
int main() {

Binary Indexed Tree

The implementation is shorter than segment tree, but maybe more confusing at first glance.

Resources

Resources
CSA

interactive

CPH

similar to above

cp-algo

also similar to above

TC

Dynamic Range Sum Queries

Implementation

#include <cassert>
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
/**
* Short for "binary indexed tree",

Finding the kk-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).

Order Statistic Tree

Luckily, such a built-in data structure already exists in C++. However, it's only supported on GCC, so Clang users are out of luck.

Resources
CF
CPH

brief overview with find_by_order and order_of_key

KACTL

code

With a BIT

However, if all updates are in the range [1,N][1,N], we can do the same thing with a BIT.

With a Segment Tree

Covered in Platinum.

Inversion Counting

Focus Problem – try your best to solve this problem before continuing!

Implementation

Using an indexed set, we can solve this in just a few lines.

#include <bits/stdc++.h>
using namespace std;
#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() {

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.

Problems

Coordinate Compression

If the coordinates are large (say, up to 10910^9), then you should apply coordinate compression before using a BIT or segment tree (though sparse segment trees do exist).

General

StatusSourceProblem NameDifficultyTags
CSESEasy
Show TagsPURS
KattisEasy
Show TagsInversions, PURS
CSESEasy
Show TagsPURS
CSESEasy
Show TagsCoordinate Compress, PURS
CFEasy
Show TagsBinary Search, Offline, PURS
CSESEasy
Show TagsCoordinate Compress, PURS
CSESNormal
Show TagsOffline, PURS

USACO

StatusSourceProblem NameDifficultyTags
GoldEasy
Show TagsInversions, PURS
GoldEasy
Show TagsInversions, PURS
GoldEasy
Show TagsInversions, PURS
GoldEasy
Show TagsPURS
PlatinumEasy
Show TagsInversions, PURS
Old GoldHard
Show TagsPURS

A hint regarding Sleepy Cow Sort: There is only one correct output.

Module Progress:

Join the USACO Forum!

Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!

PrevNext