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