РНК
Аутор: Младен Пузић
Текст и тест примери: Димитрије Ердељан
Анализа решења: Младен Пузић
Тестирање: Тадија Шебез
Подзадатак 1
Користећи 4N упита, можемо одредити цео прототип (за сваку позицију можемо да питамо колико има сваког слова на тој позицији). Након тога можемо пробати сваки интервал за промену, видети да ли даје валидну вакцину. Временска/меморијска сложеност: O(N^2), број позива функцији: 4N.
Подзадатак 2
Слично претходном подзадатку, можемо открити цео прототип, али овај пут смемо користити највише 3 упита по позицији. То није проблем, јер можемо питати за три кодона, ако ниједан не важи, знамо да је у питању четврти кодон. Одредимо кодон који се појављује више од \frac{N}{2} пута, рецимо да се појављује x пута, док се његов комплемент појављује y пута. Желимо да се најчешћи кодон у нашем интервалу појављује макар \frac{x-y}{2} пута више од комплемента. Не сме да се појављује ни превише пута, јер онда његов комплемент постаје елемент који се појављује више од \frac{N}{2} пута, срећом у већини случајева можемо наћи баш интервал у ком се најчешћи кодон појављује тачно \lceil\frac{x-y}{2}\rceil пута више од комплемента. Једини случај у којем то није могуће је уколико је N непаран број и важи x+y=N, у том случају који год интервал да изаберемо, постојаће елемент који се појављује више од \frac{N}{2} пута, па решење не постоји.
Уколико то није случај, постоји одговарајући интервал, и то одговарајући интервал који је и префикс. Назовимо са f(i) разлику броја појављивања најчешћег елемента и његовог комплемента у првих i елемената. Јасно је да важи f(0) = 0 и f(N) = x-y. Како се f(i) и f(i+1) разликују за највише 1, можемо рећи да је у неком смислу ова функција непрекидна, тј. постоје индекси за које износи 0 и x-y, постоје и индекси где износи и било шта између тога, укључујући и \lceil\frac{x-y}{2}\rceil. Самим тим, постоји префикс који нам одговара, и можемо га једноставно наћи.
Временска/меморијска сложеност: O(N), број позива функцији: 3N.
Подзадатак 3
Овај подзадатак веома је сличан претходном, нећемо директно одредити цео прототип, него ћемо искористити 3 позива функцији да за сваки кодон одредимо колико пута се појављује, тј. да одредимо који кодон се појављује највише пута. Када имамо ту информацију, можемо да израчунамо f(i) са два позива функцији. Можемо да израчунамо f(i) и одаберемо оно које нам одговара. Временска/меморијска сложеност: O(N), број позива функцији: (највише) 2N+3.
Подзадатак 4
Нађимо колико се који кодон појављује, односно који се појављује најчешће. Нађимо сва појављивања његовог комплемента у низу користећи до сад укупно N+3 позива функцији. Тих појављивања може бити највише \frac{N}{2}. За сваки префикс који се завршава на једном од ових појављивања, откријмо колико се пута до њега појављује најчешћи кодон. Ова информација нам, због непрекидности наше функције, помаже да одредимо између која два појављивања се налази префикс који тражимо. Када нађемо ту информацију, можемо урадити бинарну претрагу, да нађемо тачан потребан индекс. Временска/меморијска сложеност: O(N), број позива функцији: (највише) 1.5N+\lceil logN\rceil+3.
Главно решење
Користићемо бинарну претрагу да нађемо i за које важи f(i) = \lceil\frac{x-y}{2}\rceil. Знамо f(0) = 0 и f(N) = x-y, проверавамо f(mid). Важиће да ће се \lceil\frac{x-y}{2}\rceil налазити или између f(l) и f(mid) или између f(mid) и f(r) (можда и на оба места, али нама је довољно једно). Ово важи по непрекидности наше функције. Онда настављамо бинарну претрагу у делу који садржи вредност коју тражимо. Временска/меморијска сложеност: O(logN), број позива функцији: (највише) 2\lceil logN\rceil+3.