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;
}