Chapter 27 first version
This commit is contained in:
parent
986de0d086
commit
e422e2652f
427
luku27.tex
427
luku27.tex
|
@ -1,37 +1,37 @@
|
||||||
\chapter{Square root algorithms}
|
\chapter{Square root algorithms}
|
||||||
|
|
||||||
\index{nelizjuurialgoritmi@neliöjuurialgoritmi}
|
\index{square root algorithm}
|
||||||
|
|
||||||
\key{Neliöjuurialgoritmi} on algoritmi,
|
A \key{square root algorithm} is an algorithm
|
||||||
jonka aikavaativuudessa esiintyy neliöjuuri.
|
that has a square root in its time complexity.
|
||||||
Neliöjuurta voi ajatella ''köyhän miehen logaritmina'':
|
A square root can be seen as a ''poor man's logarithm'':
|
||||||
aikavaativuus $O(\sqrt n)$ on parempi kuin $O(n)$
|
the complexity $O(\sqrt n)$ is better than $O(n)$
|
||||||
mutta huonompi kuin $O(\log n)$.
|
but worse than $O(\log n)$.
|
||||||
Toisaalta neliöjuurialgoritmit toimivat
|
Still, many square root algorithms are fast in practice
|
||||||
käytännössä hyvin ja niiden vakiokertoimet ovat pieniä.
|
and have small constant factors.
|
||||||
|
|
||||||
Tarkastellaan esimerkkinä tuttua ongelmaa,
|
As an example, let's consider the problem of
|
||||||
jossa toteutettavana on summakysely taulukkoon.
|
handling sum queries in an array.
|
||||||
Halutut operaatiot ovat:
|
The required operations are:
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item muuta kohdassa $x$ olevaa lukua
|
\item change the value at index $x$
|
||||||
\item laske välin $[a,b]$ lukujen summa
|
\item calculate the sum in the range $[a,b]$
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
Olemme aiemmin ratkaisseet tehtävän
|
We have previously solved the problem using
|
||||||
binääri-indeksipuun ja segmenttipuun avulla,
|
a binary indexed tree and a segment tree,
|
||||||
jolloin kummankin operaation aikavaativuus on $O(\log n)$.
|
that support both operations in $O(\log n)$ time.
|
||||||
Nyt ratkaisemme tehtävän toisella
|
However, now we will solve the problem
|
||||||
tavalla neliöjuurirakennetta käyttäen,
|
in another way using a square root structure
|
||||||
jolloin summan laskenta vie aikaa $O(\sqrt n)$
|
so that we can calculate sums in $O(\sqrt n)$ time
|
||||||
ja luvun muuttaminen vie aikaa $O(1)$.
|
and modify values in $O(1)$ time.
|
||||||
|
|
||||||
Ideana on jakaa taulukko $\sqrt n$-kokoisiin
|
The idea is to divide the array into segments
|
||||||
väleihin niin, että jokaiseen väliin
|
of size $\sqrt n$ so that each segment contains
|
||||||
tallennetaan lukujen summa välillä.
|
the sum of values inside the segment.
|
||||||
Seuraavassa on esimerkki taulukosta ja
|
The following example shows an array and the
|
||||||
sitä vastaavista $\sqrt n$-väleistä:
|
corresponding segments:
|
||||||
|
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.7]
|
\begin{tikzpicture}[scale=0.7]
|
||||||
|
@ -67,9 +67,9 @@ sitä vastaavista $\sqrt n$-väleistä:
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
|
|
||||||
Kun taulukon luku muuttuu,
|
When a value in the array changes,
|
||||||
tämän yhteydessä täytyy laskea uusi summa
|
we have to calculate the sum in the corresponding
|
||||||
vastaavalle $\sqrt n$-välille:
|
segment again:
|
||||||
|
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.7]
|
\begin{tikzpicture}[scale=0.7]
|
||||||
|
@ -107,9 +107,9 @@ vastaavalle $\sqrt n$-välille:
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
|
|
||||||
Välin summan laskeminen taas tapahtuu muodostamalla
|
Any sum in the array can be calculated as a combination
|
||||||
summa reunoissa olevista yksittäisistä luvuista
|
of single values in the array and the sums of the
|
||||||
sekä keskellä olevista $\sqrt n$-väleistä:
|
segments between them:
|
||||||
|
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.7]
|
\begin{tikzpicture}[scale=0.7]
|
||||||
|
@ -152,207 +152,213 @@ sekä keskellä olevista $\sqrt n$-väleistä:
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
|
|
||||||
Luvun muuttamisen aikavaativuus on
|
We can change a value in $O(1)$ time,
|
||||||
$O(1)$, koska riittää muuttaa yhden $\sqrt n$-välin summaa.
|
because we only have to change the sum of a single segment.
|
||||||
Välin summa taas lasketaan kolmessa osassa:
|
A sum in a range consists of three parts:
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item vasemmassa reunassa on $O(\sqrt n)$ yksittäistä lukua
|
\item first, there are $O(\sqrt n)$ single values
|
||||||
\item keskellä on $O(\sqrt n)$ peräkkäistä $\sqrt n$-väliä
|
\item then, there are $O(\sqrt n)$ consecutive segments
|
||||||
\item oikeassa reunassa on $O(\sqrt n)$ yksittäistä lukua
|
\item finally, there are $O(\sqrt n)$ single values
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
Jokaisen osan summan laskeminen vie aikaa $O(\sqrt n)$,
|
Calculating each sum takes $O(\sqrt n)$ time,
|
||||||
joten summan laskemisen aikavaativuus on yhteensä $O(\sqrt n)$.
|
so the total complexity for calculating the sum
|
||||||
|
of values in any range is $O(\sqrt n)$.
|
||||||
|
|
||||||
Neliöjuurialgoritmeissa parametri $\sqrt n$
|
The reason why we use the parameter $\sqrt n$ is that
|
||||||
johtuu siitä, että se saattaa kaksi asiaa tasapainoon:
|
it balances two things:
|
||||||
esimerkiksi $n$ alkion taulukko jakautuu
|
for example, an array of $n$ elements is divided
|
||||||
$\sqrt n$ osaan, joista jokaisessa on $\sqrt n$ alkiota.
|
into $\sqrt n$ segments, each of which contains
|
||||||
Käytännössä algoritmeissa
|
$\sqrt n$ elements.
|
||||||
ei ole kuitenkaan pakko käyttää
|
In practice, it is not needed to use exactly
|
||||||
tarkalleen parametria $\sqrt n$,
|
the parameter $\sqrt n$ in algorithms, but it may be better to
|
||||||
vaan voi olla parempi valita toiseksi
|
use parameters $k$ and $n/k$ where $k$ is
|
||||||
parametriksi $k$ ja toiseksi $n/k$,
|
larger or smaller than $\sqrt n$.
|
||||||
missä $k$ on pienempi tai suurempi kuin $\sqrt n$.
|
|
||||||
|
|
||||||
Paras parametri selviää usein kokeilemalla
|
The best parameter depends on the problem
|
||||||
ja riippuu tehtävästä ja syötteestä.
|
and input.
|
||||||
Esimerkiksi jos taulukkoa käsittelevä algoritmi
|
For example, if an algorithm often goes through
|
||||||
käy usein läpi välit mutta harvoin välin sisällä
|
segments but rarely iterates the elements inside
|
||||||
olevia alkioita, taulukko voi olla järkevää
|
the segments, it may be good to divide the array into
|
||||||
jakaa $k < \sqrt n$ väliin,
|
$k < \sqrt n$ segments, each of which contains $n/k > \sqrt n$
|
||||||
joista jokaisella on $n/k > \sqrt n$ alkiota.
|
elements.
|
||||||
|
|
||||||
\section{Eräkäsittely}
|
\section{Batch processing}
|
||||||
|
|
||||||
\index{erxkxsittely@eräkäsittely}
|
\index{batch processing}
|
||||||
|
|
||||||
\key{Eräkäsittelyssä} algoritmin suorittamat
|
In \key{batch processing}, the operations in the
|
||||||
operaatiot jaetaan eriin,
|
algorithm are divided into batches,
|
||||||
jotka käsitellään omina kokonaisuuksina.
|
and each batch will be processed separately.
|
||||||
Erien välissä tehdään yksittäinen työläs toimenpide,
|
Between the batches some precalculation is done
|
||||||
joka auttaa tulevien operaatioiden käsittelyä.
|
to process the future operations more efficiently.
|
||||||
|
|
||||||
Neliöjuurialgoritmi syntyy, kun $n$ operaatiota
|
In a square root algorithm, $n$ operations are
|
||||||
jaetaan $O(\sqrt n)$-kokoisiin eriin,
|
divided into batches of size $O(\sqrt n)$,
|
||||||
jolloin sekä eriä että operaatioita kunkin erän
|
and the number of both batches and operations in each
|
||||||
sisällä on $O(\sqrt n)$.
|
batch is $O(\sqrt n)$.
|
||||||
Tämä tasapainottaa sitä, miten usein erien välinen
|
This balances the precalculation time between
|
||||||
työläs toimenpide tapahtuu sekä miten paljon työtä
|
the batches and the time needed for processing
|
||||||
erän sisällä täytyy tehdä.
|
the batches.
|
||||||
|
|
||||||
Tarkastellaan esimerkkinä tehtävää, jossa
|
As an example, let's consider a problem
|
||||||
ruudukossa on $k \times k$ ruutua,
|
where a grid of size $k \times k$
|
||||||
jotka ovat aluksi valkoisia.
|
initially consists of white squares.
|
||||||
Tehtävänä on suorittaa ruudukkoon
|
Our task is to perform $n$ operations,
|
||||||
$n$ operaatiota,
|
each of which is one of the following:
|
||||||
joista jokainen on jompikumpi seuraavista:
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item
|
\item
|
||||||
väritä ruutu $(y,x)$ mustaksi
|
paint square $(y,x)$ black
|
||||||
\item
|
\item
|
||||||
etsi ruudusta $(y,x)$ lähin
|
find the nearest black square to
|
||||||
musta ruutu, kun
|
square $(y,x)$ where the distance
|
||||||
ruutujen $(y_1,x_1)$ ja $(y_2,x_2)$
|
between squares $(y_1,x_1)$ and $(y_2,x_2)$
|
||||||
etäisyys on $|y_1-y_2|+|x_1-x_2|$
|
is $|y_1-y_2|+|x_1-x_2|$
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
Ratkaisuna on jakaa operaatiot $O(\sqrt n)$ erään,
|
The solution is to divide the operations into
|
||||||
joista jokaisessa on $O(\sqrt n)$ operaatiota.
|
$O(\sqrt n)$ batches, each of which consists
|
||||||
Kunkin erän alussa jokaiseen ruudukon ruutuun
|
of $O(\sqrt n)$ operations.
|
||||||
lasketaan pienin etäisyys mustaan ruutuun.
|
At the beginning of each batch,
|
||||||
Tämä onnistuu ajassa $O(k^2)$ leveyshaun avulla.
|
we calculate for each square in the grid
|
||||||
|
the smallest distance to a black square.
|
||||||
|
This can be done in $O(k^2)$ time using breadth-first search.
|
||||||
|
|
||||||
Kunkin erän käsittelyssä pidetään yllä listaa ruuduista,
|
When processing a batch, we maintain a list of squares
|
||||||
jotka on muutettu mustaksi tässä erässä.
|
that have been painted black in the current batch.
|
||||||
Nyt etäisyys ruudusta lähimpään mustaan ruutuun
|
Now, the distance from a square to the nearest black
|
||||||
on joko erän alussa laskettu etäisyys tai sitten
|
square is either the precalculated distance or the distance
|
||||||
etäisyys johonkin listassa olevaan tämän erän aikana mustaksi
|
to a square that has been painted black in the current batch.
|
||||||
muutettuun ruutuun.
|
|
||||||
|
|
||||||
Algoritmi vie aikaa $O((k^2+n) \sqrt n)$,
|
The algorithm works in
|
||||||
koska erien välissä tehdään $O(\sqrt n)$ kertaa
|
$O((k^2+n) \sqrt n)$ time.
|
||||||
$O(k^2)$-aikainen läpikäynti, ja
|
First, between the batches,
|
||||||
erissä käsitellään yhteensä $O(n)$ solmua,
|
there are $O(\sqrt n)$ searches that each take
|
||||||
joista jokaisen kohdalla käydään läpi
|
$O(k^2)$ time.
|
||||||
$O(\sqrt n)$ solmua listasta.
|
Second, the total number of processed
|
||||||
|
squares is $O(n)$, and at each square,
|
||||||
|
we go through a list of $O(\sqrt n)$ squares
|
||||||
|
in a batch.
|
||||||
|
|
||||||
Jos algoritmi tekisi leveyshaun jokaiselle operaatiolle,
|
If the algorithm would perform a breadth-first search
|
||||||
aikavaativuus olisi $O(k^2 n)$.
|
at each operation, the complexity would be
|
||||||
Jos taas algoritmi kävisi kaikki muutetut ruudut läpi
|
$O(k^2 n)$.
|
||||||
jokaisen operaation kohdalla,
|
And if the algorithm would go through all painted
|
||||||
aikavaativuus olisi $O(n^2)$.
|
squares at each operation,
|
||||||
Neliöjuurialgoritmi yhdistää nämä aikavaativuudet
|
the complexity would be $O(n^2)$.
|
||||||
ja muuttaa kertoimen $n$ kertoimeksi $\sqrt n$.
|
The square root algorithm combines these complexities,
|
||||||
|
and turns the factor $n$ into $\sqrt n$.
|
||||||
|
|
||||||
\section{Tapauskäsittely}
|
\section{Case processing}
|
||||||
|
|
||||||
\index{tapauskxsittely@tapauskäsittely}
|
\index{case processing}
|
||||||
|
|
||||||
\key{Tapauskäsittelyssä} algoritmissa on useita
|
In \key{case processing}, an algorithm has
|
||||||
toimintatapoja, jotka aktivoituvat syötteen
|
specialized subalgorithms for different cases that
|
||||||
ominaisuuksista riippuen.
|
may appear during the algorithm.
|
||||||
Tyypillisesti yksi algoritmin osa on tehokas
|
Typically, one part is efficient for
|
||||||
pienellä parametrilla
|
small parameters, and another part is efficient
|
||||||
ja toinen osa on tehokas suurella parametrilla,
|
for large parameters, and the turning point is
|
||||||
ja sopiva jakokohta kulkee suunnilleen arvon $\sqrt n$ kohdalla.
|
about $\sqrt n$.
|
||||||
|
|
||||||
Tarkastellaan esimerkkinä tehtävää, jossa
|
As an example, let's consider a problem where
|
||||||
puussa on $n$ solmua, joista jokaisella on tietty väri.
|
we are given a tree that contains $n$ nodes,
|
||||||
Tavoitteena on etsiä puusta kaksi solmua,
|
each with some color. Our task is to find two nodes
|
||||||
jotka ovat samanvärisiä ja mahdollisimman
|
that have the same color and the distance
|
||||||
kaukana toisistaan.
|
between them is as large as possible.
|
||||||
|
|
||||||
Tehtävän voi ratkaista
|
The problem can be solved by going through all
|
||||||
käymällä läpi värit yksi kerrallaan ja
|
colors one after another, and for each color,
|
||||||
etsimällä kullekin värille kaksi solmua, jotka ovat
|
finding two nodes of that color whose distance is
|
||||||
mahdollisimman kaukana toisistaan.
|
maximum.
|
||||||
Tietyllä värillä algoritmin toiminta riippuu siitä,
|
For a fixed color, a subalgorithm will be used
|
||||||
montako kyseisen väristä solmua puussa on.
|
that depends on the number of nodes of that color.
|
||||||
Oletetaan nyt, että käsittelyssä on väri $x$
|
Let's assume that the current color is $x$
|
||||||
ja puussa on $c$ solmua, joiden väri on $x$.
|
and there are $c$ nodes whose color is $x$.
|
||||||
Tapaukset ovat seuraavat:
|
There are two cases:
|
||||||
|
|
||||||
\subsubsection*{Tapaus 1: $c \le \sqrt n$}
|
\subsubsection*{Case 1: $c \le \sqrt n$}
|
||||||
|
|
||||||
Jos $x$-värisiä solmuja on vähän,
|
If the number of nodes is small,
|
||||||
käydään läpi kaikki $x$-väristen solmujen parit
|
we go through all pairs of nodes whose
|
||||||
ja valitaan pari, jonka etäisyys on suurin.
|
color is $x$ and select the pair that
|
||||||
Jokaisesta solmusta täytyy
|
has the maximum distance.
|
||||||
laskea etäisyys $O(\sqrt n)$ muuhun solmuun (ks. luku 18.3),
|
For each node, we have calculate the distance
|
||||||
joten kaikkien tapaukseen 1 osuvien solmujen
|
to $O(\sqrt n)$ other nodes (see 18.3),
|
||||||
käsittely vie aikaa yhteensä $O(n \sqrt n)$.
|
so the total time needed for processing all
|
||||||
|
nodes in case 1 is $O(n \sqrt n)$.
|
||||||
|
|
||||||
\subsubsection*{Tapaus 2: $c > \sqrt n$}
|
\subsubsection*{Case 2: $c > \sqrt n$}
|
||||||
|
|
||||||
Jos $x$-värisiä solmuja on paljon,
|
If the number of nodes is large,
|
||||||
käydään koko puu läpi ja
|
we traverse through the whole tree
|
||||||
lasketaan suurin etäisyys kahden
|
and calculate the maximum distance between
|
||||||
$x$-värisen solmun välillä.
|
two nodes with color $x$.
|
||||||
Läpikäynnin aikavaativuus on $O(n)$,
|
The time complexity of the tree traversal is $O(n)$,
|
||||||
ja tapaus 2 aktivoituu korkeintaan $O(\sqrt n)$
|
and this will be done at most $O(\sqrt n)$ times,
|
||||||
värille, joten tapauksen 2 solmut
|
so the total time needed for case 2 is
|
||||||
tuottavat aikavaativuuden $O(n \sqrt n)$.\\\\
|
$O(n \sqrt n)$.\\\\
|
||||||
\noindent
|
\noindent
|
||||||
Algoritmin kokonaisaikavaativuus on $O(n \sqrt n)$,
|
The time complexity of the algorithm is $O(n \sqrt n)$,
|
||||||
koska sekä tapaus 1 että tapaus 2 vievät aikaa
|
because both case 1 and case 2 take $O(n \sqrt n)$ time.
|
||||||
yhteensä $O(n \sqrt n)$.
|
|
||||||
|
|
||||||
\section{Mo'n algoritmi}
|
\section{Mo's algorithm}
|
||||||
|
|
||||||
\index{Mo'n algoritmi}
|
\index{Mo's algorithm}
|
||||||
|
|
||||||
\key{Mo'n algoritmi} soveltuu tehtäviin,
|
\key{Mo's algorithm} can be used in many problems
|
||||||
joissa taulukkoon tehdään välikyselyitä ja
|
where we are asked to process range queries in
|
||||||
taulukon sisältö kaikissa kyselyissä on sama.
|
a \emph{static} array.
|
||||||
Algoritmi järjestää
|
The algorithm handles the queries in a special order
|
||||||
kyselyt uudestaan niin,
|
so that it is efficient to process them.
|
||||||
että niiden käsittely on tehokasta.
|
|
||||||
|
|
||||||
Algoritmi pitää yllä taulukon väliä,
|
The algorithm maintains a range in the array,
|
||||||
jolle on laskettu kyselyn vastaus.
|
and the answer for a query for that range.
|
||||||
Kyselystä toiseen siirryttäessä algoritmi
|
When moving from a range to another range,
|
||||||
muuttaa väliä askel kerrallaan niin,
|
the algorithm modifies the range step by step
|
||||||
että vastaus uuteen kyselyyn saadaan laskettua.
|
so that the answer for the next range can be
|
||||||
Algoritmin aikavaativuus on $O(n \sqrt n f(n))$,
|
calculated.
|
||||||
kun kyselyitä on $n$ ja
|
The time complexity of the algorithm is
|
||||||
yksi välin muutosaskel vie aikaa $f(n)$.
|
$O(n \sqrt n f(n))$ when there are $n$ queries
|
||||||
|
and each step takes $f(n)$ time.
|
||||||
|
|
||||||
Algoritmin toiminta perustuu järjestykseen,
|
The algorithm processes the queries in a special
|
||||||
jossa kyselyt käsitellään.
|
order which makes the algorithm efficient.
|
||||||
Kun kyselyjen välit ovat muotoa $[a,b]$,
|
When the queries correspond to ranges of the form $[a,b]$,
|
||||||
algoritmi järjestää ne ensisijaisesti arvon
|
they are primarily sorted according to
|
||||||
$\lfloor a/\sqrt n \rfloor$ mukaan ja toissijaisesti arvon $b$ mukaan.
|
the value $\lfloor a/\sqrt n \rfloor$,
|
||||||
Algoritmi suorittaa siis peräkkäin kaikki kyselyt,
|
and secondarily according to the value $b$.
|
||||||
joiden alkukohta on tietyllä $\sqrt n$-välillä.
|
Hence, all queries whose starting index
|
||||||
|
is in a fixed segment
|
||||||
|
are processed after each other.
|
||||||
|
|
||||||
Osoittautuu, että tämän järjestyksen ansiosta
|
It turns out that using this order, the algorithm
|
||||||
algoritmi tekee yhteensä vain $O(n \sqrt n)$ muutosaskelta.
|
only performs $O(n \sqrt n)$ steps.
|
||||||
Tämä johtuu siitä, että välin vasen reuna liikkuu
|
The reason for this is that the left border of
|
||||||
$n$ kertaa $O(\sqrt n)$ askelta,
|
the range moves $n$ times $O(\sqrt n)$ steps,
|
||||||
kun taas välin oikea reuna liikkuu $\sqrt n$
|
and the right border of the range moves
|
||||||
kertaa $O(n)$ askelta. Molemmat reunat liikkuvat
|
$\sqrt n$ times $O(n)$ steps. Thus, both the
|
||||||
siis yhteensä $O(n \sqrt n)$ askelta.
|
borders move a total of $O(n \sqrt n)$ steps.
|
||||||
|
|
||||||
\subsubsection*{Esimerkki}
|
\subsubsection*{Example}
|
||||||
|
|
||||||
Tarkastellaan esimerkkinä tehtävää,
|
As an example, let's consider a problem
|
||||||
jossa annettuna on joukko välejä taulukossa
|
where we are given a set of ranges in an array,
|
||||||
ja tehtävänä on selvittää kullekin välille,
|
and our task is to calculate for each range
|
||||||
montako eri lukua taulukossa on kyseisellä välillä.
|
the number of distinct elements in the range.
|
||||||
|
|
||||||
Mo'n algoritmissa kyselyt järjestetään aina samalla
|
In Mo's algorithm, the queries are always sorted
|
||||||
tavalla, ja tehtävästä riippuva osa on,
|
in the same way, but it depends on the problem
|
||||||
miten kyselyn vastausta pidetään yllä.
|
how the answer for queries is maintained.
|
||||||
Tässä tehtävässä luonteva tapa on
|
In this problem, we can maintain an array
|
||||||
pitää muistissa kyselyn vastausta sekä
|
\texttt{c} where $\texttt{c}[x]$
|
||||||
taulukkoa \texttt{c}, jossa $\texttt{c}[x]$
|
indicates how many times an element $x$
|
||||||
on alkion $x$ lukumäärä aktiivisella välillä.
|
occurs in the active range.
|
||||||
|
|
||||||
Kyselystä toiseen siirryttäessä taulukon aktiivinen
|
|
||||||
väli muuttuu. Esimerkiksi jos nykyinen kysely koskee väliä
|
|
||||||
|
|
||||||
|
When we move from a query to another query,
|
||||||
|
the active range changes.
|
||||||
|
For example, if the current range is
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.7]
|
\begin{tikzpicture}[scale=0.7]
|
||||||
\fill[color=lightgray] (1,0) rectangle (5,1);
|
\fill[color=lightgray] (1,0) rectangle (5,1);
|
||||||
|
@ -368,7 +374,7 @@ väli muuttuu. Esimerkiksi jos nykyinen kysely koskee väliä
|
||||||
\node at (8.5, 0.5) {4};
|
\node at (8.5, 0.5) {4};
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
ja seuraava kysely koskee väliä
|
and the next range is
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.7]
|
\begin{tikzpicture}[scale=0.7]
|
||||||
\fill[color=lightgray] (2,0) rectangle (7,1);
|
\fill[color=lightgray] (2,0) rectangle (7,1);
|
||||||
|
@ -384,22 +390,25 @@ ja seuraava kysely koskee väliä
|
||||||
\node at (8.5, 0.5) {4};
|
\node at (8.5, 0.5) {4};
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
niin tapahtuu kolme muutosaskelta:
|
there will be three steps:
|
||||||
välin vasen reuna siirtyy askeleen oikealle
|
the left border moves one step to the left,
|
||||||
ja välin oikea reuna siirtyy kaksi askelta oikealle.
|
and the right border moves two steps to the right.
|
||||||
|
|
||||||
Jokaisen muutosaskeleen jälkeen täytyy
|
After each step, we should update the
|
||||||
päivittää taulukkoa \texttt{c}.
|
array \texttt{c}.
|
||||||
Jos väliin tulee alkio $x$,
|
If an element $x$ is added to the range,
|
||||||
arvo $\texttt{c}[x]$ kasvaa 1:llä,
|
the value
|
||||||
ja jos välistä poistuu alkio $x$,
|
$\texttt{c}[x]$ increases by one,
|
||||||
arvo $\texttt{c}[x]$ vähenee 1:llä.
|
and if a value $x$ is removed from the range,
|
||||||
Jos lisäyksen jälkeen $\texttt{c}[x]=1$,
|
the value $\texttt{c}[x]$ decreases by one.
|
||||||
kyselyn vastaus kasvaa 1:llä,
|
If after an insertion
|
||||||
ja jos poiston jälkeen $\texttt{c}[x]=0$,
|
$\texttt{c}[x]=1$,
|
||||||
kyselyn vastaus vähenee 1:llä.
|
the answer for the query increases by one,
|
||||||
|
and if after a removel $\texttt{c}[x]=0$,
|
||||||
|
the answer for the query decreases by one.
|
||||||
|
|
||||||
Tässä tapauksessa muutosaskeleen aikavaativuus on $O(1)$,
|
In this problem, the time needed to perform
|
||||||
joten algoritmin kokonaisaikavaativuus on $O(n \sqrt n)$.
|
each step is $O(1)$, so the total time complexity
|
||||||
|
of the algorithm is $O(n \sqrt n)$.
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue