Binarni blokovi

Niz binarnih cifara je podeljen na blokove na sledeći način:

Na primer, niz 1001 podeljen je na 4 bloka dužine 1 (1, 0, 0 i 1), na 2 bloka dužine 2 (10 i 01) i na 1 blok dužine 4 (1001).

Ispisati najduži blok koji sadrži jednak broj 0 i 1. Ukoliko postoji više takvih blokova, ispisati onaj sa najvećim početnim indeksom u polaznom nizu.

Opis ulaza

Sa standardnog ulaza se unosi prirodan broj \(n\) koji predstavlja dužinu niza (može se smatrati da je stepen broja 2). Zatim se unosi \(n\) binarnih cifara koje čine niz.

Opis izlaza

Na standardni izlaz ispisati traženi blok. U slučaju da takav blok ne postoji, ispisati -1.

Primer

Ulaz

8 1 0 1 1 0 1 0 1

Izlaz

0 1 0 1

Rešenje

Zadatak možemo rešiti primenom tehnike podeli-pa-vladaj. Možemo primetiti da blok sadrži jednak broj 0 i 1 ukoliko je broj jedinica koje sadrži jednak polovini ukupnog broja elemenata.

Definišimo rekurzivnu funkciju pronađiBlok koja kao parametre prima niz, indeks početka i indeks kraja bloka. Funkcija treba da vrati broj jedinica u bloku određenom prosleđenim indeksima i usput proveri da li je u pitanju najduži blok sa jednakim brojem 0 i 1.

Bazni slučaj je jednočlani blok i tada je dovoljno proveriti da li je jedini element 1. Ukoliko blok ima barem dva elementa, delimo ga na levu i desnu polovinu, pozivamo funkciju rekurzivno za obe polovine i dohvatamo rezultate rekurzivnih poziva. Ostaje da proverimo da li su rezultati u zbiru jednaki polovini broja elemenata trenutno posmatranog bloka i po potrebi ažuriramo indekse najdužeg bloka. Kao povratnu vrednost funkcije vraćamo zbir rezultata rekurzivnih poziva.

#include <iostream>
#include <vector>

using namespace std;

int najbolje_l = -1, najbolje_d = -1;

int pronađiBlok(const vector<int>& v, int l, int d){
   if(l == d)
      return v[d];

   int s = (d + l)/2;
   int levo = pronađiBlok(v, l, s);
   int desno = pronađiBlok(v, s+1, d);

   if(levo + desno == (d - l + 1)/2){
      if(d - l + 1 > najbolje_d - najbolje_l + 1 || 
         d - l + 1 == najbolje_d - najbolje_l + 1 && l > najbolje_l){
            najbolje_l = l;
            najbolje_d = d;
         }
   }

   return levo + desno;
}

int main() {

   int n;
   cin >> n;

   vector<int> v(n);
   for(int i = 0; i < n; i++)
      cin >> v[i];

   pronađiBlok(v, 0, n-1);

   if(najbolje_l == -1){
      cout << -1 << endl;
      return 0;
   }

   for(int i = najbolje_l; i <= najbolje_d; i++){
      cout << v[i] << " ";
   }
   cout << endl;

   return 0;
}