Corrections

This commit is contained in:
Antti H S Laaksonen 2017-02-15 23:22:40 +02:00
parent 9cd7cc801c
commit b04d80b1f8
1 changed files with 40 additions and 42 deletions

View File

@ -5,13 +5,16 @@
\index{minimum query} \index{minimum query}
\index{maximum query} \index{maximum query}
A \key{range query} asks to calculate some information In this chapter, we discuss data structures
about the elements in a given range of an array. that allow us to efficiently answer range queries.
In a \key{range query}, we are given two indices
to an array, and our task is to calculate some
value based on the elements between the given indices.
Typical range queries are: Typical range queries are:
\begin{itemize} \begin{itemize}
\item \key{sum query}: calculate the sum of elements in a range \item \key{sum query}: calculate the sum of elements
\item \key{minimum query}: find the smallest element in a range \item \key{minimum query}: find the smallest element
\item \key{maximum query}: find the largest element in a range \item \key{maximum query}: find the largest element
\end{itemize} \end{itemize}
For example, consider the range $[4,7]$ in the following array: For example, consider the range $[4,7]$ in the following array:
\begin{center} \begin{center}
@ -44,12 +47,12 @@ the minimum element is 1 and the maximum element is 6.
A simple way to process range queries is to A simple way to process range queries is to
go through all elements in the range. go through all elements in the range.
For example, the following function \texttt{rsq} For example, the following function \texttt{sum}
calculates the sum of elements in any range calculates the sum of elements in a range
$[a,b]$ of an array $t$: $[a,b]$ of an array $t$:
\begin{lstlisting} \begin{lstlisting}
int rsq(int a, int b) { int sum(int a, int b) {
int s = 0; int s = 0;
for (int i = a; i <= b; i++) { for (int i = a; i <= b; i++) {
s += t[i]; s += t[i];
@ -62,10 +65,9 @@ The above function works in $O(n)$ time,
where $n$ is the number of elements in the array. where $n$ is the number of elements in the array.
Thus, we can process $q$ queries in $O(nq)$ Thus, we can process $q$ queries in $O(nq)$
time using the function. time using the function.
If both $n$ and $q$ are large, this approach However, if both $n$ and $q$ are large, this approach
is slow. is slow, and it turns out that there are
In this chapter, we will learn how ways to process range queries much more efficiently.
range queries can be processed much more efficiently.
\section{Static array queries} \section{Static array queries}
@ -74,7 +76,7 @@ the array is \key{static}, i.e.,
the elements are never modified between the queries. the elements are never modified between the queries.
In this case, it suffices to construct In this case, it suffices to construct
a data structure that tells us a data structure that tells us
the answer for any possible range query efficiently. the answer for any possible query efficiently.
\subsubsection{Sum queries} \subsubsection{Sum queries}
@ -82,13 +84,11 @@ the answer for any possible range query efficiently.
Let $\textrm{rsq}(a,b)$ (''range sum query'') be the sum of Let $\textrm{rsq}(a,b)$ (''range sum query'') be the sum of
elements in the range $[a,b]$ of an array. elements in the range $[a,b]$ of an array.
Our first task is to find a way to calculate any value of $\textrm{rsq}(a,b)$ To answer such queries efficiently,
efficiently. we can construct a data structure called
It turns out that there is a simple data structure a \key{sum array}.
that we can use: a \key{sum array}. Each element in a sum array contains
Such an array contains all values of the form the sum of elements in the original array up to that position.
$\textrm{rsq}(1,k)$ where $1 \le k \le n$,
i.e., for each $k$ the sum of the first $k$ elements of the array.
For example, consider the following array: For example, consider the following array:
\begin{center} \begin{center}
@ -143,7 +143,9 @@ The corresponding sum array is as follows:
\node at (7.5,1.4) {$8$}; \node at (7.5,1.4) {$8$};
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Now we can calculate any value of Since the sum array contains all values
of the form $\textrm{rsq}(1,k)$ for $1 \le k \le n$,
we can calculate any value of
$\textrm{rsq}(a,b)$ in $O(1)$ time, because $\textrm{rsq}(a,b)$ in $O(1)$ time, because
\[ \textrm{rsq}(a,b) = \textrm{rsq}(1,b) - \textrm{rsq}(1,a-1).\] \[ \textrm{rsq}(a,b) = \textrm{rsq}(1,b) - \textrm{rsq}(1,a-1).\]
It is convenient to define $\textrm{rsq}(1,0)=0$, It is convenient to define $\textrm{rsq}(1,0)=0$,
@ -241,14 +243,14 @@ to the position of $X$.
Let $\textrm{rmq}(a,b)$ (''range minimum query'') be the Let $\textrm{rmq}(a,b)$ (''range minimum query'') be the
minimum element in the range $[a,b]$ of an array. minimum element in the range $[a,b]$ of an array.
It is possible to process also minimum queries It is possible to answer also minimum queries
in $O(1)$ time, though it is more difficult than in $O(1)$ time, though it is more difficult than
processing sum queries. processing sum queries.
Note that minimum and maximum queries can always Note that minimum and maximum queries can always
be processed using similar techniques, be processed using similar techniques,
so it suffices to focus on minimum queries. so it suffices to focus on minimum queries.
The idea is to precalculate all values $\textrm{rmq}(a,b)$ The idea is to precalculate all values of $\textrm{rmq}(a,b)$
where $b-a+1$, the length of the range, is a power of two. where $b-a+1$, the length of the range, is a power of two.
For example, for the array For example, for the array
@ -442,7 +444,7 @@ and modifying the value of an element.
The advantage of a binary indexed tree is The advantage of a binary indexed tree is
that it allows us to efficiently update that it allows us to efficiently update
the array between the sum queries. the array elements between the sum queries.
This would not be possible using a sum array, This would not be possible using a sum array,
because after each update, we should build the because after each update, we should build the
whole sum array again in $O(n)$ time. whole sum array again in $O(n)$ time.
@ -451,7 +453,8 @@ whole sum array again in $O(n)$ time.
A binary indexed tree can be represented as an array A binary indexed tree can be represented as an array
whose each value is the sum of elements in a range. whose each value is the sum of elements in a range.
More precisely, the value at position $x$ is $\textrm{rsq}(x-k+1,x)$, More precisely, the value at position $x$
is $\textrm{rsq}(x-k+1,x)$,
where $k$ is the largest power of two that divides $x$. where $k$ is the largest power of two that divides $x$.
For example, if $x=6$, then $k=2$, because 2 divides 6 For example, if $x=6$, then $k=2$, because 2 divides 6
but 4 does not divide 6. but 4 does not divide 6.
@ -568,9 +571,7 @@ corresponds to a range in the array:
The values in the binary indexed tree The values in the binary indexed tree
can be used to efficiently calculate can be used to efficiently calculate
any value of $\textrm{rsq}(1,k)$: any value of $\textrm{rsq}(1,k)$.
the sum of elements in the range $[1,k]$
of the array.
It turns out that any range $[1,k]$ It turns out that any range $[1,k]$
can be divided into $O(\log n)$ ranges can be divided into $O(\log n)$ ranges
whose sums are available in the binary indexed tree. whose sums are available in the binary indexed tree.
@ -630,7 +631,7 @@ Also in this case, only $O(\log n)$ values are needed.
\subsubsection{Array update} \subsubsection{Array update}
When a value in the array is updated, When a value in the array changes,
several values in the binary indexed tree should be updated. several values in the binary indexed tree should be updated.
For example, if the element at position 3 changes, For example, if the element at position 3 changes,
the sums of the following ranges change: the sums of the following ranges change:
@ -689,8 +690,8 @@ The operations of a binary indexed tree can be implemented
in an elegant and efficient way using bit operations. in an elegant and efficient way using bit operations.
The key fact needed is that $k \& -k$ The key fact needed is that $k \& -k$
isolates the last one bit of a number $k$. isolates the last one bit of a number $k$.
For example, $6 \& -6=2$ because the number $6$ For example, $26 \& -26=2$ because the number $26$
corresponds to 110 and the number $2$ corresponds to 10. corresponds to 11010 and the number $2$ corresponds to 10.
It turns out that when processing a sum query, It turns out that when processing a sum query,
the position $k$ in the binary indexed tree needs to be the position $k$ in the binary indexed tree needs to be
@ -702,7 +703,7 @@ Suppose that the binary indexed tree is stored in an array \texttt{b}.
The following function calculates The following function calculates
the sum of elements in a range $[1,k]$: the sum of elements in a range $[1,k]$:
\begin{lstlisting} \begin{lstlisting}
int rsq(int k) { int sum(int k) {
int s = 0; int s = 0;
while (k >= 1) { while (k >= 1) {
s += b[k]; s += b[k];
@ -1092,7 +1093,7 @@ The following function
calculates the sum of elements in a range $[a,b]$: calculates the sum of elements in a range $[a,b]$:
\begin{lstlisting} \begin{lstlisting}
int rsq(int a, int b) { int sum(int a, int b) {
a += N; b += N; a += N; b += N;
int s = 0; int s = 0;
while (a <= b) { while (a <= b) {
@ -1139,13 +1140,10 @@ and the operations move one level forward in the tree at each step.
\subsubsection{Other queries} \subsubsection{Other queries}
A segment tree can support any queries Segment trees can support any queries
as long as the results of the queries as long as we can divide a range into two parts,
can be combined efficiently; calculate the answer for both parts
if the results for ranges $[a,b]$ and $[c,d]$ and then efficiently combine the answers.
are known and $b$ and $c$ are two adjacent positions,
it should be easy to compute the result
for the range $[x,z]$.
Examples of such queries are Examples of such queries are
minimum and maximum, greatest common divisor, minimum and maximum, greatest common divisor,
and bit operations and, or and xor. and bit operations and, or and xor.
@ -1266,13 +1264,13 @@ by traversing a path downwards from the top node:
A limitation in data structures that A limitation in data structures that
are built upon an array is that are built upon an array is that
the elements are indexed using integers the elements are indexed using
consecutive integers. consecutive integers.
Difficulties arise when large indices Difficulties arise when large indices
are needed. are needed.
For example, if we wish to use the index $10^9$, For example, if we wish to use the index $10^9$,
the array should contain $10^9$ the array should contain $10^9$
elements which is not realistic. elements which would require too much memory.
\index{index compression} \index{index compression}