LearnToCP
Prijavi se
Navigacija
PočetnaRoad-mapaProblemiO Nama
Teorija
Takmičarsko Znanje
Izbor Radnog Okruženja (IDE)
Osnove
Tvoj Prvi ProgramTipovi podataka, Unos i IzlazC++ sintaksaModuloFunkcijeVektoriMatriceVremenska Složenost Algoritma
Sortiranje
SortiranjeSortiranje PrebrojavanjemRadix Sort
Tehnike Optimizacije
Dva PokazivačaZbir brojeva od 1 do nZbir PrefiksaBinarna PretragaPohlepni AlgoritmiFunkcije Binarne PretrageBinarna Pretraga po RešenjuPodeli, pa Vladaj
Binarni Brojevi
Binarni BrojeviBrojevi u koduOperacije nad BitovimaBitmaske
Matematika
Binarno StepenovanjeProsti BrojeviRastavljanje na proste činioceNZD i NZSEratostenovo SitoModifikovano Sito
Strukture Podataka
Niske (Stringovi)StekRedMapeSkupovi (Set)Red sa PrioritetomKorišćenje Proizvoljnih KriterijumaSegmentna StablaFenvikova StablaSparse TabeleDisjunktni Skupovi
Kombinatorika
Pravilo SabiranjaPravilo MnoženjaKombinatorni ObjektiPrincip Uključenja Isključenja
Geometrija
Osnove GeometrijeVektoriVektorski i Skalarni ProizvodLinijePoligoniUgloviTačka u PoligonuRastojanja i Tačke PresekaKonveksni OmotačKrugovi
Rekurzija
PokazivačiRekurzijaGenerisanje Kombinatornih Objekata
Dinamičko Programiranje
O DP-uDP nad StablimaDP nad BitmaskamaDP nad brojevima
Teorija Grafova
GrafoviDFS i BFSNajkraći PuteviStablaTopološko SortiranjeDajkstrin AlgoritamMinimalna Razapinjuća StablaAlgoritmi Najkraćih Puteva
Napredna Teorija Grafova
Dvostruka PovezanostJako Povezane KomponenteBipartitni GrafMaksimalni Protok u GrafuFord-Fulkersonov AlgoritamDualnost Protoka i Minimalnog PresekaTeško-Laka DekompozicijaCentroidna Dekompozicija
Napredne Strukture Podataka
2D i 3D Segmentna StablaLenjo PropagiranjeImplicitna Segmentna StablaPerzistentna Segmentna StablaNajbliži Zajednički PredakTrieBalansirana Binarna Stabla PretrageMoov Algoritam

Binarna Pretraga po Rešenju

U ovoj lekciji naučićemo tehniku koja pronalazi najbolju moguću vrednost u O(log n) - Binarnu Pretragu po Rešenju (en. Binary Search by Answer)

Binarna Pretraga po Rešenju veoma liči na običnu binarnu pretragu.

Prva razlika je u tome što se ne zaustavljamo čim pronađemo rešenje. Zapamtimo ga, pa nastavimo da tražimo bolje.

Druga razlika je u tome što ne pretražujemo niz. Umesto niza, sami određujemo dve vrednosti:

  • low - najmanja vrednost koja bi mogla biti rešenje
  • high - najveća vrednost koja bi mogla biti rešenje

Nad tim opsegom pokrećemo binarnu pretragu, i u svakom koraku proveravamo da li nam ta vrednost rešava zadatak.

Pseudo kod:

bool check(int mid){ //ova funkcija proverava da li trenutni broj rešava zadatak

}

int main(){

    int low = 1; //najmanja vrednost koja bi mogla biti rešenje
    int high = 100000; //najveća vrednost koja bi mogla biti rešenje

    int ans = -1; //na početku pretpostavljamo da rešenja nema

    while(low <= high){

        int mid = (low + high) / 2;

        if(check(mid)){ //ako je uslov zadovoljen

            ans = mid; //zapamtimo rešenje
            high = mid - 1; //pa probamo da nađemo bolje

        }else{
            low = mid + 1; //nije rešenje, probamo dalje
        }
    }

    cout<<ans<<'\n';

}

Vremenska složenost: O(log high * T), gde je T složenost funkcije check().

Kada ovo radi?

Važno je razumeti da se ova tehnika ne može primeniti na svaki zadatak.

Radi samo kada rešenja izgledaju ovako:

NE NE NE NE NE DA DA DA DA

Drugim rečima, ako jedna vrednost zadovoljava uslov, moraju ga zadovoljavati i sve manje (ili sve veće, u zavisnosti od zadatka).

Nama je onda potrebna granica - poslednje NE i prvo DA.

Dva reda rezultata funkcije check nad vrednostima od 1 do 12: prvi se sa false na true prelama tačno jednom, kod 8, što je rešenje, dok se drugi prelama više puta pa granica ne postoji