###### tags: `ilo` *MAP 2021* # Notatki - grupa podstawowa ## 12.06.2021 ### Sortowanie za pomocą funkcji sort() Funkcja `sort()` znajduje się w bibliotece `algorithm`. Sortuje ona elementy z podanego zakresu. Jako pierwszy argument funkcja `sort` przyjmuje wskaźnik (strzałeczkę) na pierwszy element - nazwijmy ten argument *first*, a drugi element to wskaźnik na ostatni element - nazwijmy go *end*. Sort sortuje zakres \[*first*,*end*\). Trzeci argument jest opcjonalny i jest oznaczaniem funkcji, która kontroluje porządek utrzymywany w trakcie sortowania. ``` Sortowanie całej tablicy 5-elementowej o nazwie tablica: sort(tablica, tablica+5); Sortowanie tylko 3 środkowych elementów powyższej tablicy: sort(tablica+1, tablica+4); Sortowanie vectora G: sort(G.begin(), G.end()); ``` #### Przykład użycia ```cpp= #include <iostream> #include <algorithm> using namespace std; int tab[5]={8,2,7,1,4}; void wypisz(){ for(int i=0; i<5; i++){ cout<<tab[i]<<" "; } cout<<"\n"; } bool cmp(int a, int b){ return a > b; } int main(){ wypisz(); // 8 2 7 1 4 sort(tab, tab+5); wypisz(); // 1 2 4 7 8 sort(tab, tab+5, cmp); wypisz(); // 8 7 4 2 1 return 0; } ``` ### Para Para to mała struktura pozwalająca utrzymywać wygodnie dwa elementy dowolnych typów. ``` deklaracja: pair<typ pierwszego elementu, typ drugiego elementu> nazwa; ``` Do elementów pary dostajemy się za pomocą słów *first* i *second*, które umieszczamy po nazwie pary i kropce. #### Przykład deklaracji pary ```cpp= ... // ↓ tablica, w której trzymamy imiona i wagi naszych królików pair<string, int> kroliki[2]; kroliki[0].first = "Leszek"; kroliki[0].second = 21; kroliki[1].first = "Pies"; kroliki[1].second = 37; // Nadpisywanie pary nową parą: kroliki[0] = make_pair("Staszek", 19); // można też tak: kroliki[1] = {"Patrycja", 11}; ``` ## 29.05.2021 ### Sumy prefiksowe Gdy potrzebujemy szybko odpowiadać na zapytania o sumę pewnych wyników na przedziałach (na przykład z tablicy `tab`), możemy użyć do tego tablicy sum prefiksowych. Wynik w miejscu `x` w tablicy sum prefiksowych oznacza wynik dla tablicy `tab` z przedziału od początku tablicy do `x`. By uzyskać wynik na przedziale $[a, b]$, wystarczy wziąć wynik z przedziału $[0, b]$ i odjąć od niego wynik z przedziału $[0, a-1]$. #### Przykład Powiedz jaka jest suma liczb na zadanym przedziale. ```cpp= int tab[] = {0,1,2,3,4,5}; //przykładowa tablica //indeksy: 0,1,2,3,4,5 int sumy[5]; //tablica sum prefiksowych //uzupełnijmy tablicę sum prefiksowych for(int i=1; i<5; i++){ sumy[i] = sumy[i+1] + tab[i]; } //odpowiadamy na pytania // [2, 5] tab[5]-tab[2-1]; // [1, 2] tab[2]; tab[2]-tab[1-1]; //lub ogólniej //[a, b] tab[b]-tab[a-1]; ``` ### Tablica https://miro.com/app/board/o9J_lBslUk0=/ <iframe width="768" height="432" src="https://miro.com/app/live-embed/o9J_lBslUk0=/?moveToViewport=-696,-346,2133,1045" frameBorder="0" scrolling="no" allowFullScreen></iframe> ## 15.05.2021 Przykłady z wyszukiwaniem binarnym: ### Przykład 1 Grasz z drugą osobą w *Zgadnij liczbę*. Osoba ta myśli liczbę od 1 do $n$, a Ty musisz zgadnąć co to za liczba. Możesz zadawać osobie pytania, na które może odpowiadać tylko TAK/NIE. Dodatkowo chcesz być pewn_, że nie zadasz więcej niż $\lceil log_2(n)\rceil$ pytań. ```python= def binary_search(start, koniec): lewy = start - 1 prawy = koniec + 1 while lewy + 1 < prawy: srodek = (lewy+prawy)/2 if <czy środek jest >= od pomyślanej liczby?>: prawy = srodek else: lewy = srodek return <Ta liczba to prawy> def main(): p = 1 n = <osoba mówi jaka jest maksymalna liczba> print("Twoja liczba to:", binary_search(p, n)) ``` ### Przykład 2 Franek ma swoim domu hodowlę królików - ma ich bardzo dużo! Weterynarz kazał mu co jakiś czas przyjeżdzać na kontrolę z pierwszym królikiem o wadze mniejszej niż $x$. Pomóż Frankowi szybko dowiadywać się z którym królikiem powinien jechać na kontrolę zdrowia. *Wejście* Dostajesz $n$ - liczbę królików, a następnie w $n$ liniach pary $w, p$, gdzie $w$ ($0<w\leq10^9$) to waga królika, a $p$ to jego imię. Króliki podawane są w kolejności rosnącej wag. Następnie na wejściu pojawia się liczba $q$, a po niej $q$ zapytań z jedną liczbą $x$. *Wyjście* Twoim zadaniem jest wypisanie $q$ wierszy, w każdym należy wypisać imię pierwszego lżejszego niż $x$ królika. Jeśli nie ma takiego królika, należy wypisać pusty napis. *Przykładowe wejście* ``` 5 13 Jan 9 Jola 12 Joachim 3 Jurek 7 Joanna 3 10 2 15 ``` *Przykładowe wyjście* ``` Jola Jan ``` #### Rozwiązanie przykładu 2 ```cpp= #include <iostream> #include <string> using namespace std; int n; int wagi[1000002]; string imiona[1000002]; string bs(int x){ int lewy = 0; int prawy = n+1; while(lewy+1<prawy){ int srodek = (lewy+prawy)/2; if( wagi[srodek] >= x ){ prawy = srodek; }else{ lewy = srodek; } } return imiona[lewy]; } int main(){ int q,x; cin>>n; for(int i=1; i<=n; i++){ cin>>wagi[i]>>imiona[i]; } cin>>q; for(int i=0; i<q; i++){ cin>>x; cout<<bs(x)<<"\n"; } return 0; } ``` ### Tablica https://miro.com/app/board/o9J_lEMdokI=/ <iframe width="768" height="432" src="https://miro.com/app/live-embed/o9J_lEMdokI=/?moveToViewport=-1248,-452,4210,2054" frameBorder="0" scrolling="no" allowFullScreen></iframe> ## 07.05.21 ### Własności wykorzystywane przy algorytmie Euklidesa $$ nwd(a,0) = a\\ nwd(a,b) = nwd(b, a-b) \text{ dla } a>b\\ nwd(a,b) = nwd(b, a\ mod\ b)\\ $$ [Więcej o NWD (wiki)](https://pl.wikipedia.org/wiki/Najwi%C4%99kszy_wsp%C3%B3lny_dzielnik#Za_pomoc%C4%85_algorytmu_Euklidesa) [Więcej o NWW (wiki)](https://pl.wikipedia.org/wiki/Najmniejsza_wsp%C3%B3lna_wielokrotno%C5%9B%C4%87#Algorytmy_wyznaczania_NWW) ### Przydatne informacje 1. Typ `int` ma 4 bajty = 32 bity. 2. W zmiennej typu `int` możemy trzymać liczby od $-2^{31}$ (~ -2mld.) do $2^{31}-1$ (~ 2 mld.) [→ Więcej informacji o typach ←](http://cpp0x.pl/kursy/Kurs-C++/Poziom-1/Pojecie-zmiennej-i-podstawowe-typy-danych/11) 3. Komputerowi wykonanie $10^8$ operacji zajmuje ok. 1 sekundy. 4. Trzeba pamiętać, że gdy nie przypisujemy wartości danej komórce pamięci, to znajduje się tam losowa wartość (tak jak znak zapytania w maszynie RAM). 5. Zadania na Themisie i na konkursach często mają limit pamięci. Jednym z przeliczników, które warto znać jest ten, że tablica miliona intów ma rozmiar 4MB. 6. Deklarując tablicę musimy pamiętać o jej odpowiedniej wielkości. Nie możemy jako programiści dopuścić do zaglądania w "nie naszą pamięć". Np. próba odczytu lub zapisu do komórki spoza tablicy, w zadaniu na Themisie, np. tab\[-1\], lub tab\[10\] (dla tablicy 10 elementowej), zakończy się odpowiednim błędem. 7. Próba zapisu liczby o typie innym niż zmienna do której zapisujemy, nie zakończy się błędem. Program wykona swoje zadanie, odpowiednio ucinając liczbę, lub modyfikując ją w inny sposób. Np. `cout<<(int)(3.5);` wypisze liczbę 3. ### Tablica https://miro.com/app/board/o9J_lF6SJLk=/ <iframe width="768" height="432" src="https://miro.com/app/live-embed/o9J_lF6SJLk=/?moveToViewport=-1058,734,2996,1462" frameBorder="0" scrolling="no" allowFullScreen></iframe>