Corrections
This commit is contained in:
parent
9854d9d6ea
commit
9cd7cc801c
123
luku09.tex
123
luku09.tex
|
@ -702,7 +702,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 sum(int k) {
|
int rsq(int k) {
|
||||||
int s = 0;
|
int s = 0;
|
||||||
while (k >= 1) {
|
while (k >= 1) {
|
||||||
s += b[k];
|
s += b[k];
|
||||||
|
@ -755,12 +755,19 @@ memory and is a bit more difficult to implement.
|
||||||
A segment tree is a binary tree that
|
A segment tree is a binary tree that
|
||||||
contains $2n-1$ nodes.
|
contains $2n-1$ nodes.
|
||||||
The nodes on the bottom level of the tree
|
The nodes on the bottom level of the tree
|
||||||
correspond to the original array,
|
correspond to the array elements,
|
||||||
and the other nodes
|
and the other nodes
|
||||||
contain information needed for processing range queries.
|
contain information needed for processing range queries.
|
||||||
|
|
||||||
We will first discuss segment trees that support
|
Throughout the section, we assume that the size
|
||||||
sum queries. As an example, consider the following array:
|
of the array is a power of two and zero-based
|
||||||
|
indexing is used, because it is convenient to build
|
||||||
|
a segment tree for such an array.
|
||||||
|
If the size of the array is not a power of two,
|
||||||
|
we can always append extra elements to it.
|
||||||
|
|
||||||
|
We will first discuss segment trees that support sum queries.
|
||||||
|
As an example, consider the following array:
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.7]
|
\begin{tikzpicture}[scale=0.7]
|
||||||
\draw (0,0) grid (8,1);
|
\draw (0,0) grid (8,1);
|
||||||
|
@ -774,15 +781,15 @@ sum queries. As an example, consider the following array:
|
||||||
\node at (6.5,0.5) {$2$};
|
\node at (6.5,0.5) {$2$};
|
||||||
\node at (7.5,0.5) {$6$};
|
\node at (7.5,0.5) {$6$};
|
||||||
|
|
||||||
% \footnotesize
|
\footnotesize
|
||||||
% \node at (0.5,1.4) {$1$};
|
\node at (0.5,1.4) {$0$};
|
||||||
% \node at (1.5,1.4) {$2$};
|
\node at (1.5,1.4) {$1$};
|
||||||
% \node at (2.5,1.4) {$3$};
|
\node at (2.5,1.4) {$2$};
|
||||||
% \node at (3.5,1.4) {$4$};
|
\node at (3.5,1.4) {$3$};
|
||||||
% \node at (4.5,1.4) {$5$};
|
\node at (4.5,1.4) {$4$};
|
||||||
% \node at (5.5,1.4) {$6$};
|
\node at (5.5,1.4) {$5$};
|
||||||
% \node at (6.5,1.4) {$7$};
|
\node at (6.5,1.4) {$6$};
|
||||||
% \node at (7.5,1.4) {$8$};
|
\node at (7.5,1.4) {$7$};
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
The corresponding segment tree is as follows:
|
The corresponding segment tree is as follows:
|
||||||
|
@ -833,15 +840,6 @@ node is the sum of the corresponding array elements,
|
||||||
and it can be calculated as the sum of
|
and it can be calculated as the sum of
|
||||||
the values of its left and right child node.
|
the values of its left and right child node.
|
||||||
|
|
||||||
It is convenient to build a segment tree
|
|
||||||
for an array whose size is a power of two,
|
|
||||||
because in this case every internal node has a left
|
|
||||||
and right child.
|
|
||||||
In the sequel, we will assume that the tree
|
|
||||||
is built like this.
|
|
||||||
If the size of the array is not a power of two,
|
|
||||||
we can always add zero elements to the array.
|
|
||||||
|
|
||||||
\subsubsection{Range query}
|
\subsubsection{Range query}
|
||||||
|
|
||||||
The sum of elements in a given range
|
The sum of elements in a given range
|
||||||
|
@ -875,7 +873,7 @@ For example, consider the following range:
|
||||||
The sum of elements in the range is
|
The sum of elements in the range is
|
||||||
$6+3+2+7+2+6=26$.
|
$6+3+2+7+2+6=26$.
|
||||||
The following two nodes in the tree
|
The following two nodes in the tree
|
||||||
cover the range:
|
correspond to the range:
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.7]
|
\begin{tikzpicture}[scale=0.7]
|
||||||
\draw (0,0) grid (8,1);
|
\draw (0,0) grid (8,1);
|
||||||
|
@ -921,7 +919,7 @@ that are located as high as possible in the tree,
|
||||||
at most two nodes on each level
|
at most two nodes on each level
|
||||||
of the tree are needed.
|
of the tree are needed.
|
||||||
Hence, the total number of nodes
|
Hence, the total number of nodes
|
||||||
examined is only $O(\log n)$.
|
is only $O(\log n)$.
|
||||||
|
|
||||||
\subsubsection{Array update}
|
\subsubsection{Array update}
|
||||||
|
|
||||||
|
@ -985,10 +983,11 @@ so each update changes $O(\log n)$ nodes in the tree.
|
||||||
|
|
||||||
A segment tree can be stored in an array
|
A segment tree can be stored in an array
|
||||||
of $2N$ elements where $N$ is a power of two.
|
of $2N$ elements where $N$ is a power of two.
|
||||||
From now on, we will assume that the indices
|
Such a tree corresponds to an array
|
||||||
of the original array are between $0$ and $N-1$.
|
indexed from $0$ to $N-1$.
|
||||||
|
|
||||||
The element at position 1 in the array
|
In the segment tree array,
|
||||||
|
the element at position 1
|
||||||
corresponds to the top node of the tree,
|
corresponds to the top node of the tree,
|
||||||
the elements at positions 2 and 3 correspond to
|
the elements at positions 2 and 3 correspond to
|
||||||
the second level of the tree, and so on.
|
the second level of the tree, and so on.
|
||||||
|
@ -1082,18 +1081,18 @@ for a node at position $k$,
|
||||||
\item the left child node is at position $2k$, and
|
\item the left child node is at position $2k$, and
|
||||||
\item the right child node is at position $2k+1$.
|
\item the right child node is at position $2k+1$.
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
Note that this implies that the index of a node
|
% Note that this implies that the index of a node
|
||||||
is even if it is a left child and odd if it is a right child.
|
% is even if it is a left child and odd if it is a right child.
|
||||||
|
|
||||||
\subsubsection{Functions}
|
\subsubsection{Functions}
|
||||||
|
|
||||||
We assume that the segment tree is stored
|
Assume that the segment tree is stored
|
||||||
in an array \texttt{p}.
|
in an array \texttt{p}.
|
||||||
The following function
|
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 sum(int a, int b) {
|
int rsq(int a, int b) {
|
||||||
a += N; b += N;
|
a += N; b += N;
|
||||||
int s = 0;
|
int s = 0;
|
||||||
while (a <= b) {
|
while (a <= b) {
|
||||||
|
@ -1105,15 +1104,15 @@ int sum(int a, int b) {
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
|
||||||
The function maintains a range in the segment tree array.
|
The function starts at the bottom of the tree
|
||||||
Initially the range is $[a+N,b+N]$,
|
and moves one level up at each step.
|
||||||
that corresponds to the range $[a,b]$
|
Initially, the range $[a+N,b+N]$ corresponds
|
||||||
in the underlying array.
|
to the range $[a,b]$ in the original array.
|
||||||
At each step, the function adds the value of
|
At each step, the function adds the value of
|
||||||
the left and right node to the sum
|
the left and right node to the sum
|
||||||
if their parent nodes do not belong to the range.
|
if their parent nodes do not belong to the range.
|
||||||
After this, the same process continues on the
|
This process continues, until the sum of the
|
||||||
next level of the tree.
|
range has been calculated.
|
||||||
|
|
||||||
The following function increases the value
|
The following function increases the value
|
||||||
of the element at position $k$ by $x$:
|
of the element at position $k$ by $x$:
|
||||||
|
@ -1140,11 +1139,13 @@ 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 query
|
A segment tree can support any queries
|
||||||
where the answer for a range $[a,b]$
|
as long as the results of the queries
|
||||||
can be calculated
|
can be combined efficiently;
|
||||||
from the answers for ranges $[a,c]$ and $[c+1,b]$, where
|
if the results for ranges $[a,b]$ and $[c,d]$
|
||||||
$c$ is some index between $a$ and $b$.
|
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.
|
||||||
|
@ -1195,7 +1196,7 @@ supports minimum queries:
|
||||||
|
|
||||||
In this segment tree, every node in the tree
|
In this segment tree, every node in the tree
|
||||||
contains the smallest element in the corresponding
|
contains the smallest element in the corresponding
|
||||||
range of the underlying array.
|
range of the array.
|
||||||
The top node of the tree contains the smallest
|
The top node of the tree contains the smallest
|
||||||
element in the whole array.
|
element in the whole array.
|
||||||
The operations can be implemented like previously,
|
The operations can be implemented like previously,
|
||||||
|
@ -1205,7 +1206,7 @@ but instead of sums, minima are calculated.
|
||||||
|
|
||||||
The structure of the segment tree allows us
|
The structure of the segment tree allows us
|
||||||
to use binary search for finding elements in the array.
|
to use binary search for finding elements in the array.
|
||||||
For example, if the tree supports the minimum query,
|
For example, if the tree supports minimum queries,
|
||||||
we can find the position of the smallest
|
we can find the position of the smallest
|
||||||
element in $O(\log n)$ time.
|
element in $O(\log n)$ time.
|
||||||
|
|
||||||
|
@ -1266,7 +1267,7 @@ 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 integers
|
||||||
$1,2,3,$ etc.
|
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$,
|
||||||
|
@ -1278,7 +1279,7 @@ elements which is not realistic.
|
||||||
However, we can often bypass this limitation
|
However, we can often bypass this limitation
|
||||||
by using \key{index compression},
|
by using \key{index compression},
|
||||||
where the original indices are replaced
|
where the original indices are replaced
|
||||||
with the indices $1,2,3,$ etc.
|
with indices $1,2,3,$ etc.
|
||||||
This can be done if we know all the indices
|
This can be done if we know all the indices
|
||||||
needed during the algorithm beforehand.
|
needed during the algorithm beforehand.
|
||||||
|
|
||||||
|
@ -1288,7 +1289,7 @@ compresses the indices.
|
||||||
We require that the order of the indices
|
We require that the order of the indices
|
||||||
does not change, so if $a<b$, then $p(a)<p(b)$.
|
does not change, so if $a<b$, then $p(a)<p(b)$.
|
||||||
This allows us to conviently perform queries
|
This allows us to conviently perform queries
|
||||||
despite the fact that the indices are compressed.
|
even if the indices are compressed.
|
||||||
|
|
||||||
For example, if the original indices are
|
For example, if the original indices are
|
||||||
$555$, $10^9$ and $8$, the new indices are:
|
$555$, $10^9$ and $8$, the new indices are:
|
||||||
|
@ -1301,12 +1302,12 @@ p(10^9) & = & 3 \\
|
||||||
\end{array}
|
\end{array}
|
||||||
\]
|
\]
|
||||||
|
|
||||||
\subsubsection{Range update}
|
\subsubsection{Range updates}
|
||||||
|
|
||||||
So far, we have implemented data structures
|
So far, we have implemented data structures
|
||||||
that support range queries and modifications
|
that support range queries and updates
|
||||||
of single values.
|
of single values.
|
||||||
Let us now consider a reverse situation,
|
Let us now consider an opposite situation,
|
||||||
where we should update ranges and
|
where we should update ranges and
|
||||||
retrieve single values.
|
retrieve single values.
|
||||||
We focus on an operation that increases all
|
We focus on an operation that increases all
|
||||||
|
@ -1314,10 +1315,11 @@ elements in a range $[a,b]$ by $x$.
|
||||||
|
|
||||||
Surprisingly, we can use the data structures
|
Surprisingly, we can use the data structures
|
||||||
presented in this chapter also in this situation.
|
presented in this chapter also in this situation.
|
||||||
To do this, we change the array so that
|
To do this, we build an \key{inverse sum array}
|
||||||
each element indicates the \emph{change}
|
for the array.
|
||||||
with respect to the previous element.
|
The idea is that the original array is the sum array of the
|
||||||
For example, the array
|
inverse sum array.
|
||||||
|
For example, consider the following array:
|
||||||
|
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.7]
|
\begin{tikzpicture}[scale=0.7]
|
||||||
|
@ -1344,7 +1346,8 @@ For example, the array
|
||||||
\node at (7.5,1.4) {$8$};
|
\node at (7.5,1.4) {$8$};
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
becomes as follows:
|
|
||||||
|
The inverse sum array for the above array is as follows:
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.7]
|
\begin{tikzpicture}[scale=0.7]
|
||||||
\draw (0,0) grid (8,1);
|
\draw (0,0) grid (8,1);
|
||||||
|
@ -1371,15 +1374,13 @@ becomes as follows:
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
|
|
||||||
The original array is the sum array of the new array.
|
|
||||||
Thus, each element in the original array equals
|
|
||||||
a sum of values in the new array.
|
|
||||||
For example, the value 5 at position 6 in the original array
|
For example, the value 5 at position 6 in the original array
|
||||||
corresponds to the sum $3-2+4=5$.
|
corresponds to the sum $3-2+4=5$.
|
||||||
|
|
||||||
The benefit in using the new array is
|
The advantage of the inverse sum array is
|
||||||
that we can update a range by changing just
|
that we can update a range
|
||||||
two elements in the array.
|
in the original array by changing just
|
||||||
|
two elements in the inverse sum array.
|
||||||
For example, if we want to
|
For example, if we want to
|
||||||
increase the elements in the range $2 \ldots 5$ by 5,
|
increase the elements in the range $2 \ldots 5$ by 5,
|
||||||
it suffices to increase the value at position 2 by 5
|
it suffices to increase the value at position 2 by 5
|
||||||
|
|
Loading…
Reference in New Issue