Editorial for K-tacne sekvence zagrada
Submitting an official solution before solving the problem yourself is a bannable offence.
K-tačne sekvence zagrada
Autor: Nikola Pešić Tekst i test primeri: Nikola Pešić Analiza rešenja: Nikola Pešić Tester: Ivan Stošić
Analiza
Ideja za dinamičko programiranje
Za rešavanje problema koristićemo dinamičko programiranje.
Neka prstavlja stanje gde označava broj zagrada koje još moramo da postavimo, označava trenutnu prefiksnu sumu postavljenih zagrada (ako uzmemo da je (
jednako 1 a )
jednako -1) i predstavlja broj zagrada koje možemo još da obrišemo.
Za prelaze imamo 2 opcije: Postavi (
kao sledeću zagradu ili postavi )
kao sledeću zagradu.
Ako postavljamo (
, iz stanja ćemo preći u stanje .
Ako postavljamo )
imamo 2 opcije:
- , iz stanja ćemo preći u stanje .
- , iz stanja ćemo preći u stanje .
Na početku treba da inicijalizujemo na ako je , a na u ostalim slučajevima. Takođe treba paziti na , vrednosti u -u veoma brzo mogu da premaše long\(, tako da je potrebno ograničiti ih da ne mogu da budu veće od \)2^{61}\( ili neke slične vrednosti. \)2^{61}2\cdot 2^{61}long, dok je veće od najveće moguće vrednosti za . Uz pomoć ovog -a, možemo da odgovorimo na upite. Za upit ćemo krenuti od stanja i nakon toga ćemo raditi sledeće dok ne postane :
- Ako je , preći ćemo u to stanje i na odgovor dodati
(
. - U suprotnom ćemo od oduzeti , na odgovor dodati
)
i preći u stanje ako je ili ako je .
Sa ovim rešenjem se moglo dobiti bodova, dok se sa malo modifikovanim rešenjem (za slučaj kada je ), moglo dobiti još bodova. Glavni problem ovog rešenja je memorija, tako da ćemo se u sledećem delu fokusirati na smanjenje memorije. Biće opisana 3 rešenja, u redosledu od najlakšeg do najtežeg za implementaciju. Prvo rešenje je alternativno rešenje za problem, drugo koristi ideju koju je Tadija Šebez koristio da reši problem, i treće je zamišljeno rešenje.
U sva 3 rešenja se koristi klasična memorijska optimizacija gde se čuvaju samo poslednja 2 reda. Ovo je poprilično lako uraditi kada se računa u redosledu rastućih dužina, međutim, za odgovaranje na upite nama trebaju vrednosti u redosledu opadajućih dužina.
Rešenje 1
Ovo rešenje koristi činjenicu da u našem -u ima malo vrednosti koje nisu , a manje su od . Štaviše, ima tačno takvih vrednosti. Postoje 2 slučaja kada je :
- i
Treba nam još dobar način da sačuvamo ove vrednosti. Možemo da napravimo matricu gde za sve vrednosti i čuvamo sve vrednosti (listu vrednosti) i vrednosti odgovarajućeg stanja. Međutim, kako vrednosti i mogu biti do , ova matrica će koristiti previše memorije. Da bi smanjili memoriju, možemo da primetimo da za neku vrednosti parametra , vrednost parametra će biti u intervalu za sva polja čija je vrednost u traženom intervalu. Time možemo da smanjimo matricu na dimenzije . Što se tiče, pronalaženja odgovarajuće vrednosti za iz liste, dovoljno je samo da prođemo kroz celu listu ako nam treba neka vrednost iz nje. Ovo je moguće uraditi i u ali nema potrebe kako složenost programa ostaje ista. Složenost: Vreme: , Memorija: Broj polja čija je vrednost u intervalu .
Rešenje 2
U ovom i sledećem rešenju rešavaćemo upite oflajn, tj. rešićemo ih sve jednim prolazom kroz tabelu u redosledu opadajućih dužina. Za ovo rešenje definisaćemo konstantu i u odvojenu tabelu ćemo zapamtiti svaki -ti red, tj. , , ,... Nakon toga, prolazimo kroz sve dužine u opadajućem redosledu, i za svaku dužinu ćemo da dobijemo red koji koji nam treba, tj. tako što ćemo krenuti od najbližeg zapamćenog reda, u ovom slučaju to je , i pomeriti se koraka do -tog reda. Odabir konstante je dovoljno velik da rešenje prođe memorijsko ograničenje, a dovoljno mali da prođe vremensko ograničenje. Složenost: Vreme: , Memorija: .
Rešenje 3
Ovo rešenje se svodi na memorijsku optimizaciju prve dimenzije tabele. Ako znamo sve vrednosti za dužinu i prva 2 reda za trenutnu dužinu tj. i , možemo da izračunamo sve vrednosti za dužinu . Ovo je moguće uraditi tako što konstruišemo graf svih prelaza i ako znamo neku vrednost u redu , oduzećemo tu vrednost od svih stanja (iz reda ) sa kojima je to stanje povezano, a ako imamo neko stanje u redu koje je povezano sa tačno jednim stanjem (iz reda ) za koje ne znamo vrednost, možemo da zaključimo koja je vrednost tog stanja. Kako bi ovo radilo, moramo da računamo vrednosti po modulu, moduo radi iz istih razloga kao u rešenju 1. Sad nam još treba način da kažemo da li je vrednost u nekom polju zapravo veća od modula ili ne. Za ovo ćemo definisati vrednost , polje će nam čuvati najmanje za koje je neko stanje čija je vrednost parametra odgovarajuća, postalo veće od modula. Primetimo da kad jednom postane veće od modula za neko , vrednost za svako veće i istom vrednošću parametra će takođe biti veća od modula. Ovo je sve što nam treba da rešimo problem, rešavaćemo uptite oflajn, prvo izračunamo vrednosti u predosledu rastućih dužina, popunimo tabelu i sačuvamo vrednosti za i , i odgovorimo na upite za koje je rešenje "Ne postoji". Nakon toga ćemo da izračunamo vrednosti u redosledu opadajućih dužina i odgovorimo na ostale upite. Složenost: Vreme: , Memorija: .
Comments