Improve language

This commit is contained in:
Antti H S Laaksonen 2017-05-13 00:12:32 +03:00
parent 41cc186beb
commit 6c6d857d35
1 changed files with 135 additions and 111 deletions

View File

@ -9,7 +9,7 @@ the complexity $O(\sqrt n)$ is better than $O(n)$
but worse than $O(\log n)$. but worse than $O(\log n)$.
In any case, many square root algorithms are fast and usable in practice. In any case, many square root algorithms are fast and usable in practice.
As an example, let us consider the problem of As an example, consider the problem of
creating a data structure that supports creating a data structure that supports
two operations on an array: two operations on an array:
modifying an element at a given position modifying an element at a given position
@ -108,10 +108,8 @@ the sum of the corresponding block change:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
Calculating the sum of elements in a range is Then, to calculate the sum of elements in a range,
a bit more difficult. we divide the range into three parts such that
It turns out that we can always divide
the range into three parts such that
the sum consists of values of single elements the sum consists of values of single elements
and sums of blocks between them: and sums of blocks between them:
@ -158,14 +156,15 @@ and sums of blocks between them:
Since the number of single elements is $O(\sqrt n)$ Since the number of single elements is $O(\sqrt n)$
and the number of blocks is also $O(\sqrt n)$, and the number of blocks is also $O(\sqrt n)$,
the time complexity of the sum query is $O(\sqrt n)$. the sum query takes $O(\sqrt n)$ time.
In this case, the parameter $\sqrt n$ balances two things: The purpose of the block size $\sqrt n$ is
that it \emph{balances} two things:
the array is divided into $\sqrt n$ blocks, the array is divided into $\sqrt n$ blocks,
each of which contains $\sqrt n$ elements. each of which contains $\sqrt n$ elements.
In practice, it is not needed to use the In practice, it is not necessary to use the
exact value of $\sqrt n$ as a parameter, but it may be better to exact value of $\sqrt n$ as a parameter,
use parameters $k$ and $n/k$ where $k$ is and instead we may use parameters $k$ and $n/k$ where $k$ is
different from $\sqrt n$. different from $\sqrt n$.
The optimal parameter depends on the problem and input. The optimal parameter depends on the problem and input.
For example, if an algorithm often goes For example, if an algorithm often goes
@ -180,9 +179,10 @@ elements.
In this section we discuss two square root algorithms In this section we discuss two square root algorithms
that are based on combining two algorithms into one algorithm. that are based on combining two algorithms into one algorithm.
In both cases, we could use either of the algorithms In both cases, we could use either of the algorithms
alone and solve the problem in $O(n^2)$ time. without the other
and solve the problem in $O(n^2)$ time.
However, by combining the algorithms, the running However, by combining the algorithms, the running
time becomes $O(n \sqrt n)$. time is only $O(n \sqrt n)$.
\subsubsection{Case processing} \subsubsection{Case processing}
@ -218,9 +218,11 @@ For example, consider the following grid:
\end{center} \end{center}
In this case, the minimum distance is 2 between the two 'E' letters. In this case, the minimum distance is 2 between the two 'E' letters.
Let us consider the problem of calculating the minimum distance We can solve the problem by considering each letter separately.
Using this approach, the new problem is to calculate
the minimum distance
between two cells with a \emph{fixed} letter $c$. between two cells with a \emph{fixed} letter $c$.
There are two algorithms for this: We focus on two algorithms for this:
\emph{Algorithm 1:} Go through all pairs of cells with letter $c$, \emph{Algorithm 1:} Go through all pairs of cells with letter $c$,
and calculate the minimum distance between such cells. and calculate the minimum distance between such cells.
@ -230,13 +232,14 @@ This will take $O(k^2)$ time where $k$ is the number of cells with letter $c$.
starts at each cell with letter $c$. The minimum distance between starts at each cell with letter $c$. The minimum distance between
two cells with letter $c$ will be calculated in $O(n)$ time. two cells with letter $c$ will be calculated in $O(n)$ time.
Now we can go through all letters that appear in the grid One way to solve the problem is to choose either of the
and use either of the above algorithms. algorithms and use it for all letters.
If we always used Algorithm 1, the running time would be $O(n^2)$, If we use Algorithm 1, the running time is $O(n^2)$,
because all cells may have the same letters and $k=n$. because all cells may contain the same letter,
Also if we always used Algorithm 2, the running time would be $O(n^2)$, and in this case $k=n$.
because all cells may have different letters and there would Also if we use Algorithm 2, the running time is $O(n^2)$,
be $n$ searches. because all cells may have different letters,
and in this case $n$ searches are needed.
However, we can \emph{combine} the two algorithms and However, we can \emph{combine} the two algorithms and
use different algorithms for different letters use different algorithms for different letters
@ -258,12 +261,12 @@ so processing those letters also takes $O(n \sqrt n)$ time.
\subsubsection{Batch processing} \subsubsection{Batch processing}
Consider again a two-dimensional grid that contains $n$ cells. Our next problem also deals with
a two-dimensional grid that contains $n$ cells.
Initially, each cell except one is white. Initially, each cell except one is white.
We perform $n-1$ operations, each of which is given a white cell. We perform $n-1$ operations, each of which first
Each operation fist calculates the minimum distance calculates the minimum distance from a given white cell
between the white cell and any black cell, and to a black cell, and then paints the white cell black.
then paints the white cell black.
For example, consider the following operation: For example, consider the following operation:
@ -277,48 +280,58 @@ For example, consider the following operation:
\end{tikzpicture} \end{tikzpicture}
\end{center} \end{center}
There are three black cells and the cell marked with * First, we calculate the minimum distance
will be painted black next. from the white cell marked with * to a black cell.
Before painting the cell, the minimum distance The minimum distance is 2, because we can move
to a black cell is calculated. to steps left to a black cell.
In this case the minimum distance is 2 Then, we paint the white cell black:
to the right cell.
There are two algorithms for solving the problem: \begin{center}
\begin{tikzpicture}[scale=0.7]
\fill[color=black] (1,1) rectangle (2,2);
\fill[color=black] (3,1) rectangle (4,2);
\fill[color=black] (0,3) rectangle (1,4);
\fill[color=black] (2,3) rectangle (3,4);
\draw (0,0) grid (4,4);
\end{tikzpicture}
\end{center}
\emph{Algorithm 1:} After each operation, use breadth-first search Consider the following two algorithms:
to calculate for each white cell the distance to the nearest black cell.
Each search takes $O(n)$ time, so the total running time is $O(n^2)$. \emph{Algorithm 1:} Use breadth-first search
to calculate
for each white cell the distance to the nearest black cell.
This takes $O(n)$ time, and after the search,
we can find the minimum distance from any white cell
to a black cell in $O(1)$ time.
\emph{Algorithm 2:} Maintain a list of cells that have been \emph{Algorithm 2:} Maintain a list of cells that have been
painted black, go through this list at each operation painted black, go through this list at each operation
and then add a new cell to the list. and then add a new cell to the list.
The size of the list is $O(n)$, so the algorithm An operation takes $O(k)$ time where $k$ is the length of the list.
takes $O(n^2)$ time.
We can combine the above algorithms by We combine the above algorithms by
dividing the operations into dividing the operations into
$O(\sqrt n)$ \emph{batches}, each of which consists $O(\sqrt n)$ \emph{batches}, each of which consists
of $O(\sqrt n)$ operations. of $O(\sqrt n)$ operations.
At the beginning of each batch, At the beginning of each batch,
we calculate for each white cell the minimum distance we perform Algorithm 1.
to a black cell using breadth-first search. Then, we use Algorithm 2 to process the batches.
Then, when processing a batch, we maintain a list of cells We clear the list of Algorithm 2 between
that have been painted black in the current batch. the batches.
The list contains $O(\sqrt n)$ elements, At each operation,
because there are $O(\sqrt n)$ operations in each batch. the minimum distance to a black cell
Now, the distance between a white cell and the nearest black is either the distance calculated by Algorithm 1
cell is either the precalculated distance or the distance or the distance calculated by Algorithm 2.
to a cell that appears in the list.
The resulting algorithm works in The resulting algorithm works in
$O(n \sqrt n)$ time. $O(n \sqrt n)$ time.
First, there are $O(\sqrt n)$ breadth-first searches First, Algorithm 1 is performed $O(\sqrt n)$ times,
and each search takes $O(n)$ time. and each search works in $O(n)$ time.
Second, the total number of Second, when using Algorithm 2 in a batch,
distances calculated during the algorithm the list contains $O(\sqrt n)$ cells
is $O(n)$, and when calculating each distance, (because we clear the list between the batches)
we go through a list of $O(\sqrt n)$ squares. and each operation takes $O(\sqrt n)$ time.
\section{Integer partitions} \section{Integer partitions}
@ -326,13 +339,16 @@ Some square root algorithms are based on
the following observation: the following observation:
if a positive integer $n$ is represented as if a positive integer $n$ is represented as
a sum of positive integers, a sum of positive integers,
such a sum contains only $O(\sqrt n)$ \emph{distinct} numbers. such a sum always contains at most
The reason for this is that a sum with $O(\sqrt n)$ \emph{distinct} numbers.
the maximum amount of distinct numbers has to be of the form
\[1+2+3+ \cdots = n.\] The reason for this is that to construct
The sum of the numbers $1,2,\ldots,k$ is a sum that contains a maximum number of distinct
\[\frac{k(k+1)}{2},\] numbers, we should choose \emph{small} numbers.
so the maximum amount of distinct numbers is $k = O(\sqrt n)$. If we choose the numbers $1,2,\ldots,k$,
the resulting sum is
\[\frac{k(k+1)}{2} \le n.\]
Thus, the maximum amount of distinct numbers is $k = O(\sqrt n)$.
Next we will discuss two problems that can be solved Next we will discuss two problems that can be solved
efficiently using this observation. efficiently using this observation.
@ -374,51 +390,48 @@ The idea is to use an array that records the sums of weights
that can be formed using the groups processed so far. that can be formed using the groups processed so far.
The array contains $n$ elements: element $k$ is 1 if the sum The array contains $n$ elements: element $k$ is 1 if the sum
$k$ can be formed and 0 otherwise. $k$ can be formed and 0 otherwise.
To process a group of weights, we can easily scan the array To process a group of weights, we scan the array
from left to right and record the new sums of weights that from left to right and record the new sums of weights that
can be formed using this group and the previous groups. can be formed using this group and the previous groups.
\subsubsection{String construction} \subsubsection{String construction}
Given a string and a dictionary of words, Given a string \texttt{s} and a dictionary $D$ of strings,
consider the problem of counting the number of ways consider the problem of counting the number of ways
the string can be constructed using the dictionary words. \texttt{s} can be formed as a concatenation of strings in $D$.
For example, For example,
if the string is \texttt{ABAB} and the dictionary is if \texttt{s} is \texttt{ABAB} and $D$ is
$\{\texttt{A},\texttt{B},\texttt{AB}\}$, $\{\texttt{A},\texttt{B},\texttt{AB}\}$,
there are 4 ways: there are 4 ways:
$\texttt{A}+\texttt{B}+\texttt{A}+\texttt{B}$,
$\texttt{AB}+\texttt{A}+\texttt{B}$,
$\texttt{A}+\texttt{B}+\texttt{AB}$ and
$\texttt{AB}+\texttt{AB}$.
Assume that the length of the string is $n$ \begin{itemize}[noitemsep]
and the total length of the dictionary words is $m$. \item $\texttt{A}+\texttt{B}+\texttt{A}+\texttt{B}$
A natural way to solve the problem is to use dynamic \item $\texttt{AB}+\texttt{A}+\texttt{B}$
programming: we can define a function $f$ such that \item $\texttt{A}+\texttt{B}+\texttt{AB}$
$f(k)$ denotes the number of ways to construct a prefix \item $\texttt{AB}+\texttt{AB}$
of length $k$ of the string using the dictionary words. \end{itemize}
Using this function, $f(n)$ gives the answer to the problem.
There are several ways to calculate the values of $f$. Assume that the length of \texttt{s} is $n$
One method is to store the dictionary words and the total length of the strings in $D$ is $m$.
in a trie and go through all ways to select the We can solve the problem using dynamic programming:
last word in each prefix, which results in an $O(n^2)$ time algorithm. Let $f(k)$ denote the number of ways to construct the prefix
However, instead of using a trie, we can also use string hashing $\texttt{s}[0 \ldots k]$ using the strings in $D$.
and always go through the dictionary words and compare their Now $f(n-1)$ gives the answer to the problem,
hash values. and we can solve the problem in $O(n^2)$ time
using a trie structure.
The most straightforward implementation of this idea However, we can solve the problem more efficiently
yields an $O(nm)$ time algorithm, by using string hashing and the fact that there
because the dictionary may contain $m$ words. are at most $O(\sqrt m)$ distinct string lengths in $D$.
However, we can make the algorithm more efficient First, we construct a set $H$ that contains all
by considering the dictionary words grouped by their lengths. hash values of the strings in $D$.
Each group can be processed in constant time, Then, when calculating a value of $f(k)$,
because all hash values of dictionary words may be stored in a set. we consider each integer $p$
Since the total length of the words is $m$, such that there is a string of length $p$ in $D$,
there are at most $O(\sqrt m)$ distinct word lengths calculate the hash value of $\texttt{s}[k-p+1 \ldots k]$
and at most $O(\sqrt m)$ groups. and check if it belongs to $H$.
Thus, the running time of the algorithm is only $O(n \sqrt m)$. Since there are at most $O(\sqrt m)$ distinct word lengths,
this results in an algorithm whose running time is $O(n \sqrt m)$.
\section{Mo's algorithm} \section{Mo's algorithm}
@ -429,38 +442,49 @@ is named after Mo Tao, a Chinese competitive programmer, but
the technique has appeared earlier in the literature \cite{ken06}.} the technique has appeared earlier in the literature \cite{ken06}.}
can be used in many problems can be used in many problems
that require processing range queries in that require processing range queries in
a \emph{static} array. a \emph{static} array, i.e., the array values
Since the array is static, the queries can be do not change between the queries.
processed in any order. In each query, we are given a range $[a,b]$,
Before processing the queries, the algorithm and we should calculate a value based on the
sorts them in a special order which guarantees array elements between positions $a$ and $b$.
Since the array is static,
the queries can be processed in any order,
and Mo's algorithm
processes the queries in a special order which guarantees
that the algorithm works efficiently. that the algorithm works efficiently.
At each moment in the algorithm, there is an active Mo's algorithm maintains an \emph{active range}
range and the algorithm maintains the answer of the array, and the answer to a query
to a query related to that range. concerning the active range is known at each moment.
The algorithm processes the queries one by one, The algorithm processes the queries one by one,
and always moves the endpoints of the and always moves the endpoints of the
active range by inserting and removing elements. active range by inserting and removing elements.
The time complexity of the algorithm is The time complexity of the algorithm is
$O(n \sqrt n f(n))$ when the array contains $O(n \sqrt n f(n))$ where the array contains
$n$ elements, there are $n$ queries $n$ elements, there are $n$ queries
and each insertion and removal of an element and each insertion and removal of an element
takes $O(f(n))$ time. takes $O(f(n))$ time.
The trick in Mo's algorithm is the order The trick in Mo's algorithm is the order
in which the queries are processed: in which the queries are processed:
The array is divided into blocks of $O(\sqrt n)$ The array is divided into blocks of $k=O(\sqrt n)$
elements, and the queries are sorted primarily by elements, and a query $[a_1,b_1]$
the number of the block that contains the first element is processed before a query $[a_2,b_2]$
in the range, and secondarily by the position of the if either
last element in the range. \begin{itemize}
It turns out that using this order, the algorithm \item $\lfloor a_1/k \rfloor < \lfloor a_2/k \rfloor$ or
\item $\lfloor a_1/k \rfloor = \lfloor a_2/k \rfloor$ and $b_1 < b_2$.
\end{itemize}
Thus, all queries whose left endpoints are
in a certain block are processed one after another
sorted according to their right endpoints.
Using this order, the algorithm
only performs $O(n \sqrt n)$ operations, only performs $O(n \sqrt n)$ operations,
because the left endpoint moves because the left endpoint moves
$n$ times $O(\sqrt n)$ steps, $O(n)$ times $O(\sqrt n)$ steps,
and the right endpoint moves and the right endpoint moves
$\sqrt n$ times $O(n)$ steps. Thus, both $O(\sqrt n)$ times $O(n)$ steps. Thus, both
endpoints move a total of $O(n \sqrt n)$ steps during the algorithm. endpoints move a total of $O(n \sqrt n)$ steps during the algorithm.
\subsubsection*{Example} \subsubsection*{Example}