5 - Dodela vrednosti
Vremensko ograničenje | Memorijsko ograničenje |
---|---|
2000ms | 512MB |
Jaca je pametna maca i za vas ima veoma jednostavan zadatak. Ona će vam dati prirodne brojeve \(N\) i \(Q\), nakon čega vi treba da napravite niz \(a = [1,2,\ldots,N]\) (niz se indeksira od \(1\)) i da izvršite \(Q\) njenih naredbi. Svaka naredba ima jedan od sledeća dva oblika:
- \(1\) \(u\) \(v\) \(l\) - Za svako \(i \in \{0,1,\ldots,l-1\}\) (tim redom), izvršiti naredbu dodele \(a_{u+i} \leftarrow a_{v+i}\) (\(a_{u+i}\) dobija vrednost koju u tom trenutku ima \(a_{v+i}\))
- \(2\) \(x\) - Recite Jaci trenutnu vrednost \(a_x\)
Opis ulaza
U prvoj liniji standardnog ulaza nalaze se prirodni brojevi \(N\) - veličina niza i \(Q\) - broj upita. Narednih \(Q\) linija mogu biti oblika \(1\) \(u\) \(v\) \(l\) ili \(2\) \(x\). U prvom slučaju važi \(u,v \geq 1\) i \(u+l-1,v+l-1\leq N\), a u drugom \(1 \leq x \leq N\).
Opis izlaza
Za svaki upit tipa \(2\) u poseban red standardnog izlaza ispisati traženi broj.
Primer 1
Ulaz
Izlaz
Objašnjenje primera
Nakon prve izmene niz će izgledati ovako: \([5,2,3,4,5,6]\), u drugom upitu Jaca nam traži da joj kažemo \(a_1\), što iznosi \(5\). Nakon druge izmene (treći upit) niz će izgledati ovako: \([5,2,5,2,5,2]\). U četvrtom upitu Jaca nas pita za \(a_6\), što iznosi \(2\).
Ograničenja
- \(N \leq 1.000.000, Q \leq 100.000\)
Test primeri su podeljeni u 4 disjunktne grupe:
- U test primerima vrednim 10 poena: \(N, Q \leq 5.000\)
- U test primerima vrednim 30 poena: Svi upiti tipa \(2\) se nalaze posle svih upita tipa \(1\)
- U test primerima vrednim 30 poena: U upitima tipa \(1\) važi \(|u-v| \geq l\)
- U test primerima vrednim 30 poena: Nema dodatnih ograničenja
Autor | Tekst i test primeri | Analiza rеšenja | Testiranje |
---|---|---|---|
Ivan Stošić | Ivan Stošić | Ivan Stošić | Vladimir Milenković |
Održavajmo u svakom trenutku graf sa sledećim osobinama:
- Postoje tri vrste čvorova, "unutrašnji", "listovi" i jedan specijalan "prazan" čvor. Unutrašnji čvorovi imaju tačno dve izlazne grane, koje ćemo zvati "levom" i "desnom". Listovi nemaju izlazne grane i čuvaju jednu celobrojnu vrednost, koju ćemo zvati "labela".
- Graf je "nepromenljiv", odnosno, nije moguće izmeniti osobine postojećih čvorova. Moguće je samo dodavati nove čvorove.
- Svaki čvor čuva veličinu iz njega dostižnog dela grafa. Za listove, ova veličina iznosi \(1\). Za unutrašnje čvorove, ova veličina jednaka je zbiru veličina čvorova do kojih se stiže pomoću leve i desne grane. Za prazan čvor ova veličina je \(0\).
- Analogno definišemo dostižni niz labela za neki čvor. Za listove, to je niz od jednog elementa - njegova labela. Za unutrašnje čvorove niz se dobija konkatenacijom nizova levog i desnog čvora. Za prazan čvor je prazan niz.
Pored grafa, održavajmo i pokazivač \(R\) na čvor čiji će dostižni niz labela biti jednak trenutnoj vrednosti niza \(a\). Upite tipa \(2\) rešavamo veoma jednostavno, krećemo iz čvora \(R\) i spuštamo se levo ili desno u zavisnosti od toga kom elementu niza želimo da pristupimo, sve dok ne dođemo do lista.
Upite prvog tipa rešavamo pomoću sledećih operacija nad grafom:
seci(x, s)
, vraća dva pokazivača na čvorove, gde je prvi čvor takav da je njegov dostižni niz jednak prefiksu dostižnog niza za čvor \(x\) dužine \(s\), a dostižni niz drugog čvora je jednak ostatku dostižnog niza za čvor \(x\).spoji(x, y)
vraća čvor čiji je dostižni niz jednak konkatenaciji dostižnih nizova za čvorove \(x\) i \(y\). Ova operacija se može izvesti na dva načina o čemu će biti više reči kasnije.pomnozi(x, k)
vraća čvor čiji je dostižni niz jednak konkatenaciji \(k\) dostižnih nizova za čvor \(x\).
Naš cilj je da sve tri operacije rade brzo. Tačnije, sve tri operacije radiće u složenosti linearnoj po dubini grafa počev od datog čvora ili čvorova, zato će nama biti cilj da se ova dubina ne povećava previše u toku rada.
Slede skice mogućih realizacija ove tri operacije:
seci(x, s)
, ukoliko je \(s\) manje od veličine levog čvora od \(x\), pravimo kopiju \(y\) čvora \(x\) čiji levi čvor sečemo rekurzivno. Prvi čvor rezultata rekurzivnog poziva vratimo kao prvi čvor, dok drugi čvor rezultata rekurzivnog poziva zakačimo kao levi čvor čvora \(y\) i kao drugi čvor vratimo upravo \(y\). U suprotnom, analogno sečemo desni čvor.spoji(x, y)
, nasumično izaberemo jedan od ta dva čvora (recimo da je to čvor \(x\)), napravimo njegovu kopiju \(z\), rekurzivno spojimo desni čvor čvora \(z\) i čvor \(y\) i rezultat zakačimo kao desni čvor \(z\), zatim vratimo \(z\).pomnozi(x, k)
, kako će važiti \(k \leq n < 2^{20}\), napravimo čvorove \(y_0, y_1, \ldots, y_{19}\), gde je \(y_0\) kopija čvora \(x\), a za \(i > 0\) je \(y_i\) čvor koji se dobija "prostim" (nerekurzivnim) spajanjem čvora \(y_{i-1}\) sa samim sobom. Tačnije, čvoru \(y_i\) će i leva i desna grana pokazivati na čvor \(y_{i-1}\). Sada je jasno da je niz čvora \(y_i\) jednak konkatenaciji \(2^i\) nizova čvora \(x\). Zatim samo izaberemo stepene dvojke u binarnom zapisu broja \(k\) i ponovo prostim spajanjem napravimo rezultujući čvor, vodeći računa da spajamo od manjih ka većim stepenima.
Sada, zadatak rešavamo na sledeći način. Graf inicijalizujemo kao binarno stablo čiji listovi redom imaju labele od \(1\) do \(N\) i \(R\) postavljamo za koren tog stabla. U većini slučajeva samo sečemo delove niza za čvor \(R\) i sastavljamo ih u nekom drugom redosledu. Jedini nezgodan slučaj jeste taj kada je \(u > v\) i \(l > u-v\). Tada se jedno parče originalnog niza ciklično ponavlja određen broj puta, i tu nam je potrebna efikasna operacija pomnozi
.
Jedna moguća optimizacija jeste da, kada broj čvorova prebaci neku unapred zadatu granicu (recimo par miliona), izračunamo ceo dostižan niz iz čvora \(R\), obrišemo sve čvorove i "počnemo ispočetka" sa tim nizom.
Vremenska i memorijska složenost: \(N + Q \log N\).
05_dodela.cpp | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
|