Középiskolai Matematikai és Fizikai Lapok
Informatika rovattal
Kiadja a MATFUND Alapítvány
Már regisztráltál?
Új vendég vagy?

Az S. 111. feladat (2016. november)

S. 111. Egy vasútállomáson különböző befogadóképességű személyvagonokból állítanak össze egy szerelvényt. Egy csapat katona az éppen rendezés alatt álló vonatra szeretne felszállni, ezért figyelik, ahogy a vagonokat tologatják. Megfigyelték, hogy a rendező mozdony egyszerre mindig csak egy kocsit mozgat, azaz a fő szerelvény egy helyben áll, és ennek a végére kapcsolhatnak egy vagont, illetve néha meggondolják magukat, ekkor le is kapcsolhatnak egy kocsit a szerelvény végéről vagy az elejéről. Továbbá minden vagonra rá van írva, hogy hány utas fér el benne (egy pozitív egész szám 1 és \(\displaystyle 10^9\) között). Egy tiszt figyeli a vonat összeállítását, és minden mozgatás után szeretné tudni, hogy mekkora osztagokat hozzon létre, ha minden osztag ugyanannyi katonából áll, és úgy kell felszállniuk a vonatra, hogy minden kocsi tele legyen, és az egyes osztagok tagjai ugyanabban a kocsiban utazzanak, továbbá minél kevesebb osztagba szeretné szervezni a katonákat. Mivel az állomáson rengeteg vagon van, ezért lapunk segítségét kérte, hogy ki tudja adni a helyes parancsokat.

A standard bemenet első sorában a mozgatások \(\displaystyle N\) száma van, a következő \(\displaystyle N\) sor mindegyike egy-egy mozgatást ír le:

\(\displaystyle \bullet\) 0 x \(\displaystyle \to\) új vagont kapcsolnak a szerelvény végére, aminek a kapacitása \(\displaystyle x\);

\(\displaystyle \bullet\) 1 \(\displaystyle \to\) lekapcsolják az utolsó vagont;

\(\displaystyle \bullet\) 2 \(\displaystyle \to\) lekapcsolják az első vagont. A standard kimenet \(\displaystyle N\) sort tartalmazzon, minden mozgatás után az osztagok méretét. Amennyiben a szerelvény az egyik mozgatás után üres lenne, akkor sajnos nem lehet létrehozni semekkora csapatokat sem, ezt a 0 szám kiírásával jelezzük. A mozgatások helyesek, vagyis üres szerelvényről sohasem kapcsolnak le kocsit. A szerelvény kezdetben üres.

Pontozás: az első két tesztesetben (2 pont) csak ,,0'' és ,,1'' típusú mozgatások vannak, vagyis a vonat elejét sosem kapcsolják le.

Korlátok: \(\displaystyle 1\le N\le 10^{5}\), időkorlát 1 mp, memórialimit: 256 MB.

Magyarázat: a szerelvény az egyes műveletek után: (10); \(\displaystyle (10,6)\); \(\displaystyle (10,6,21)\); \(\displaystyle (6,21)\); (6); \(\displaystyle (6,18)\); (18); ().

Pontozás és korlátok: a programhoz mellékelt, a helyes megoldás elvét tömören, de érthetően leíró dokumentáció 1 pontot ér. A programra akkor kapható meg a további 9 pont, ha bármilyen hibátlan bemenetet képes megoldani a fenti korlátoknak megfelelően.

Beküldendő egy tömörített s111.zip állományban a program forráskódja, valamint a program rövid dokumentációja, amely a fentieken túl megadja, hogy a forrás mely fejlesztői környezetben fordítható.

(10 pont)

A beküldési határidő 2016. december 12-én LEJÁRT.


A feladat szövegét értelmezve kiderül, hogy valójában mi a feladat: minden szerelvényre meg kell adni a vagonok kapacitásának legnagyobb közös osztóját.

A legnagyobb közös osztót (lnko) az euklidészi algoritmus segítségével \(\displaystyle O(log(N))\) időben számolhatjuk (lásd a minta kódot).

Az első 2 pont megszerezhető, ha megfigyeljük, hogy \(\displaystyle lnko(a_1,...,a_{k-1},a_k) = lnko(lnko(a_1,...,a_{k-1}),a_k))\) a legnagyobb közös osztó asszociatív (csoportosítható) tulajdonsága miatt, illetve azt, hogy a vonat ebben az esetben veremként működik (hiszen csak az egyik végéhez kapcsolunk, illetve csak onnan kapcsolunk le vagonokat, egyesével). Így az ötlet az, hogy tároljuk egy veremben a legnagyobb közös osztókat. Ha jön egy új vagon, akkor annak a kapacitásának és a verem tetejének legnagyobb közös osztóját beszúrjuk a verem tetejére. Ha egy vagont lekapcsolnak, akkor eltávolítjuk a verem tetejét. így a válasz mindig a verem tetején lesz. Ha ügyesek vagyunk, rájöhetünk, hogy azt az esetet, amikor a vonat üres (a verem üres) könnyen kezelhetjük, ha eredetileg egy egyetlen 0 értéket tartalmazó veremmel indulunk (így az üres verem helyett mindig egy 0-t tartalmazó vermet kapunk, egyébként nem módosítja a választ).

Minta 3 pontért

A további 8 pont megszerzéséhez másképp kell hozzáállni a feladathoz. Először is vegyük észre, hogy ha egy vagon kapacitását 0-ra átírjuk, az olyan, mintha lekapcsoltuk volna (nem befolyásolja a legnagyobb közös osztót). A második fontos megfigyelés az, hogy maximum \(\displaystyle N\)-szer kapcsolunk a szerelvényhez új vagont, így az összhossz maximum \(\displaystyle N\) a lekapcsolt vagonokkal együtt.

Ezeket kihasználva ha egy csupa nullát tartalmazó tömbbel indulunk és mindig meg tudjuk találni a lekapcsolandó vagon indexét, akkor a feladat a következő lesz: Van egy tömbünk, ebben átírhatunk egy tetszőleges elemet, illetve lekérdezhetjük az egész tömb legnagyobb közös osztóját. Ez a szegmensfa klasszikus alkalmazása (ahol a szegmensfa művelete nyilvánvalóan a legnagyobb közös osztó).

Ennek tudatában az első részfeladat megoldását kiterjeszthetjük: Egy kétvégű sort (deque) kell fenntartani a tömbben, illetve egy szegmensfát építeni rá. Ezt könnyen megtehetjük két mutatóval (indexxel), amik a szerelvény első és utolsó vagonjára mutatnak.

A pontos megvalósításhoz lásd a mintamegoldást:

Minta 10 pontért

Minta 10 pontért (szegmensfa pointer-ekkel)


Statisztika:

17 dolgozat érkezett.
10 pontot kapott:Csenger Géza, Csertán András, Dóczi András, Gáspár Attila, Horváth Botond István, Janzer Orsolya Lili, Kiss Gergely, Nagy Nándor, Németh 123 Balázs, Noszály Áron, Vári-Kakas Andor.
9 pontot kapott:Tóth 827 Balázs.
8 pontot kapott:1 versenyző.
6 pontot kapott:1 versenyző.
4 pontot kapott:1 versenyző.
1 pontot kapott:2 versenyző.

A KöMaL 2016. novemberi informatika feladatai