Czwarte zadanie z ASD:
Rozważmy uporządkowany ciąg C różnych liczb naturalnych długości n>0 oraz wybrany element c tego ciągu. Dalej przyjmujemy, że algorytm wyszukiwania binarnego jest zgodny z poniższym (zakładamy indeksowanie elementów ciągu od wartości początkowej 0):
1 l:=0, r:=n-1, m:=(l+r)/2; 2 3 while (C[m]!=c) { 4 if (C[m]<c) 5 l:=m+1; 6 else 7 r:=m-1; 8 m:=(l+r)/2; 9 }
Wprowadzamy teraz modyfikacje algorytmu wyszukiwania binarnego polegającą na tym, że w miejsce instrukcji zawartych w wierszach 4-8 w pewnej iteracji rozważanego algorytmu wykonujemy sekwencyjne przeszukanie pozostałego fragmentu ciągu począwszy od pozycji l aż do skutku, tj.
4 while (C[l]!=c) 5 l:=l+1; 6 7 m:=l; 8
Załóżmy, że koszt wykonania algorytmu wszykiwania binarnego (zarówno bez i z w/w modyfikacją) oznaczamy jako COST i definiujemy zależnością:
COST=sqrt(a)*div+cmp
gdzie a jest pewną dodatnią stałą naturalną, sqrt(a) jest funkcją, której rezultatem jest część naturalna z pierwiastka z liczby a oraz div i cmp to odpowiednio liczba operacji dzielenia przez 2 (wiersze 1 i 8) oraz liczba operacji prówniania z elementami ciągu C występujacych w rozważanym algorytmie (wiersze 3 i 4).
Wyznacz najmniejszą możliwą wartość stałej a, dla której wykonanie algorytmu wyszukiwania binarnego z modyfikacją sekwencyjną niezależnie od wybranej iteracji zastosowania tej modyfikacji, prowadzi w każdym przypadku do rozwiązania o koszcie mniejszym niż standardowe wyszukiwanie binarne (tj. algorytm bez modyfikacji sekwencyjnej).
Wejście
Wiersz zawierający ciąg liczb naturlanych oddzielonych znakiem odstępu/spacji (ASCII kod 32) i zakończony znakiem końca pliku (EOF), gdzie:
- pierwszy element ciągu definiuje długość n ciągu C tak, że n zawarte jest w przedziale wartości [1,10^6],
- kolejne elementy ciągu reprezentują elementy właściwe ciagu C i zawarte są w przedziale wartości [0,10^9],
- ostatni element ciągu wejściowego reprezentuje wybrane element c ciągu C.
Wyjście
Wiersz zawierajacy pojedynczą liczbę naturalną nie większą niż 10^9 będącą rozwiązaniem postawionego problemu (wiersz pusty w przypadku braku rozwiązania).
Złożoności i limity
Złożoność czasowa O(n), złożoność pamięciowa O(n), gdzie n jest długością ciągu podanego na wejściu. Fizyczny limit pamięci zależny od rozmiaru danych wejściowych i ograniczony przez 4n B + 1 KB.
Przykład 1
Wejście: 3 1 2 3 3 Wyjście: 9
Przykład 2
Wejście: 10 0 1 2 3 4 5 6 7 8 9 0 Wyjście: 1
Rozwiązanie w C++:
#include <stdio.h> int main() { int n; fscanf(stdin, "%i", &n); int* C = new int[n]; for(int i = 0; i < n; i++) { fscanf(stdin, "%i", &C[i]); } int c; fscanf(stdin, "%i", &c); n--; int l = 0; int r = n; int m = (l + r) / 2; int binarneDzielenie = 1; int binarnePorownania = 1; while(C[m] != c) { binarnePorownania++; if(C[m] < c) l = m + 1; else r = m - 1; binarnePorownania++; m = (l + r) / 2; binarneDzielenie++; } int indeksWyniku = m; l = 0; r = n; m = (l + r) / 2; int minimalneA = 0; int sekwencyjneDzielenie = 1; int sekwencyjnePorownania = 1; while(C[m] != c) { sekwencyjnePorownania++; int iloscPorownan = sekwencyjnePorownania + indeksWyniku - l + 1; int a = ((iloscPorownan - binarnePorownania) / (binarneDzielenie - sekwencyjneDzielenie)) + 1; if(a > minimalneA) minimalneA = a; if(C[m] < c) l = m + 1; else r = m - 1; sekwencyjnePorownania++; m = (l + r) / 2; sekwencyjneDzielenie++; } fprintf(stdout, "%i", minimalneA * minimalneA); return 0; }