├── .gitignore ├── README.md ├── README.ru.md ├── lab01-linear ├── CMakeLists.txt ├── src │ ├── a.cpp │ ├── b.cpp │ ├── c.cpp │ ├── d.cpp │ ├── e.cpp │ └── f.cpp └── tasks.pdf ├── lab02-sort ├── CMakeLists.txt ├── draft │ ├── a_mergesort.cpp │ ├── e.cpp │ └── h.cpp ├── src │ ├── a.cpp │ ├── b.cpp │ ├── d.cpp │ └── f.cpp └── tasks.pdf ├── lab03-heap-dsu ├── CMakeLists.txt ├── src │ ├── a.cpp │ ├── b.cpp │ ├── c.cpp │ ├── d.cpp │ ├── e.cpp │ ├── f.cpp │ ├── g.cpp │ ├── h.cpp │ ├── i.cpp │ └── j.cpp └── tasks.pdf ├── lab04-dp ├── CMakeLists.txt ├── draft │ ├── j.cpp │ └── m.cpp ├── src │ ├── a.cpp │ ├── b.cpp │ ├── d.cpp │ ├── e.cpp │ ├── f.cpp │ ├── k.cpp │ ├── l.cpp │ ├── o.cpp │ ├── r.cpp │ └── s.cpp └── tasks.pdf ├── lab05-bst ├── CMakeLists.txt ├── draft │ ├── e_1.cpp │ └── e_2.cpp ├── src │ ├── a.cpp │ └── c.cpp └── tasks.pdf ├── lab06-hash ├── CMakeLists.txt ├── draft │ └── a.cpp └── tasks.pdf ├── lab07-segment ├── CMakeLists.txt ├── src │ ├── a.cpp │ ├── b.cpp │ ├── d.cpp │ ├── e.cpp │ ├── f.cpp │ ├── g.cpp │ ├── h.cpp │ ├── j.cpp │ ├── k.cpp │ ├── l.cpp │ ├── m.cpp │ └── o.cpp └── tasks.pdf ├── lab08-sortnet ├── CMakeLists.txt ├── draft │ └── b.cpp └── tasks.pdf ├── lab09-dfs ├── CMakeLists.txt ├── src │ ├── a.cpp │ ├── b.cpp │ ├── c.cpp │ ├── d.cpp │ ├── e.cpp │ ├── f.cpp │ ├── g.cpp │ ├── h.cpp │ ├── i.cpp │ ├── j.cpp │ ├── k.cpp │ ├── l.cpp │ ├── m.cpp │ ├── n.cpp │ ├── o.cpp │ ├── p.cpp │ ├── q.cpp │ └── s.cpp └── tasks.pdf ├── lab10-shortest-spanning ├── CMakeLists.txt ├── src │ ├── a.cpp │ ├── d.cpp │ ├── e.cpp │ ├── f.cpp │ ├── g.cpp │ └── h.cpp └── tasks.pdf ├── lab11-matching ├── CMakeLists.txt ├── src │ ├── c.cpp │ └── d.cpp └── tasks.pdf ├── lab12-flow └── tasks.pdf ├── lab13-strings ├── CMakeLists.txt ├── draft │ └── g.cpp ├── src │ ├── a.cpp │ ├── b.cpp │ ├── c.cpp │ ├── d.cpp │ └── f.cpp └── tasks.pdf ├── lab14-suffix ├── CMakeLists.txt ├── draft │ └── i.cpp ├── src │ ├── a.cpp │ ├── b.cpp │ ├── c.cpp │ ├── d.cpp │ ├── e.cpp │ ├── f.cpp │ ├── g.cpp │ └── j.cpp └── tasks.pdf ├── lab15-exp └── tasks.pdf └── lab16-numbers ├── CMakeLists.txt ├── draft └── g.cpp ├── src ├── a.cpp └── b.cpp └── tasks.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | lab01-linear/.idea/ 2 | lab01-linear/cmake-build-debug/ 3 | lab02-sort/.idea/ 4 | lab02-sort/cmake-build-debug/ 5 | lab03-heap-dsu/.idea/ 6 | lab03-heap-dsu/cmake-build-debug/ 7 | lab04-dp/.idea/ 8 | lab04-dp/cmake-build-debug/ 9 | lab05-bst/.idea/ 10 | lab05-bst/cmake-build-debug/ 11 | lab07-segment/.idea/ 12 | lab07-segment/cmake-build-debug/ 13 | lab08-sortnet/.idea/ 14 | lab08-sortnet/cmake-build-debug/ 15 | lab09-dfs/.idea/ 16 | lab09-dfs/cmake-build-debug/ 17 | lab10-shortest-spanning/.idea/ 18 | lab10-shortest-spanning/cmake-build-debug/ 19 | lab11-matching/.idea/ 20 | lab11-matching/cmake-build-debug/ 21 | lab13-strings/.idea/ 22 | lab13-strings/cmake-build-debug/ 23 | lab14-suffix/.idea/ 24 | lab14-suffix/cmake-build-debug/ 25 | lab16-numbers/.idea/ 26 | lab16-numbers/cmake-build-debug/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![en](https://img.shields.io/badge/lang-en-red.svg)](README.md) [![en](https://img.shields.io/badge/lang-ru-blue.svg)](README.ru.md) 2 | 3 | # Algorithms and Data Structures 4 | 5 | Course was designed and taught by [Niyaz Nigmatullin](https://github.com/niyaznigmatullin) at ITMO University in 2017–19 (year2017, 1st–4th semesters). 6 | 7 | ## Labs 8 | 9 | ### 1st semester 10 | 11 | 1. Linear data structures 12 | * **themes:** _amortized analysis_ 13 | * [statements (ru)](lab01-linear/tasks.pdf), [solutions](lab01-linear) 14 | 2. Sorts and searches 15 | * **themes:** _sorts, search algorithms_ 16 | * [statements (ru)](lab02-sort/tasks.pdf), [solutions](lab02-sort) 17 | 3. Priority queues and DSU 18 | * **themes:** _priority queue, disjoint set union_ 19 | * [statements (ru)](lab03-heap-dsu/tasks.pdf), [solutions](lab03-heap-dsu) 20 | 4. Dynamic programming 21 | * **themes:** _dynamic programming_ 22 | * [statements (ru)](lab04-dp/tasks.pdf), [solutions](lab04-dp) 23 | 24 | ### 2nd semester 25 | 26 | 5. Search trees 27 | * **themes:** _search data structures_ 28 | * [statements (ru)](lab05-bst/tasks.pdf), [solutions](lab05-bst) 29 | 6. Hash-tables 30 | * **themes:** _hashing_ 31 | * [statements (ru)](lab06-hash/tasks.pdf) 32 | 7. Segment queries 33 | * **themes:** _segment queries, binary indexed tree, least common ancestor_ 34 | * [statements (ru)](lab07-segment/tasks.pdf), [solutions](lab07-segment) 35 | 8. Sorting nets 36 | * **themes:** _sotring nets_ 37 | * [statements (ru)](lab08-sortnet/tasks.pdf), [solutions](lab08-sortnet) 38 | 39 | ### 3rd semester 40 | 41 | 9. DFS 42 | * **themes:** _basics of graph theory, connectivity in graphs, depth-first search_ 43 | * [statements (ru)](lab09-dfs/tasks.pdf), [solutions](lab09-dfs) 44 | 10. Shortest paths and spanning trees 45 | * **themes:** _spanning trees, shortest path problem_ 46 | * [statements (ru)](lab10-shortest-spanning/tasks.pdf), [solutions](lab10-shortest-spanning) 47 | 11. Independent edge set 48 | * **themes:** _matching problem_ 49 | * [statements (ru)](lab11-matching/tasks.pdf), [solutions](lab11-matching) 50 | 12. Flows 51 | * **themes:** _maximum flow problems, minimum-cost flow problem_ 52 | * [statements (ru)](lab12-flow/tasks.pdf) 53 | 54 | ### 4th semester 55 | 56 | 13. String algorithms 57 | * **themes:** _basics of string theory, string searching algorithm_ 58 | * [statements (ru)](lab13-strings/tasks.pdf), [solutions](lab13-strings) 59 | 14. Suffix data structures 60 | * **themes:** _string searching algorithm, suffix tree, suffix array_ 61 | * [statements (ru)](lab14-suffix/tasks.pdf), [solutions](lab14-suffix) 62 | 15. Exponential algorithms 63 | * **themes:** _exponential algorithms_ 64 | * [statements (ru)](lab15-exp/tasks.pdf) 65 | 16. Arithmetical and algebraic algorithms 66 | * **themes:** _basics of number theory, fundamental theorem of arithmetic, basics of group theory_ 67 | * [statements (ru)](lab16-numbers/tasks.pdf), [solutions](lab16-numbers) 68 | 69 | ## Useful links 70 | 71 | * ["Алгоритмы и структуры данных" on wikiconspects (ru)](http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B8_%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D1%8B_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85) 72 | * ["Теория графов" on wikiconspects (ru)](http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B8%D1%8F_%D0%B3%D1%80%D0%B0%D1%84%D0%BE%D0%B2) 73 | * ["Алгоритмы на строках" on wikiconspects (ru)](http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%BD%D0%B0_%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B0%D1%85) 74 | * ["Алгоритмы алгебры и теории чисел" on wikiconspects (ru)](http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B0%D0%BB%D0%B3%D0%B5%D0%B1%D1%80%D1%8B_%D0%B8_%D1%82%D0%B5%D0%BE%D1%80%D0%B8%D0%B8_%D1%87%D0%B8%D1%81%D0%B5%D0%BB) -------------------------------------------------------------------------------- /README.ru.md: -------------------------------------------------------------------------------- 1 | [![en](https://img.shields.io/badge/lang-en-red.svg)](README.md) [![en](https://img.shields.io/badge/lang-ru-blue.svg)](README.ru.md) 2 | 3 | # Алгоритмы и Структуры Данных 4 | 5 | Курс подготовил и прочитал [Нияз Нигматуллин](https://github.com/niyaznigmatullin) в Университете ИТМО в 2017—19 годах (year2017, 1—4 семестры). 6 | 7 | ## Лабораторные работы 8 | 9 | ### 1 семестр 10 | 11 | 1. Линейные структуры данных 12 | * **примерные темы:** _амортизационный анализ_ 13 | * [условия](lab01-linear/tasks.pdf), [решения](lab01-linear) 14 | 2. Сортировки и поиск 15 | * **примерные темы:** _сортировки, алгоритмы поиска_ 16 | * [условия](lab02-sort/tasks.pdf), [решения](lab02-sort) 17 | 3. Приоритетные очереди и СНМ 18 | * **примерные темы:** _приоритетные очереди, система непересекающихся множеств_ 19 | * [условия](lab03-heap-dsu/tasks.pdf), [решения](lab03-heap-dsu) 20 | 4. Динамическое программирование 21 | * **примерные темы:** _динамическое программирование_ 22 | * [условия](lab04-dp/tasks.pdf), [решения](lab04-dp) 23 | 24 | ### 2 семестр 25 | 26 | 5. Деревья поиска 27 | * **примерные темы:** _поисковые структуры данных_ 28 | * [условия](lab05-bst/tasks.pdf), [решения](lab05-bst) 29 | 6. Хеш-таблицы 30 | * **примерные темы:** _хеширование_ 31 | * [условия](lab06-hash/tasks.pdf) 32 | 7. Запросы на отрезках 33 | * **примерные темы:** _запросы на отрезках, дерево Фенвика, задача о наименьшем общем предке_ 34 | * [условия](lab07-segment/tasks.pdf), [решения](lab07-segment) 35 | 8. Сортирующие сети 36 | * **примерные темы:** _сортирующие сети_ 37 | * [условия](lab08-sortnet/tasks.pdf), [решения](lab08-sortnet) 38 | 39 | ### 3 семестр 40 | 41 | 9. DFS 42 | * **примерные темы:** _основы теории графов, связность в графах, обход в глубину_ 43 | * [условия](lab09-dfs/tasks.pdf), [решения](lab09-dfs) 44 | 10. Кратчайшие пути и остовные деревья 45 | * **примерные темы:** _остовные деревья, кратчайшие пути в графах_ 46 | * [условия](lab10-shortest-spanning/tasks.pdf), [решения](lab10-shortest-spanning) 47 | 11. Паросочетания 48 | * **примерные темы:** _задача о паросочетании_ 49 | * [условия](lab11-matching/tasks.pdf), [решения](lab11-matching) 50 | 12. Потоки 51 | * **примерные темы:** _задача о максимальном потоке, задача о потоке минимальной стоимости_ 52 | * [условия](lab12-flow/tasks.pdf) 53 | 54 | ### 4 семестр 55 | 56 | 13. Строковые алгоритмы 57 | * **примерные темы:** _основы теории строк, поиск подстроки в строке_ 58 | * [условия](lab13-strings/tasks.pdf), [решения](lab13-strings) 59 | 14. Суффиксные структуры данных 60 | * **примерные темы:** _поиск подстроки в строке, суффиксное дерево, суффиксный массив_ 61 | * [условия](lab14-suffix/tasks.pdf), [решения](lab14-suffix) 62 | 15. Экспоненциальные алгоритмы 63 | * **примерные темы:** _экспоненциальные алгоритмы_ 64 | * [условия](lab15-exp/tasks.pdf) 65 | 16. Численные алгоритмы 66 | * **примерные темы:** _основы теории чисел, основная теорема арифметики, основы теории групп_ 67 | * [условия](lab16-numbers/tasks.pdf), [решения](lab16-numbers) 68 | 69 | ## Полезные ссылки 70 | 71 | * ["Алгоритмы и структуры данных" на викиконспектах](http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B8_%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D1%8B_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85) 72 | * ["Теория графов" на викиконспектах](http://neerc.ifmo.ru/wiki/index.php?title=%D0%A2%D0%B5%D0%BE%D1%80%D0%B8%D1%8F_%D0%B3%D1%80%D0%B0%D1%84%D0%BE%D0%B2) 73 | * ["Алгоритмы на строках" на викиконспектах](http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%BD%D0%B0_%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B0%D1%85) 74 | * ["Алгоритмы алгебры и теории чисел" на викиконспектах](http://neerc.ifmo.ru/wiki/index.php?title=%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B0%D0%BB%D0%B3%D0%B5%D0%B1%D1%80%D1%8B_%D0%B8_%D1%82%D0%B5%D0%BE%D1%80%D0%B8%D0%B8_%D1%87%D0%B8%D1%81%D0%B5%D0%BB) -------------------------------------------------------------------------------- /lab01-linear/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(lab01_linear) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_executable(a src/a.cpp) 7 | add_executable(b src/b.cpp) 8 | add_executable(c src/c.cpp) 9 | add_executable(d src/d.cpp) 10 | add_executable(e src/e.cpp) 11 | add_executable(f src/f.cpp) -------------------------------------------------------------------------------- /lab01-linear/src/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int size, head; 6 | int* stack; 7 | void resize(int); 8 | 9 | int main() { 10 | freopen("stack1.in", "r", stdin); 11 | freopen("stack1.out", "w", stdout); 12 | ios_base::sync_with_stdio(false); 13 | cin.tie(nullptr); 14 | cout.tie(nullptr); 15 | 16 | size = 1; 17 | head = -1; 18 | stack = (int*)malloc((size_t) size * sizeof(int)); 19 | int queries; 20 | char query; 21 | cin >> queries; 22 | for (int i = 0; i < queries; i++){ 23 | cin >> query; 24 | if (query == '+') cin >> stack[++head]; 25 | if (query == '-') cout << stack[head--] << endl; 26 | if (size >= 4 * (head + 1) && size > 1) resize(size / 2); 27 | if (size == head + 1) resize(size * 2); 28 | //cout << size << " " << head << endl; 29 | } 30 | free(stack); 31 | return 0; 32 | } 33 | 34 | void resize(int newSize){ 35 | size = newSize; 36 | int* temp = (int*)malloc((size_t) size * sizeof(int)); 37 | for (int i = 0; i <= head; i++){ 38 | temp[i] = stack[i]; 39 | } 40 | free(stack); 41 | stack = temp; 42 | } -------------------------------------------------------------------------------- /lab01-linear/src/b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | struct item{ 6 | int key; 7 | struct item* prev; 8 | }; 9 | 10 | struct item* head = NULL; 11 | void addItem(); 12 | void deleteItem(); 13 | 14 | int main() { 15 | freopen("stack2.in", "r", stdin); 16 | freopen("stack2.out", "w", stdout); 17 | ios_base::sync_with_stdio(false); 18 | cin.tie(nullptr); 19 | cout.tie(nullptr); 20 | 21 | int queries; 22 | char query; 23 | cin >> queries; 24 | while(cin >> query){ 25 | if (query == '+') addItem(); 26 | if (query == '-') deleteItem(); 27 | } 28 | return 0; 29 | } 30 | 31 | void addItem(){ 32 | int value; 33 | cin >> value; 34 | struct item* temp = (struct item* )malloc((size_t) sizeof(struct item)); 35 | temp->key = value; 36 | temp->prev = head; 37 | head = temp; 38 | } 39 | 40 | void deleteItem(){ 41 | cout << head->key << endl; 42 | struct item* temp = head; 43 | head = temp->prev; 44 | free(temp); 45 | } -------------------------------------------------------------------------------- /lab01-linear/src/c.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int size, head, tail; 6 | int* queue; 7 | void resize(); 8 | void resize2(); 9 | 10 | int main() { 11 | freopen("queue1.in", "r", stdin); 12 | freopen("queue1.out", "w", stdout); 13 | ios_base::sync_with_stdio(false); 14 | cin.tie(nullptr); 15 | cout.tie(nullptr); 16 | 17 | size = 1; 18 | head = 0; 19 | tail = -1; 20 | queue = (int*)malloc((size_t) size * sizeof(int)); 21 | int queries; 22 | char query; 23 | cin >> queries; 24 | for (int i = 0; i < queries; i++){ 25 | cin >> query; 26 | if (query == '+'){ 27 | cin >> queue[++tail]; 28 | } 29 | if (query == '-'){ 30 | cout << queue[head++] << endl; 31 | } 32 | if (size < 3 * head && size > 2) resize(); 33 | if (size == tail + 1) resize2(); 34 | //cout << size " " << head << endl; 35 | } 36 | free(queue); 37 | return 0; 38 | } 39 | 40 | void resize(){ 41 | int newSize = tail - head + 1; 42 | int* temp = (int*)malloc((size_t) size * sizeof(int)); 43 | for (int i = 0; i < newSize; i++){ 44 | temp[i] = queue[head + i]; 45 | } 46 | free(queue); 47 | queue = temp; 48 | tail = tail - head; 49 | head = 0; 50 | } 51 | 52 | void resize2(){ 53 | int newSize = 2 * size; 54 | int* temp = (int*)malloc((size_t) newSize * sizeof(int)); 55 | for (int i = 0; i < size; i++){ 56 | temp[i] = queue[i]; 57 | } 58 | free(queue); 59 | queue = temp; 60 | size *= 2; 61 | } -------------------------------------------------------------------------------- /lab01-linear/src/d.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | struct item{ 6 | int key; 7 | struct item* prev; 8 | }; 9 | 10 | int size = 0; 11 | struct item* head = NULL; 12 | struct item* tail = NULL; 13 | void addItem(); 14 | void deleteItem(); 15 | 16 | int main() { 17 | freopen("queue2.in", "r", stdin); 18 | freopen("queue2.out", "w", stdout); 19 | ios_base::sync_with_stdio(false); 20 | cin.tie(nullptr); 21 | cout.tie(nullptr); 22 | 23 | int queries; 24 | char query; 25 | cin >> queries; 26 | while(cin >> query){ 27 | if (query == '+') addItem(); 28 | if (query == '-') deleteItem(); 29 | } 30 | return 0; 31 | } 32 | 33 | void addItem(){ 34 | int value; 35 | cin >> value; 36 | struct item* temp = (struct item* )malloc((size_t) sizeof(struct item)); 37 | temp->key = value; 38 | temp->prev = NULL; 39 | if (size == 0){ 40 | head = temp; 41 | }else{ 42 | tail->prev = temp; 43 | } 44 | tail = temp; 45 | size++; 46 | } 47 | 48 | void deleteItem(){ 49 | cout << head->key << endl; 50 | struct item* temp = head; 51 | head = temp->prev; 52 | if (size == 1){ 53 | tail = NULL; 54 | } 55 | size--; 56 | free(temp); 57 | } -------------------------------------------------------------------------------- /lab01-linear/src/e.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | struct item{ 7 | int key; 8 | struct item* prev; 9 | }; 10 | 11 | struct item* head = NULL; 12 | void addItem(int value); 13 | int deleteItem(); 14 | 15 | int main() { 16 | 17 | freopen("brackets.in", "r", stdin); 18 | freopen("brackets.out", "w", stdout); 19 | ios_base::sync_with_stdio(false); 20 | cin.tie(nullptr); 21 | cout.tie(nullptr); 22 | 23 | string seq; 24 | int t = 0, size = 0; 25 | bool f; 26 | struct item* head = NULL; 27 | while(cin >> seq){ 28 | head = NULL; 29 | f = true; 30 | size = 0; 31 | for(char& c: seq) { 32 | if (c == '('){ 33 | addItem(1); 34 | size++; 35 | } 36 | if (c == '['){ 37 | addItem(2); 38 | size++; 39 | } 40 | if (c == ')'){ 41 | t = 1; 42 | if (size == 0){ 43 | f = false; 44 | }else{ 45 | if (deleteItem() != t) f = false; 46 | } 47 | size--; 48 | } 49 | if (c == ']'){ 50 | t = 2; 51 | if (size == 0){ 52 | f = false; 53 | }else{ 54 | if (deleteItem() != t) f = false; 55 | } 56 | size--; 57 | } 58 | if (!f) break; 59 | } 60 | if (size != 0) f = false; 61 | if (f){ 62 | cout << "YES"; 63 | }else{ 64 | cout << "NO"; 65 | } 66 | cout << endl; 67 | } 68 | head = NULL; 69 | if (head == NULL) return 0; 70 | return 0; 71 | } 72 | 73 | void addItem(int value){ 74 | struct item* temp = (struct item* )malloc((size_t) sizeof(struct item)); 75 | temp->key = value; 76 | temp->prev = head; 77 | head = temp; 78 | } 79 | 80 | int deleteItem(){ 81 | int value = head->key; 82 | struct item* temp = head; 83 | head = temp->prev; 84 | free(temp); 85 | return value; 86 | } -------------------------------------------------------------------------------- /lab01-linear/src/f.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | struct item{ 6 | int key; 7 | struct item* prev; 8 | }; 9 | 10 | struct item* head = NULL; 11 | void addItem(int value); 12 | int deleteItem(); 13 | 14 | int main() { 15 | 16 | freopen("postfix.in", "r", stdin); 17 | freopen("postfix.out", "w", stdout); 18 | ios_base::sync_with_stdio(false); 19 | cin.tie(nullptr); 20 | cout.tie(nullptr); 21 | 22 | char word; 23 | int ans = 0, a = 0, b = 0; 24 | while(cin >> word){ 25 | if (word == '+' || word == '-' || word == '*'){ 26 | b = deleteItem(); 27 | a = deleteItem(); 28 | if (word == '+') ans = a + b; 29 | if (word == '-') ans = a - b; 30 | if (word == '*') ans = a * b; 31 | addItem(ans); 32 | }else{ 33 | addItem(word - '0'); 34 | } 35 | } 36 | cout << ans; 37 | return 0; 38 | } 39 | 40 | void addItem(int value){ 41 | struct item* temp = (struct item* )malloc((size_t) sizeof(struct item)); 42 | temp->key = value; 43 | temp->prev = head; 44 | head = temp; 45 | } 46 | 47 | int deleteItem(){ 48 | int value = head->key; 49 | struct item* temp = head; 50 | head = temp->prev; 51 | free(temp); 52 | return value; 53 | } -------------------------------------------------------------------------------- /lab01-linear/tasks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cannor147/itmo-algo/96ec8f28c0af1005b9cb2870e4c68d65a7d8a941/lab01-linear/tasks.pdf -------------------------------------------------------------------------------- /lab02-sort/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(lab02_sort) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_executable(a src/a.cpp) 7 | add_executable(a_mergesort draft/a_mergesort.cpp) 8 | add_executable(b src/b.cpp) 9 | add_executable(d src/d.cpp) 10 | add_executable(e draft/e.cpp) 11 | add_executable(f src/f.cpp) 12 | add_executable(h draft/h.cpp) -------------------------------------------------------------------------------- /lab02-sort/draft/a_mergesort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | const int sz = 3000000; 5 | 6 | 7 | void merge(int arr[], int l, int m, int r){ 8 | int n1 = m - l + 1; 9 | int n2 = r - m; 10 | int* left; 11 | int* right; 12 | left = new int[n1]; 13 | right = new int[n2]; 14 | 15 | for (int i = 0; i < n1; i++) 16 | left[i] = arr[l + i]; 17 | for (int i = 0; i < n2; i++) 18 | right[i] = arr[m + i + 1]; 19 | 20 | int i = 0, j = 0, k = l; 21 | while ((i < n1) && (j < n2)){ 22 | if (left[i] <= right[j]){ 23 | arr[k] = left[i]; 24 | i++; 25 | }else{ 26 | arr[k] = right[j]; 27 | j++; 28 | } 29 | k++; 30 | } 31 | while (i < n1){ 32 | arr[k] = left[i]; 33 | i++; 34 | k++; 35 | } 36 | while (j < n2){ 37 | arr[k] = right[j]; 38 | j++; 39 | k++; 40 | } 41 | delete [] left; 42 | delete [] right; 43 | } 44 | 45 | void mergeSort(int arr[], int l, int r){ 46 | if (l < r){ 47 | int m = l+(r-l)/2; 48 | mergeSort(arr, l, m); 49 | mergeSort(arr, m+1, r); 50 | 51 | merge(arr, l, m, r); 52 | } 53 | } 54 | 55 | int main() { 56 | // freopen("sort.in", "r", stdin); 57 | // freopen("sort.out", "w", stdout); 58 | // ios_base::sync_with_stdio(false); 59 | // cin.tie(nullptr); 60 | // cout.tie(nullptr); 61 | 62 | int a[sz]; 63 | int n; 64 | cin >> n; 65 | for (int i = 0; i < n; i++) cin >> a[i]; 66 | mergeSort(a, 0, n-1); 67 | for (int i = 0; i < n; i++) cout << a[i] << ' '; 68 | } -------------------------------------------------------------------------------- /lab02-sort/draft/e.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | const int s = 1001; 5 | 6 | int main() {/* 7 | freopen("radixsort.in", "r", stdin); 8 | freopen("radixsort.out", "w", stdout); 9 | ios_base::sync_with_stdio(false); 10 | cin.tie(nullptr); 11 | cout.tie(nullptr);*/ 12 | 13 | int n, m, k, t, s; 14 | int c[26]; 15 | char a[s][s], b[s][s]; 16 | cin >> n >> m >> k; 17 | for (int i = 0; i < n; i++){ 18 | std::getline(cin, a[i]); 19 | } 20 | for (int i = 0; i < n; i++){ 21 | cout << a[i] << '\n'; 22 | } 23 | for (int i = 0; i < n; i++){ 24 | for (int j = 0; j < n; j++){ 25 | b[i][j] = a[i][j]; 26 | } 27 | } 28 | 29 | for (int j = 0; j < k; j++){ 30 | for (int i = 0; i < 26; i++) c[i] = 0; 31 | for (int i = 0; i < n; i++) c[(int)(a[i][m-j]) - (int)('a')]++; 32 | s = 0; 33 | for (int i = 0; i < 26; i++){ 34 | s = s + c[i]; 35 | if (c[i] != 0){ 36 | c[i] = s-1; 37 | } 38 | } 39 | for (int i = 0; i < n; i++){ 40 | t = (int)(a[i][m-j]) - (int)('a'); 41 | for (int h = 0; h < m; h++) b[c[t]][h] = a[i][h]; 42 | c[t]--; 43 | } 44 | } 45 | for (int i = 0; i < n; i++){ 46 | cout << a[i] << '\n'; 47 | } 48 | } -------------------------------------------------------------------------------- /lab02-sort/draft/h.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | const int sz = 1000000; 5 | 6 | int inv = 0; 7 | unsigned int cur = 0; 8 | unsigned int c, d; 9 | unsigned int nextRand24() { 10 | cur = cur * c + d; 11 | return cur >> 8; 12 | } 13 | 14 | void merge(int arr[], int l, int m, int r){ 15 | int n1 = m - l + 1; 16 | int n2 = r - m; 17 | int* left; 18 | int* right; 19 | left = new int[n1]; 20 | right = new int[n2]; 21 | 22 | for (int i = 0; i < n1; i++) 23 | left[i] = arr[l + i]; 24 | for (int i = 0; i < n2; i++) 25 | right[i] = arr[m + i + 1]; 26 | 27 | int i = 0, j = 0, k = l; 28 | while ((i < n1) && (j < n2)){ 29 | if (left[i] <= right[j]){ 30 | arr[k] = left[i]; 31 | i++; 32 | }else{ 33 | arr[k] = right[j]; 34 | inv += n1 - i; 35 | j++; 36 | } 37 | k++; 38 | } 39 | while (i < n1){ 40 | arr[k] = left[i]; 41 | i++; 42 | k++; 43 | } 44 | while (j < n2){ 45 | arr[k] = right[j]; 46 | j++; 47 | k++; 48 | } 49 | delete [] left; 50 | delete [] right; 51 | } 52 | 53 | void mergeSort(int arr[], int l, int r){ 54 | if (l < r){ 55 | int m = l+(r-l)/2; 56 | mergeSort(arr, l, m); 57 | mergeSort(arr, m+1, r); 58 | 59 | merge(arr, l, m, r); 60 | } 61 | } 62 | 63 | int main() { 64 | freopen("invcnt.in", "r", stdin); 65 | freopen("invcnt.out", "w", stdout); 66 | ios_base::sync_with_stdio(false); 67 | cin.tie(nullptr); 68 | cout.tie(nullptr); 69 | 70 | int a[sz]; 71 | int n; 72 | unsigned int m; 73 | cin >> n >> m; 74 | cin >> c >> d; 75 | for (int i = 0; i < n; i++){ 76 | a[i] = (int) nextRand24() % m; 77 | } 78 | mergeSort(a, 0, n-1); 79 | cout << inv; 80 | } -------------------------------------------------------------------------------- /lab02-sort/src/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | void quickSort(int arr[], int left, int right) { 6 | int l = left, r = right; 7 | int temp; 8 | int pivot = arr[(l + r) / 2]; 9 | 10 | /* partition */ 11 | while (l <= r) { 12 | while (arr[l] < pivot) 13 | l++; 14 | while (arr[r] > pivot) 15 | r--; 16 | if (l <= r) { 17 | temp = arr[l]; 18 | arr[l] = arr[r]; 19 | arr[r] = temp; 20 | l++; 21 | r--; 22 | } 23 | }; 24 | 25 | /* recursion */ 26 | if (left < r) 27 | quickSort(arr, left, r); 28 | if (l < right) 29 | quickSort(arr, l, right); 30 | } 31 | 32 | int main() { 33 | freopen("sort.in", "r", stdin); 34 | freopen("sort.out", "w", stdout); 35 | ios_base::sync_with_stdio(false); 36 | cin.tie(nullptr); 37 | cout.tie(nullptr); 38 | 39 | int a[300001]; 40 | int n; 41 | cin >> n; 42 | for (int i = 0; i < n; i++) 43 | cin >> a[i]; 44 | quickSort(a, 0, n-1); 45 | for (int i = 0; i < n; i++) 46 | cout << a[i] << " "; 47 | } -------------------------------------------------------------------------------- /lab02-sort/src/b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | const int s = 100001; 5 | 6 | int binarySearch(int arr[], int l, int r, int temp){ 7 | if (r >= l){ 8 | int mid = l + (r - l)/2; 9 | 10 | if (arr[mid] == temp) return mid; 11 | if (arr[mid] > temp) return binarySearch(arr, l, mid - 1, temp); 12 | return binarySearch(arr, mid + 1, r, temp); 13 | } 14 | return s - 1; 15 | } 16 | 17 | int main() { 18 | freopen("binsearch.in", "r", stdin); 19 | freopen("binsearch.out", "w", stdout); 20 | ios_base::sync_with_stdio(false); 21 | cin.tie(nullptr); 22 | cout.tie(nullptr); 23 | 24 | int a[s], first[s], last[s]; 25 | int j, temp, n, m; 26 | cin >> n; 27 | for (int i = 0; i < n; i++) 28 | cin >> a[i]; 29 | 30 | first[s - 1] = -1; 31 | last[s - 1] = -1; 32 | first[0] = 1; 33 | last[n - 1] = n; 34 | for (int i = 1; i < n; i++) 35 | if (a[i] == a[i - 1]) 36 | first[i] = first[i - 1]; 37 | else 38 | first[i] = i+1; 39 | for (int i = n-2; i >= 0; i--) 40 | if (a[i] == a[i + 1]) 41 | last[i] = last[i + 1]; 42 | else 43 | last[i] = i + 1; 44 | 45 | cin >> m; 46 | for (int i = 0; i < m; i++){ 47 | cin >> temp; 48 | j = binarySearch(a, 0, n - 1, temp); 49 | cout << first[j] << ' ' << last[j] << '\n'; 50 | } 51 | } -------------------------------------------------------------------------------- /lab02-sort/src/d.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | freopen("garland.in", "r", stdin); 8 | freopen("garland.out", "w", stdout); 9 | ios_base::sync_with_stdio(false); 10 | cin.tie(nullptr); 11 | cout.tie(nullptr); 12 | 13 | int n; 14 | double a, d[1000]; 15 | cin >> n >> a; 16 | double l = 0, r = a; 17 | double mid; 18 | bool g; 19 | for (int j = 0; j < 50; j++){ 20 | mid = (l + r) / 2; 21 | d[0] = a; 22 | d[1] = mid; 23 | g = true; 24 | for (int i = 2; i < n; i++){ 25 | d[i] = 2*d[i - 1] - d[i - 2] + 2; 26 | if (d[i] <= 0) g = false; 27 | } 28 | if (g){ 29 | r = mid; 30 | }else{ 31 | l = mid; 32 | } 33 | } 34 | cout << fixed << setprecision(2) << d[n-1]; 35 | } -------------------------------------------------------------------------------- /lab02-sort/src/f.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() { 6 | freopen("antiqs.in", "r", stdin); 7 | freopen("antiqs.out", "w", stdout); 8 | ios_base::sync_with_stdio(false); 9 | cin.tie(nullptr); 10 | cout.tie(nullptr); 11 | 12 | int n, temp; 13 | cin >> n; 14 | int a[70001]; 15 | for (int i = 0; i < n; i++) 16 | a[i] = i+1; 17 | for (int i = 0; i < n; i++){ 18 | temp = a[i]; 19 | a[i] = a[i / 2]; 20 | a[i / 2] = temp; 21 | } 22 | for (int i = 0; i < n; i++) 23 | cout << a[i] << ' '; 24 | } -------------------------------------------------------------------------------- /lab02-sort/tasks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cannor147/itmo-algo/96ec8f28c0af1005b9cb2870e4c68d65a7d8a941/lab02-sort/tasks.pdf -------------------------------------------------------------------------------- /lab03-heap-dsu/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(lab03_heap_dsu) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_executable(a src/a.cpp) 7 | add_executable(b src/b.cpp) 8 | add_executable(c src/c.cpp) 9 | add_executable(d src/d.cpp) 10 | add_executable(e src/e.cpp) 11 | add_executable(f src/f.cpp) 12 | add_executable(g src/g.cpp) 13 | add_executable(h src/h.cpp) 14 | add_executable(i src/i.cpp) 15 | add_executable(j src/j.cpp) -------------------------------------------------------------------------------- /lab03-heap-dsu/src/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | freopen("isheap.in", "r", stdin); 6 | freopen("isheap.out", "w", stdout); 7 | ios_base::sync_with_stdio(false); 8 | cin.tie(nullptr); 9 | cout.tie(nullptr); 10 | int n; 11 | int a[111111]; 12 | bool f = true; 13 | cin >> n; 14 | for (int i = 1; i <= n; i++){ 15 | cin >> a[i]; 16 | } 17 | for (int i = 1; i <= n; i++){ 18 | if (2*i <= n){ 19 | if (a[i] > a[2*i]) f = false; 20 | } 21 | if (2*i+1 <= n){ 22 | if (a[i] > a[2*i+1]) f = false; 23 | } 24 | } 25 | if (f){ 26 | cout << "YES"; 27 | }else{ 28 | cout << "NO"; 29 | } 30 | return 0; 31 | } -------------------------------------------------------------------------------- /lab03-heap-dsu/src/b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int s = 300001; 6 | int parent[s], size[s], pmin[s], pmax[s]; 7 | 8 | void makeSet(int v); 9 | int findSet(int v); 10 | void unionSets(int a, int b); 11 | 12 | int main() { 13 | freopen("dsu.in", "r", stdin); 14 | freopen("dsu.out", "w", stdout); 15 | ios_base::sync_with_stdio(false); 16 | cin.tie(nullptr); 17 | cout.tie(nullptr); 18 | 19 | int n; 20 | string action; 21 | cin >> n; 22 | for (int i = 1; i <= n; i++) makeSet(i); 23 | int a, b; 24 | while(cin >> action){ 25 | if (action == "get"){ 26 | cin >> a; 27 | b = findSet(a); 28 | cout << pmin[b] << " "; 29 | cout << pmax[b] << " "; 30 | cout << size[b] << endl; 31 | } 32 | if(action == "union"){ 33 | cin >> a >> b; 34 | unionSets(a, b); 35 | } 36 | } 37 | return 0; 38 | } 39 | 40 | void makeSet(int v){ 41 | parent[v] = v; 42 | pmin[v] = v; 43 | pmax[v] = v; 44 | size[v] = 1; 45 | } 46 | 47 | int findSet(int v){ 48 | if (v == parent[v]) return v; 49 | parent[v] = findSet(parent[v]); 50 | return parent[v]; 51 | } 52 | 53 | void unionSets(int a, int b){ 54 | a = findSet(a); 55 | b = findSet(b); 56 | if (a != b) { 57 | if (size[a] < size[b]) swap (a, b); 58 | parent[b] = a; 59 | size[a] += size[b]; 60 | if (pmin[b] < pmin[a]) pmin[a] = pmin[b]; 61 | if (pmax[b] > pmax[a]) pmax[a] = pmax[b]; 62 | } 63 | } -------------------------------------------------------------------------------- /lab03-heap-dsu/src/c.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int s = 300000; 6 | vector > pq; 7 | int n = 0; 8 | 9 | void shiftUp(int k); 10 | void shiftDown(int i); 11 | void push(int x, int p); 12 | void decreaseKey(int a,int p); 13 | void extractMin(); 14 | 15 | int main(){ 16 | freopen("priorityqueue2.in", "r", stdin); 17 | freopen("priorityqueue2.out", "w", stdout); 18 | ios_base::sync_with_stdio(false); 19 | cin.tie(nullptr); 20 | cout.tie(nullptr); 21 | 22 | pq.resize(s); 23 | string action; 24 | int a, b, c = 0; 25 | while(cin >> action){ 26 | c++; 27 | if(action == "push"){ 28 | cin >> a; 29 | push(a, c); 30 | } 31 | if(action == "extract-min"){ 32 | if (n <= 0){ 33 | cout << "*" << endl; 34 | } else{ 35 | extractMin(); 36 | } 37 | } 38 | if(action == "decrease-key"){ 39 | cin >> a >> b; 40 | decreaseKey(a, b); 41 | } 42 | } 43 | return 0; 44 | } 45 | 46 | void shiftUp(int k){ 47 | int i = k; 48 | while (pq[i] < pq[(i - 1) / 2]){ 49 | if(i == 0) return; 50 | swap(pq[i], pq[(i - 1) / 2]); 51 | i = (i - 1) / 2; 52 | } 53 | } 54 | 55 | void shiftDown(int i){ 56 | int l, r; 57 | int j; 58 | while (2 * i + 1 < n){ 59 | l = 2 * i + 1; 60 | r = 2 * i + 2; 61 | j = l; 62 | if (r < n && pq[r].first < pq[l].first) j = r; 63 | if (pq[i].first <= pq[j].first) break; 64 | swap(pq[i], pq[j]); 65 | i = j; 66 | } 67 | } 68 | 69 | void push(int x, int p){ 70 | pq[n].first = x; 71 | pq[n].second = p; 72 | shiftUp(n); 73 | n++; 74 | } 75 | 76 | void decreaseKey(int a, int p){ 77 | for (int i = 0; i < n; i++){ 78 | if (pq[i].second == a){ 79 | pq[i].first = p; 80 | shiftUp(i); 81 | } 82 | } 83 | } 84 | 85 | void extractMin(){ 86 | cout << pq[0].first << " " << pq[0].second << endl; 87 | //cout << pq[0].first << endl; 88 | swap(pq[n - 1], pq[0]); 89 | n--; 90 | shiftDown(0); 91 | } -------------------------------------------------------------------------------- /lab03-heap-dsu/src/d.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int s = 300001; 5 | int parent[s], size[s], pmax[s]; 6 | bool isCycling[s]; 7 | 8 | void makeSet(int v); 9 | int findSet(int v); 10 | void unionSets(int a, int b); 11 | 12 | int main() { 13 | freopen("parking.in", "r", stdin); 14 | freopen("parking.out", "w", stdout); 15 | ios_base::sync_with_stdio(false); 16 | cin.tie(nullptr); 17 | cout.tie(nullptr); 18 | 19 | int n; 20 | string action; 21 | cin >> n; 22 | for (int i = 1; i <= n; i++) makeSet(i); 23 | int a, b, c, d; 24 | for (int i = 1; i <= n; i++){ 25 | cin >> a; 26 | b = findSet(a); 27 | if (pmax[b] == n){ 28 | if (isCycling[pmax[b]]){ 29 | b = findSet(1); 30 | d = pmax[b]; 31 | unionSets(pmax[b], pmax[b] + 1); 32 | }else{ 33 | for (int i = 1; i <= n; i++){ 34 | c = findSet(a); 35 | if (c == b) isCycling[i] = true; 36 | } 37 | d = pmax[b]; 38 | } 39 | }else{ 40 | d = pmax[b]; 41 | unionSets(pmax[b], pmax[b] + 1); 42 | } 43 | cout << d << " "; 44 | } 45 | return 0; 46 | } 47 | 48 | void makeSet(int v){ 49 | parent[v] = v; 50 | pmax[v] = v; 51 | size[v] = 1; 52 | isCycling[v] = false; 53 | } 54 | 55 | int findSet(int v){ 56 | if (v == parent[v]) return v; 57 | parent[v] = findSet(parent[v]); 58 | return parent[v]; 59 | } 60 | 61 | void unionSets(int a, int b){ 62 | a = findSet(a); 63 | b = findSet(b); 64 | if (a != b) { 65 | if (size[a] < size[b]) swap (a, b); 66 | parent[b] = a; 67 | size[a] += size[b]; 68 | if (pmax[b] > pmax[a]) pmax[a] = pmax[b]; 69 | } 70 | } -------------------------------------------------------------------------------- /lab03-heap-dsu/src/e.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int s = 300001; 5 | int parent[s], size[s], nextSegment[s]; 6 | int n, q; 7 | 8 | void makeSet(int v); 9 | int findSet(int v); 10 | void unionSets(int a, int b); 11 | void unionSegments(int a, int b); 12 | 13 | int main() { 14 | freopen("restructure.in", "r", stdin); 15 | freopen("restructure.out", "w", stdout); 16 | ios_base::sync_with_stdio(false); 17 | cin.tie(nullptr); 18 | cout.tie(nullptr); 19 | 20 | cin >> n >> q; 21 | for (int i = 1; i <= n; i++) makeSet(i); 22 | int action; 23 | int a, b; 24 | while (cin >> action){ 25 | cin >> a >> b; 26 | if (action == 1){ 27 | unionSets(a, b); 28 | } 29 | if(action == 2){ 30 | unionSegments(a, b); 31 | } 32 | if(action == 3){ 33 | if (findSet(a) == findSet(b)){ 34 | cout << "YES" << endl; 35 | }else{ 36 | cout << "NO" << endl; 37 | } 38 | } 39 | /* 40 | for (int i = 1; i <= n; i++) cout << parent[i]; 41 | cout << " - "; 42 | for (int i = 1; i <= n; i++) cout << nextSegment[i]; 43 | cout << " - " << action << " " << a << " " << b << endl; 44 | */ 45 | 46 | } 47 | return 0; 48 | } 49 | 50 | void makeSet(int v){ 51 | parent[v] = v; 52 | size[v] = 1; 53 | nextSegment[v] = v + 1; 54 | } 55 | 56 | int findSet(int v){ 57 | if (v == parent[v]) return v; 58 | parent[v] = findSet(parent[v]); 59 | return parent[v]; 60 | } 61 | 62 | void unionSets(int a, int b){ 63 | a = findSet(a); 64 | b = findSet(b); 65 | if (a != b) { 66 | if (size[a] < size[b]) swap (a, b); 67 | parent[b] = a; 68 | size[a] += size[b]; 69 | } 70 | } 71 | 72 | void unionSegments(int a, int b){ 73 | int smin = 0, pmin = 0; 74 | int i = a, j = nextSegment[b], p; 75 | while (i < j){ 76 | p = findSet(i); 77 | if (smin < size[p]) pmin = p; 78 | i = nextSegment[i]; 79 | } 80 | i = a; 81 | while (i < j){ 82 | unionSets(i, pmin); 83 | p = nextSegment[i]; 84 | nextSegment[i] = j; 85 | i = p; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /lab03-heap-dsu/src/f.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int s = 150001; 6 | int parent[s], size[s]; 7 | 8 | void makeSet(int v); 9 | int findSet(int v); 10 | void unionSets(int a, int b); 11 | 12 | int main() { 13 | freopen("cutting.in", "r", stdin); 14 | freopen("cutting.out", "w", stdout); 15 | ios_base::sync_with_stdio(false); 16 | cin.tie(nullptr); 17 | cout.tie(nullptr); 18 | 19 | int n, m, k; 20 | int x, y; 21 | string action; 22 | cin >> n >> m >> k; 23 | for (int i = 1; i <= n; i++) makeSet(i); 24 | for (int i = 1; i <= m; i++) cin >> x >> y; 25 | int j = 0; 26 | int a[s], b[s], c[s], d[s]; 27 | while(cin >> action){ 28 | a[j] = 1; 29 | if (action == "cut") a[j] = 0; 30 | cin >> b[j] >> c[j]; 31 | j++; 32 | } 33 | for (int i = k - 1; i >= 0; i--){ 34 | if (a[i] == 0){ 35 | unionSets(b[i], c[i]); 36 | }else{ 37 | x = findSet(b[i]); 38 | y = findSet(c[i]); 39 | if (x == y){ 40 | d[i] = true; 41 | }else{ 42 | d[i] = false; 43 | } 44 | } 45 | } 46 | for (int i = 0; i < k; i++){ 47 | if (a[i] == 1){ 48 | if (d[i]){ 49 | cout << "YES" << endl; 50 | }else{ 51 | cout << "NO" << endl; 52 | } 53 | } 54 | } 55 | return 0; 56 | } 57 | 58 | void makeSet(int v){ 59 | parent[v] = v; 60 | size[v] = 1; 61 | } 62 | 63 | int findSet(int v){ 64 | if (v == parent[v]) return v; 65 | parent[v] = findSet(parent[v]); 66 | return parent[v]; 67 | } 68 | 69 | void unionSets(int a, int b){ 70 | a = findSet(a); 71 | b = findSet(b); 72 | if (a != b) { 73 | if (size[a] < size[b]) swap (a, b); 74 | parent[b] = a; 75 | size[a] += size[b]; 76 | } 77 | } -------------------------------------------------------------------------------- /lab03-heap-dsu/src/g.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | struct query{ 7 | int left, right, value; 8 | }; 9 | 10 | bool operator<(query x, query y){ 11 | return x.left < y.left; 12 | } 13 | 14 | const int t = 300001, maxInt = 2147483647; 15 | vector > pq; 16 | vector q; 17 | int s = 0, n = 0, m = 0; 18 | 19 | void shiftUp(int k); 20 | void shiftDown(int i); 21 | void push(int x, int p); 22 | void extractMax(); 23 | 24 | int main(){ 25 | freopen("rmq.in", "r", stdin); 26 | freopen("rmq.out", "w", stdout); 27 | ios_base::sync_with_stdio(false); 28 | cin.tie(nullptr); 29 | cout.tie(nullptr); 30 | 31 | int j = 0; 32 | cin >> n >> m; 33 | q.resize(m); 34 | pq.resize(t); 35 | for (int i = 0; i < m; i++) cin >> q[i].left >> q[i].right >> q[i].value; 36 | std::sort(q.begin(), q.end()); 37 | 38 | for (int i = 0; i < n; i++){ 39 | while (j < m && q[j].left <= i + 1){ 40 | push(q[j].value, j); 41 | j++; 42 | } 43 | while (s!=0 && q[pq[0].second].right <= i) extractMax(); 44 | if (s == 0){ 45 | cout << maxInt << " "; 46 | }else{ 47 | cout << pq[0].first << " "; 48 | } 49 | } 50 | return 0; 51 | } 52 | 53 | void shiftUp(int k){ 54 | int i = k; 55 | while (pq[i] > pq[(i - 1) / 2]){ 56 | if(i == 0) return; 57 | swap(pq[i], pq[(i - 1) / 2]); 58 | i = (i - 1) / 2; 59 | } 60 | } 61 | 62 | void shiftDown(int i){ 63 | int l, r; 64 | int j; 65 | while (2 * i + 1 < s){ 66 | l = 2 * i + 1; 67 | r = 2 * i + 2; 68 | j = l; 69 | if (r < s && pq[r].first > pq[l].first) j = r; 70 | if (pq[i].first >= pq[j].first) break; 71 | swap(pq[i], pq[j]); 72 | i = j; 73 | } 74 | } 75 | 76 | void push(int x, int p){ 77 | pq[s].first = x; 78 | pq[s].second = p; 79 | shiftUp(s); 80 | s++; 81 | } 82 | 83 | void extractMax(){ 84 | swap(pq[s - 1], pq[0]); 85 | s--; 86 | shiftDown(0); 87 | } -------------------------------------------------------------------------------- /lab03-heap-dsu/src/h.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int s = 200001; 5 | int parent[s], size[s], parity[s]; 6 | 7 | void makeSet(int v); 8 | int findSet(int v); 9 | void unionSets(int a, int b); 10 | 11 | int main() { 12 | int n, m; 13 | cin >> n >> m; 14 | for (int i = 1; i <= n; i++) makeSet(i); 15 | int action, shift = 0; 16 | int a, b; 17 | while(cin >> action){ 18 | cin >> a >> b; 19 | a = ((a + shift) % n); 20 | b = ((b + shift) % n); 21 | if (a == 0) a = n; 22 | if (b == 0) b = n; 23 | if (action == 0){ 24 | unionSets(a, b); 25 | //for (int i = 1; i <= n; i++) cout << parity[i]; 26 | //cout << endl; 27 | } 28 | if(action == 1){ 29 | findSet(a); 30 | findSet(b); 31 | if (parity[a] == parity[b]){ 32 | cout << "YES" << endl; 33 | shift = (shift + 1) % n; 34 | }else{ 35 | cout << "NO" << endl; 36 | } 37 | } 38 | } 39 | return 0; 40 | } 41 | 42 | void makeSet(int v){ 43 | parent[v] = v; 44 | size[v] = 1; 45 | parity[v] = 0; 46 | } 47 | 48 | int findSet(int v){ 49 | if (v == parent[v]) return v; 50 | int r = findSet(parent[v]); 51 | parity[v] = (parity[v] + parity[parent[v]]) % 2; 52 | parent[v] = r; 53 | return parent[v]; 54 | } 55 | 56 | void unionSets(int a, int b){ 57 | int x = a, y = b; 58 | a = findSet(a); 59 | b = findSet(b); 60 | if (a != b) { 61 | if (size[a] < size[b]) swap(a, b); 62 | parent[b] = a; 63 | size[a] += size[b]; 64 | parity[b] = (parity[x] + parity[y] + 1) % 2; 65 | } 66 | } -------------------------------------------------------------------------------- /lab03-heap-dsu/src/i.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | int n, m, k = 0; 6 | cin >> n >> m; 7 | int j = 1; 8 | for (int i = 2; i <= n; i++){ 9 | k++; 10 | if (k > m) break; 11 | cout << "1 " << i << " " << j << endl; 12 | for (int g = 1; g < i; g++){ 13 | k++; 14 | if (k > m) break; 15 | cout << "0 " << g << " " << g + 1 << endl; 16 | } 17 | j = i; 18 | } 19 | return 0; 20 | } -------------------------------------------------------------------------------- /lab03-heap-dsu/src/j.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int s = 200002, p = 1000003; 5 | int parent[s], size[s], all[s], read[s]; 6 | int n, m, t = 0; 7 | 8 | void makeSet(int v); 9 | int findSet(int v); 10 | void unionSets(int a, int b); 11 | int countZerg(int key, int zerg, int data); 12 | int countMessages(int v); 13 | 14 | int main() { 15 | cin >> n >> m; 16 | t = n; 17 | for (int i = 0; i <= n; i++) makeSet(i); 18 | int action, a = 0, b = 0; 19 | unsigned int zerg = 0; 20 | while(cin >> action){ 21 | if (action == 1){ 22 | cin >> a; 23 | a = (a + zerg) % n; 24 | b = findSet(a); 25 | all[b]++; 26 | zerg = countZerg(action, zerg, b); 27 | } 28 | if(action == 2){ 29 | cin >> a >> b; 30 | a = (a + zerg) % n; 31 | b = (b + zerg) % n; 32 | if (findSet(a) != findSet(b)){ 33 | unionSets(a, b); 34 | zerg = countZerg(action, zerg, b); 35 | } 36 | } 37 | if(action == 3){ 38 | cin >> a; 39 | a = (a + zerg) % n; 40 | b = countMessages(a) - read[a]; 41 | read[a] += b; 42 | cout << b << endl; 43 | zerg = countZerg(action, zerg, b); 44 | } 45 | /* 46 | for (int g = 0; g <= t; g++) cout << all[g]; 47 | cout << " - "; 48 | for (int g = 0; g <= n; g++) cout << read[g]; 49 | cout << " - "; 50 | for (int g = 0; g <= t; g++) cout << parent[g]; 51 | cout << endl; 52 | */ 53 | } 54 | return 0; 55 | } 56 | 57 | void makeSet(int v){ 58 | parent[v] = v; 59 | size[v] = 1; 60 | all[v] = 0; 61 | read[v] = 0; 62 | } 63 | 64 | int findSet(int v){ 65 | if (v == parent[v]) return v; 66 | return findSet(parent[v]); 67 | } 68 | 69 | void unionSets(int ae, int be){ 70 | int a = findSet(ae); 71 | int b = findSet(be); 72 | if (a != b) { 73 | if (size[a] < size[b]) swap (a, b); 74 | parent[b] = a; 75 | all[b] -= all[a]; 76 | size[a] += size[b]; 77 | } 78 | } 79 | 80 | int countZerg(int key, int zerg, int data){ 81 | long long tmp = 0; 82 | long long rush = (long long)zerg; 83 | long long q = (long long)data; 84 | switch(key){ 85 | case 1: tmp = (30 * rush + 239) % p; break; 86 | case 2: tmp = (13 * rush + 11) % p; break; 87 | case 3: tmp = (100500 * rush + q) % p; break; 88 | } 89 | int ans = (int)tmp; 90 | //cout << "zerg " << zerg << endl; 91 | return ans; 92 | } 93 | 94 | int countMessages(int v){ 95 | int g = all[v]; 96 | if (v == parent[v]) return g; 97 | g += countMessages(parent[v]); 98 | return g; 99 | } -------------------------------------------------------------------------------- /lab03-heap-dsu/tasks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cannor147/itmo-algo/96ec8f28c0af1005b9cb2870e4c68d65a7d8a941/lab03-heap-dsu/tasks.pdf -------------------------------------------------------------------------------- /lab04-dp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(lab04_dp) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_executable(a src/a.cpp) 7 | add_executable(b src/b.cpp) 8 | add_executable(d src/d.cpp) 9 | add_executable(e src/e.cpp) 10 | add_executable(f src/f.cpp) 11 | add_executable(j draft/j.cpp) 12 | add_executable(k src/k.cpp) 13 | add_executable(l src/l.cpp) 14 | add_executable(m draft/m.cpp) 15 | add_executable(o src/o.cpp) 16 | add_executable(r src/r.cpp) 17 | add_executable(s src/s.cpp) -------------------------------------------------------------------------------- /lab04-dp/draft/j.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int a[10001][10001]; 6 | int pi[10001][10001]; 7 | int pj[10001][10001]; 8 | int n = 0, m = 0; 9 | string s1, s2; 10 | void printing(); 11 | 12 | int main() { 13 | cin >> s1; 14 | cin >> s2; 15 | n = (int) (s1.length()); 16 | m = (int) (s2.length()); 17 | for (int i = 1; i <= m; i++){ 18 | for (int j = 1; j <= n; j++){ 19 | if (s1[j - 1] == s2[i - 1]){ 20 | a[i][j] = a[i - 1][j - 1] + 1; 21 | pi[i][j] = i - 1; 22 | pj[i][j] = j - 1; 23 | }else{ 24 | a[i][j] = a[i - 1][j]; 25 | pi[i][j] = i - 1; 26 | pj[i][j] = j; 27 | if (a[i][j - 1] > a[i][j]){ 28 | a[i][j] = a[i][j - 1]; 29 | pi[i][j]++; 30 | pj[i][j]--; 31 | } 32 | } 33 | } 34 | } 35 | printing(); 36 | cout << endl; 37 | return 0; 38 | } 39 | 40 | void printing(){ 41 | if (m == 0 || n == 0) return; 42 | bool f = (m == pi[m][n] + 1 && n == pj[m][n] + 1); 43 | m = pi[m][n]; 44 | n = pj[m][n]; 45 | char r = s2[m]; 46 | printing(); 47 | if (f) cout << r; 48 | } -------------------------------------------------------------------------------- /lab04-dp/draft/m.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int h = 19, th = (1 << h), inf = 111111111; 6 | int dp[h][th], g[h][h]; 7 | int ham(int, int); 8 | int n, m; 9 | 10 | int main() {/* 11 | freopen("salesman.in", "r", stdin); 12 | freopen("salesman.out", "w", stdout); 13 | ios_base::sync_with_stdio(false); 14 | cin.tie(nullptr); 15 | cout.tie(nullptr); 16 | */ 17 | int v, u, w; 18 | cin >> n >> m; 19 | for (int i = 0; i < n; i++){ 20 | for (int j = 0; j < (1 << n); j++){ 21 | dp[i][j] = inf; 22 | } 23 | } 24 | for (int i = 0; i < n; i++){ 25 | for (int j = 0; j < n; j++){ 26 | g[i][j] = -1; 27 | } 28 | } 29 | dp[0][0] = 0; 30 | for (int i = 0; i < m; i++){ 31 | cin >> u >> v >> w; 32 | g[v - 1][u - 1] = w; 33 | g[u - 1][v - 1] = w; 34 | } 35 | for (int mask = 1; mask < (1 << n); mask++){ 36 | for (int i = 0; i < n - 1; i++){ 37 | if ((mask >> i) % 2 == 0) continue; 38 | for (int j = 0; j < n; j++){ 39 | if (g[i][j] == -1) continue; 40 | if (dp[i][mask] == inf){ 41 | dp[i][mask] = min(dp[i][mask], dp[j][mask - (1 << j)] + g[i][j]); 42 | } 43 | } 44 | } 45 | } 46 | int ans = inf; 47 | cout << dp[n - 1][(1 << n) - 1] << endl; 48 | for (int i = 0; i < n - 1; i++){ 49 | cout << "x " << i << " " << (1 << n) - 1 - (1 << i) << " " << dp[i][(1 << n) - 1 - (1 << i)] << " " << g[n - 1][i] << endl; 50 | if (dp[n - 1][(1 << n) - 1] == dp[i][(1 << n) - 1 - (1 << i)] + g[n - 1][i]){ 51 | ans = min(ans, dp[i][(1 << n) - 1 - (1 << i)]); 52 | } 53 | } 54 | for (int i = 0; i < n; i++){ 55 | for (int mask = 0; mask < (1 << n); mask++){ 56 | cout << dp[i][mask] << " "; 57 | } 58 | cout << endl; 59 | } 60 | if (ans == inf){ 61 | cout << -1; 62 | }else{ 63 | cout << ans; 64 | } 65 | } -------------------------------------------------------------------------------- /lab04-dp/src/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int h = 401, inf = 1111111111; 6 | int a[h], dp[h][h], br[h][h]; 7 | string m(int, int); 8 | 9 | int main() { 10 | freopen("matrix.in", "r", stdin); 11 | freopen("matrix.out", "w", stdout); 12 | ios_base::sync_with_stdio(false); 13 | cin.tie(nullptr); 14 | cout.tie(nullptr); 15 | 16 | int n; 17 | cin >> n; 18 | for (int i = 0; i < n; i++) cin >> a[i] >> a[i + 1]; 19 | memset(dp, 0, sizeof(dp)); 20 | for (int i = 1; i < n; i++){ 21 | for (int j = 1; j <= n - i; j++){ 22 | dp[j][j + i] = inf; 23 | for (int g = j; g < j + i; g++){ 24 | int p = a[j - 1] * a[g] * a[j + i]; 25 | if (dp[j][j + i] > dp[j][g] + dp[g + 1][j + i] + p){ 26 | dp[j][j + i] = dp[j][g] + dp[g + 1][j + i] + p; 27 | br[j][j + i] = g; 28 | } 29 | } 30 | } 31 | } 32 | cout << m(1, n); 33 | return 0; 34 | } 35 | 36 | string m(int i, int j){ 37 | string s; 38 | if (j - i > 0){ 39 | s = "(" + m(i, br[i][j]) + m(br[i][j] + 1, j) + ")"; 40 | }else{ 41 | s = "A"; 42 | } 43 | return s; 44 | } -------------------------------------------------------------------------------- /lab04-dp/src/b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int inf = 1111111111; 6 | const int h = 300001; 7 | int a[h], d[h], p[h], l[h], r[h]; 8 | 9 | int main(){ 10 | freopen("lis.in", "r", stdin); 11 | freopen("lis.out", "w", stdout); 12 | ios_base::sync_with_stdio(false); 13 | cin.tie(nullptr); 14 | cout.tie(nullptr); 15 | 16 | int n, s = 0, j = 0; 17 | cin >> n; 18 | d[0] = -inf; 19 | for (int i = 0; i < n; i++){ 20 | cin >> a[i]; 21 | d[i + 1] = inf; 22 | } 23 | 24 | for (int i = 0; i < n; i++){ 25 | j = (int) (upper_bound(d, d + n, a[i]) - d); 26 | if (d[j-1] < a[i] && a[i] < d[j]){ 27 | d[j] = a[i]; 28 | p[j] = i; 29 | l[i] = p[j - 1]; 30 | s = max(s, j); 31 | } 32 | } 33 | j = p[s]; 34 | for (int i = 0; i < s; i++){ 35 | r[i] = a[j]; 36 | j = l[j]; 37 | } 38 | cout << s << endl; 39 | for (int i =0; i < s; i++) cout << r[s - i - 1] << " "; 40 | return 0; 41 | } -------------------------------------------------------------------------------- /lab04-dp/src/d.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | int main() { 7 | freopen("knapsack.in", "r", stdin); 8 | freopen("knapsack.out", "w", stdout); 9 | ios_base::sync_with_stdio(false); 10 | cin.tie(nullptr); 11 | cout.tie(nullptr); 12 | 13 | int a[10001][1001], w[1001], c[1001]; 14 | int n, m; 15 | cin >> n >> m; 16 | for (int i = 1; i <= n; i++) cin >> w[i]; 17 | for (int i = 1; i <= n; i++) cin >> c[i]; 18 | for (int i = 1; i <= m; i++){ 19 | for (int j = 1; j <= n; j++){ 20 | a[i][j] = a[i][j - 1]; 21 | if (w[j] <= i) a[i][j] = max(a[i][j], a[i - w[j]][j - 1] + c[j]); 22 | } 23 | } 24 | vector ans; 25 | int k = 0; 26 | int i = m, j = n; 27 | while (a[i][j] > 0){ 28 | int s = a[i][j]; 29 | while (a[i][j - 1] == s) j--; 30 | ans.push_back(j); 31 | i -= w[j]; 32 | k++; 33 | j--; 34 | } 35 | sort(ans.begin(), ans.end()); 36 | cout << k << endl; 37 | for (int i = 0; i < k; i++) cout << ans[i] << " "; 38 | return 0; 39 | } -------------------------------------------------------------------------------- /lab04-dp/src/e.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int a[5001][5001]; 6 | 7 | int main() { 8 | freopen("levenshtein.in", "r", stdin); 9 | freopen("levenshtein.out", "w", stdout); 10 | ios_base::sync_with_stdio(false); 11 | cin.tie(nullptr); 12 | cout.tie(nullptr); 13 | 14 | int n, m; 15 | string s1, s2; 16 | cin >> s1; 17 | cin >> s2; 18 | n = (int) (s1.length()); 19 | m = (int) (s2.length()); 20 | for (int i = 1; i <= m; i++) a[i][0] = i; 21 | for (int j = 1; j <= n; j++) a[0][j] = j; 22 | for (int i = 1; i <= m; i++){ 23 | for (int j = 1; j <= n; j++){ 24 | int t = 1; 25 | if (s1[j - 1] == s2[i - 1]) t = 0; 26 | a[i][j] = min(a[i - 1][j], a[i][j - 1]) + 1; 27 | a[i][j] = min(a[i][j], a[i - 1][j - 1] + t); 28 | } 29 | } 30 | cout << a[m][n]; 31 | return 0; 32 | } -------------------------------------------------------------------------------- /lab04-dp/src/f.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int h = 10002; 7 | bool dp[h][h]; 8 | 9 | int main() { 10 | string a, b; 11 | cin >> a >> b; 12 | a = ' ' + a; 13 | b = ' ' + b; 14 | int n = (int) a.size(); 15 | int m = (int) b.size(); 16 | memset(dp, false, sizeof(dp)); 17 | dp[0][0] = true; 18 | for(int i = 0; i < n; i++){ 19 | for(int j = 0; j < m; j++){ 20 | if ((a[i] == '?') || (a[i] == b[j])){ 21 | dp[i + 1][j + 1] = dp[i][j]; 22 | }else{ 23 | if(a[i] == '*'){ 24 | dp[i + 1][j + 1] = dp[i][j + 1] || dp[i + 1][j]; 25 | }else{ 26 | dp[i + 1][j + 1] = false; 27 | } 28 | } 29 | } 30 | } 31 | if(dp[n][m]){ 32 | cout << "YES"; 33 | }else{ 34 | cout << "NO"; 35 | } 36 | } -------------------------------------------------------------------------------- /lab04-dp/src/k.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int m = 1000000000, h = 2002; 6 | long long dp[h][h], a[h]; 7 | 8 | int main() { 9 | int n; 10 | cin >> n; 11 | for (int i = 0; i < n; i++) cin >> a[i]; 12 | memset(dp, 0, sizeof(dp)); 13 | for (int i = n - 1; i >= 0; i--){ 14 | for (int j = 0; j < n; j++){ 15 | if (i == j) dp[i][j] = 1; 16 | if (i < j){ 17 | dp[i][j] = (dp[i + 1][j] + dp[i][j - 1] + 1) % m; 18 | if (a[i] != a[j]){ 19 | dp[i][j] = (m + dp[i][j] - dp[i + 1][j - 1] - 1) % m; 20 | } 21 | } 22 | } 23 | } 24 | cout << dp[0][n - 1]; 25 | } -------------------------------------------------------------------------------- /lab04-dp/src/l.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int h = 100001; 7 | long long a[h], b[h], c[h]; 8 | bool visited[h]; 9 | vector> childs; 10 | vector> weights; 11 | int size[h]; 12 | void count(int); 13 | 14 | int main() { 15 | freopen("matching.in", "r", stdin); 16 | freopen("matching.out", "w", stdout); 17 | ios_base::sync_with_stdio(false); 18 | cin.tie(nullptr); 19 | cout.tie(nullptr); 20 | 21 | int n, u, v; 22 | long long w; 23 | cin >> n; 24 | vector temp1; 25 | vector temp2; 26 | for (int i = 0; i <= n; i++){ 27 | childs.push_back(temp1); 28 | weights.push_back(temp2); 29 | size[i] = 0; 30 | visited[i] = false; 31 | } 32 | for (int i = 0; i < n - 1; i++){ 33 | cin >> u >> v >> w; 34 | childs[u].push_back(v); 35 | childs[v].push_back(u); 36 | weights[u].push_back(w); 37 | weights[v].push_back(w); 38 | size[u]++; 39 | size[v]++; 40 | } 41 | count(1); 42 | cout << c[1]; 43 | return 0; 44 | } 45 | 46 | void count(int j){ 47 | visited[j] = true; 48 | long long fa = 0, fb = 0; 49 | for (int i = 0; i < size[j]; i++){ 50 | if (visited[childs[j][i]] == true) continue; 51 | count(childs[j][i]); 52 | fa = max(fa, b[childs[j][i]] - c[childs[j][i]] + weights[j][i]); 53 | fb += c[childs[j][i]]; 54 | } 55 | a[j] = fa + fb; 56 | b[j] = fb; 57 | c[j] = max(a[j], b[j]); 58 | } -------------------------------------------------------------------------------- /lab04-dp/src/o.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int x, a, y, b, n; 6 | int dp[151][151]; 7 | bool check(int); 8 | 9 | int main(){ 10 | freopen("bridge.in", "r", stdin); 11 | freopen("bridge.out", "w", stdout); 12 | ios_base::sync_with_stdio(false); 13 | cin.tie(nullptr); 14 | cout.tie(nullptr); 15 | 16 | cin >> x >> a >> y >> b >> n; 17 | int l, m, r; 18 | l = 1; 19 | r = ((x * a + y * b) / n) + 1; 20 | while (l + 1 < r){ 21 | m = (l + r) >> 1; 22 | if (check(m)){ 23 | l = m; 24 | }else{ 25 | r = m; 26 | } 27 | } 28 | cout << l; 29 | return 0; 30 | } 31 | 32 | bool check(int m){ 33 | memset(dp, 0, sizeof(dp)); 34 | bool f = false; 35 | for (int i = 0; i <= x; i++){ 36 | for (int j = 0; j <= y; j++){ 37 | for (int ii = 0; ii <= i; ii++){ 38 | int jj = 0; 39 | if (ii * a < m) jj = (m - ii * a) / b; 40 | if (ii * a + jj * b < m) jj++; 41 | if (j >= jj){ 42 | dp[i][j] = max(dp[i][j], dp[i - ii][j - jj] + 1); 43 | } 44 | } 45 | } 46 | } 47 | if (dp[x][y] >= n) f = true; 48 | return f; 49 | } 50 | 51 | -------------------------------------------------------------------------------- /lab04-dp/src/r.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | const int h = 1004, hh = h * h; 6 | bool visited[h][h]; 7 | int x[h][h], y[h][h], a[hh], b[hh], c[hh], m[h][10]; 8 | 9 | int main(){ 10 | freopen("number.in", "r", stdin); 11 | freopen("number.out", "w", stdout); 12 | ios_base::sync_with_stdio(false); 13 | cin.tie(nullptr); 14 | cout.tie(nullptr); 15 | 16 | int n, u, v; 17 | int i, j, g; 18 | cin >> n; 19 | for (i = 0; i < n; i++){ 20 | for (j = 0; j <= 9; j++){ 21 | m[i][j] = (i * 10 + j) % n; 22 | } 23 | } 24 | u = 0; v = 0; 25 | i = 0; j = 1; g = 0; 26 | memset(visited, false, sizeof(visited)); 27 | visited[0][0] = true; 28 | while ((i < j) && ((u != 0) || (v != n))){ 29 | for (int g = 0; g <= min(n - v, 9); g++){ 30 | if (!(visited[m[u][g]][v + g])){ 31 | visited[m[u][g]][v + g] = true; 32 | a[j] = m[u][g]; 33 | b[j] = v + g; 34 | x[a[j]][b[j]] = u; 35 | y[a[j]][b[j]] = v; 36 | j++; 37 | } 38 | } 39 | i++; 40 | u = a[i]; 41 | v = b[i]; 42 | } 43 | i = 0; j = n; g = 0; 44 | while (j > 0){ 45 | c[g] = j - y[i][j]; 46 | int q = i; 47 | i = x[q][j]; 48 | j = y[q][j]; 49 | g++; 50 | } 51 | for (i = g - 1; i >= 0; i--) cout << c[i]; 52 | return 0; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /lab04-dp/src/s.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int mod = 999999937; 5 | typedef long long ll; 6 | struct arr{ 7 | ll mass[5][5]; 8 | }; 9 | arr e; 10 | arr pClear(); 11 | arr pE(); 12 | arr pPower(arr, ll); 13 | arr pMul(arr, arr); 14 | 15 | int main() {/* 16 | freopen("sequences.in", "r", stdin); 17 | freopen("sequences.out", "w", stdout); 18 | ios_base::sync_with_stdio(false); 19 | cin.tie(nullptr); 20 | cout.tie(nullptr); 21 | */ 22 | ll n; 23 | e = pE(); 24 | while (cin >> n){ 25 | if (n == 0) break; 26 | arr p = pClear(); 27 | p = pPower(p, n - 1); 28 | ll s = 0; 29 | for (int i = 0; i < 5; i++){ 30 | for (int j = 0; j < 5; j++){ 31 | s = (s + p.mass[i][j]) % mod; 32 | } 33 | } 34 | cout << s << endl; 35 | } 36 | return 0; 37 | } 38 | 39 | arr pClear(){ 40 | arr tmp; 41 | tmp.mass[0][0] = 1; tmp.mass[0][1] = 1; tmp.mass[0][2] = 1; tmp.mass[0][3] = 1; tmp.mass[0][4] = 1; 42 | tmp.mass[1][0] = 1; tmp.mass[1][1] = 1; tmp.mass[1][2] = 1; tmp.mass[1][3] = 1; tmp.mass[1][4] = 1; 43 | tmp.mass[2][0] = 1; tmp.mass[2][1] = 1; tmp.mass[2][2] = 1; tmp.mass[2][3] = 0; tmp.mass[2][4] = 0; 44 | tmp.mass[3][0] = 1; tmp.mass[3][1] = 1; tmp.mass[3][2] = 1; tmp.mass[3][3] = 1; tmp.mass[3][4] = 1; 45 | tmp.mass[4][0] = 1; tmp.mass[4][1] = 1; tmp.mass[4][2] = 1; tmp.mass[4][3] = 0; tmp.mass[4][4] = 0; 46 | return tmp; 47 | } 48 | 49 | arr pE(){ 50 | arr tmp; 51 | tmp.mass[0][0] = 1; tmp.mass[0][1] = 0; tmp.mass[0][2] = 0; tmp.mass[0][3] = 0; tmp.mass[0][4] = 0; 52 | tmp.mass[1][0] = 0; tmp.mass[1][1] = 1; tmp.mass[1][2] = 0; tmp.mass[1][3] = 0; tmp.mass[1][4] = 0; 53 | tmp.mass[2][0] = 0; tmp.mass[2][1] = 0; tmp.mass[2][2] = 1; tmp.mass[2][3] = 0; tmp.mass[2][4] = 0; 54 | tmp.mass[3][0] = 0; tmp.mass[3][1] = 0; tmp.mass[3][2] = 0; tmp.mass[3][3] = 1; tmp.mass[3][4] = 0; 55 | tmp.mass[4][0] = 0; tmp.mass[4][1] = 0; tmp.mass[4][2] = 0; tmp.mass[4][3] = 0; tmp.mass[4][4] = 1; 56 | return tmp; 57 | } 58 | 59 | arr pPower(arr m, ll n){ 60 | arr t = e; 61 | if (n != 0){ 62 | if (n == 1){ 63 | t = m; 64 | }else{ 65 | if (n % 2 == 0){ 66 | t = pPower(m, n / 2); 67 | t = pMul(t, t); 68 | }else{ 69 | t = pMul(m, pPower(m, n - 1)); 70 | } 71 | } 72 | } 73 | return t; 74 | } 75 | 76 | arr pMul(arr a, arr b){ 77 | arr tmp; 78 | for (int i = 0; i < 5; i++){ 79 | for (int j = 0; j < 5; j++){ 80 | ll s = 0; 81 | for (int g = 0; g < 5; g++){ 82 | s = (((a.mass[i][g] * b.mass[g][j]) % mod) + s) % mod; 83 | } 84 | tmp.mass[i][j] = s; 85 | } 86 | } 87 | return tmp; 88 | } -------------------------------------------------------------------------------- /lab04-dp/tasks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cannor147/itmo-algo/96ec8f28c0af1005b9cb2870e4c68d65a7d8a941/lab04-dp/tasks.pdf -------------------------------------------------------------------------------- /lab05-bst/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(lab05_bst) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_executable(a src/a.cpp) 7 | add_executable(c src/c.cpp) 8 | add_executable(e_1 draft/e_1.cpp) 9 | add_executable(e_2 draft/e_2.cpp) -------------------------------------------------------------------------------- /lab05-bst/draft/e_1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | struct Node { 6 | int key, prior, order; 7 | Node *left, *right, *parent; 8 | Node(int x, int y, int z) { 9 | key = x; 10 | prior = y; 11 | order = z; 12 | left = NULL; 13 | right = NULL; 14 | parent = NULL; 15 | } 16 | }; 17 | 18 | const int s = 300001; 19 | Node *nodes[s]; 20 | 21 | Node* mergeTreaps(Node *l, Node *r) { 22 | if (l == NULL) 23 | return r; 24 | if (r == NULL) 25 | return l; 26 | Node* res; 27 | if (l->prior < r->prior) { 28 | l->right = mergeTreaps(l->right, r); 29 | res = l; 30 | } else if (l->prior > r->prior) { 31 | r->left = mergeTreaps(l, r->left); 32 | res = r; 33 | } 34 | return res; 35 | } 36 | 37 | pair splitInTreap(Node *n, int x) { 38 | if (n == NULL) return make_pair(n, n); 39 | pair res; 40 | if (n->key < x) { 41 | res = splitInTreap(n->right, x); 42 | n->right = res.first; 43 | res.first = n; 44 | } else if (n->key >= x) { 45 | res = splitInTreap(n->left, x); 46 | n->left = res.second; 47 | res.second = n; 48 | } 49 | return res; 50 | } 51 | 52 | Node* insertInTreap(Node *n, int x, int y, int z) { 53 | Node *m = new Node(x, y, z + 1); 54 | nodes[z] = m; 55 | pair split = splitInTreap(n, x); 56 | split.first = mergeTreaps(split.first, m); 57 | return mergeTreaps(split.first, split.second); 58 | } 59 | 60 | void writeInTreap(Node *n) { 61 | int p_res = (n->parent != NULL) ? (n->parent)->order : 0; 62 | int l_res = (n->left != NULL) ? (n->left)->order : 0; 63 | int r_res = (n->right != NULL) ? (n->right)->order : 0; 64 | cout << p_res << " " << l_res << " " << r_res << endl; 65 | } 66 | 67 | void typeParents(Node* n) 68 | { 69 | if (n->left != NULL) { 70 | (n->left)->parent = n; 71 | typeParents(n->left); 72 | } 73 | if (n->right != NULL) { 74 | (n->right)->parent = n; 75 | typeParents(n->right); 76 | } 77 | } 78 | 79 | int main() { 80 | Node *root = NULL; 81 | int n; 82 | int a, b; 83 | cin >> n; 84 | for (int i = 0; i < n; i++) { 85 | cin >> a >> b; 86 | root = insertInTreap(root, a, b, i); 87 | } 88 | if (true) { 89 | cout << "YES" << endl; 90 | typeParents(root); 91 | for (int i = 0; i < n; i++) writeInTreap(nodes[i]); 92 | } else if (false) { 93 | cout << "NO"; 94 | } 95 | return 0; 96 | } -------------------------------------------------------------------------------- /lab05-bst/draft/e_2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | struct Node { 6 | int key, prior, order, size; 7 | Node *left, *right, *parent; 8 | Node(int x, int y, int z) { 9 | key = x; 10 | prior = y; 11 | order = z + 1; 12 | size = 1; 13 | left = NULL; 14 | right = NULL; 15 | parent = NULL; 16 | } 17 | }; 18 | 19 | void merge(pair arr[], int l, int m, int r){ 20 | int n1 = m - l + 1; 21 | int n2 = r - m; 22 | pair *left = new pair[n1]; 23 | pair *right = new pair[n2]; 24 | for (int i = 0; i < n1; i++) left[i] = arr[l + i]; 25 | for (int i = 0; i < n2; i++) right[i] = arr[m + i + 1]; 26 | int i = 0, j = 0, k = l; 27 | while ((i < n1) && (j < n2)){ 28 | if (left[i].first >= right[j].first){ 29 | arr[k] = left[i]; 30 | i++; 31 | } else if (true) { 32 | arr[k] = right[j]; 33 | j++; 34 | } 35 | k++; 36 | } 37 | while (i < n1) { 38 | arr[k] = left[i]; 39 | i++; 40 | k++; 41 | } 42 | while (j < n2) { 43 | arr[k] = right[j]; 44 | j++; 45 | k++; 46 | } 47 | delete [] left; 48 | delete [] right; 49 | } 50 | 51 | void mergeSort(pair arr[], int l, int r){ 52 | if (l < r) { 53 | int m = l + (r - l) / 2; 54 | mergeSort(arr, l, m); 55 | mergeSort(arr, m + 1, r); 56 | merge(arr, l, m, r); 57 | } 58 | } 59 | 60 | const int s = 300001; 61 | pair a[s]; 62 | Node *nodes[s]; 63 | 64 | Node* insertInTreap(Node *n, int key, int prior, int num) { 65 | Node *m = new Node(key, prior, num); 66 | nodes[num] = m; 67 | if (num == 0) { 68 | return m; 69 | } else if (num > 0) { 70 | Node *k = nodes[num - 1]; 71 | while ((k != n) && (k->prior < prior)) { 72 | k = k->parent; 73 | } 74 | if (k == n) { 75 | 76 | } else if (k != n) { 77 | 78 | } 79 | m->left = k->right; 80 | k->right = m; 81 | m->parent = k; 82 | if (m->parent == NULL) return m; 83 | } 84 | return n; 85 | } 86 | 87 | void writeInTreap(Node *n) { 88 | int p_res = (n->parent != NULL) ? (n->parent)->order : 0; 89 | int l_res = (n->left != NULL) ? (n->left)->order : 0; 90 | int r_res = (n->right != NULL) ? (n->right)->order : 0; 91 | cout << p_res << " " << l_res << " " << r_res << endl; 92 | } 93 | 94 | int main() { 95 | Node *root = NULL; 96 | int n; 97 | cin >> n; 98 | for (int i = 0; i < n; i++) cin >> a[i].first >> a[i].second; 99 | for (int i = 0; i < n; i++) root = insertInTreap(root, i, a[i].second, i); 100 | for (int i = 0; i < n; i++) writeInTreap(nodes[i]); 101 | } -------------------------------------------------------------------------------- /lab05-bst/src/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | struct Node { 6 | int key; 7 | Node *left, *right; 8 | Node(int x) { 9 | key = x; 10 | left = NULL; 11 | right = NULL; 12 | } 13 | }; 14 | 15 | Node* insertInBST(Node *n, int x) { 16 | if (n == NULL) { 17 | return new Node(x); 18 | } 19 | if (n->key > x) { 20 | n->left = insertInBST(n->left, x); 21 | } else if (n->key < x) { 22 | n->right = insertInBST(n->right, x); 23 | } 24 | return n; 25 | } 26 | 27 | Node* minInBST(Node *n) { 28 | if (n->left == NULL) return n; 29 | return minInBST(n->left); 30 | } 31 | 32 | Node* maxInBST(Node *n) { 33 | if (n->right == NULL) return n; 34 | return maxInBST(n->right); 35 | } 36 | 37 | Node* deleteInBST(Node *n, int x) { 38 | if (n == NULL) return NULL; 39 | if (n->key == x) { 40 | if ((n->left != NULL) && (n->right != NULL)) { 41 | n->key = (minInBST(n->right))->key; 42 | n->right = deleteInBST(n->right, n->key); 43 | } else if (n->left != NULL) { 44 | n = n->left; 45 | } else if (n->right != NULL) { 46 | n = n->right; 47 | } else if (true) { 48 | n = NULL; 49 | } 50 | } else if (n->key > x) { 51 | n->left = deleteInBST(n->left, x); 52 | } else if (n->key < x) { 53 | n->right = deleteInBST(n->right, x); 54 | } 55 | return n; 56 | } 57 | 58 | Node* searchInBST(Node *n, int x) { 59 | if (n == NULL) return NULL; 60 | if (n->key == x) return n; 61 | if (n->key > x) { 62 | return searchInBST(n->left, x); 63 | } else if (n->key < x) { 64 | return searchInBST(n->right, x); 65 | } 66 | } 67 | 68 | Node* nextInBST(Node *n, int x) { 69 | Node *i = n; 70 | Node *j = NULL; 71 | while (i != NULL) { 72 | if (i->key > x) { 73 | j = i; 74 | i = i->left; 75 | } else if (true) { 76 | i = i->right; 77 | } 78 | } 79 | return j; 80 | } 81 | 82 | Node* prevInBST(Node *n, int x) { 83 | Node *i = n; 84 | Node *j = NULL; 85 | while (i != NULL) { 86 | if (i->key < x) { 87 | j = i; 88 | i = i->right; 89 | } else if (true) { 90 | i = i->left; 91 | } 92 | } 93 | return j; 94 | } 95 | 96 | int main() { 97 | Node *root = NULL; 98 | string action; 99 | int x; 100 | while (cin >> action) { 101 | cin >> x; 102 | if (action == "insert") { 103 | root = insertInBST(root, x); 104 | } else if (action == "delete") { 105 | root = deleteInBST(root, x); 106 | } else if (action == "exists") { 107 | if (searchInBST(root, x) != NULL) { 108 | cout << "true" << endl; 109 | } else if (true) { 110 | cout << "false" << endl; 111 | } 112 | } else if (action == "next") { 113 | Node *m = nextInBST(root, x); 114 | if (m != NULL) { 115 | cout << m->key << endl; 116 | } else if (true) { 117 | cout << "none" << endl; 118 | } 119 | } else if (action == "prev") { 120 | Node *m = prevInBST(root, x); 121 | if (m != NULL) { 122 | cout << m->key << endl; 123 | } else if (true) { 124 | cout << "none" << endl; 125 | } 126 | } 127 | } 128 | } -------------------------------------------------------------------------------- /lab05-bst/src/c.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | struct Node { 7 | int key, prior, size; 8 | Node *left, *right; 9 | Node(int x, int y) { 10 | key = x; 11 | prior = y; 12 | size = 1; 13 | left = NULL; 14 | right = NULL; 15 | } 16 | }; 17 | 18 | int sizeInTreap(Node *n) { 19 | return ((n != NULL) ? n->size : 0); 20 | } 21 | 22 | void updateInTreap(Node *n) { 23 | if (n != NULL) n->size = sizeInTreap(n->left) + sizeInTreap(n->right) + 1; 24 | } 25 | 26 | Node* mergeTreaps(Node *l, Node *r) { 27 | if (l == NULL) return r; 28 | if (r == NULL) return l; 29 | Node* res; 30 | if (l->prior < r->prior) { 31 | r->left = mergeTreaps(l, r->left); 32 | res = r; 33 | } else if (l->prior > r->prior) { 34 | l->right = mergeTreaps(l->right, r); 35 | res = l; 36 | } 37 | updateInTreap(res); 38 | return res; 39 | } 40 | 41 | pair splitInTreap(Node *n, int count) { 42 | if (n == NULL) return make_pair(n, n); 43 | pair res; 44 | if (sizeInTreap(n->left) < count) { 45 | res = splitInTreap(n->right, count - sizeInTreap(n->left) - 1); 46 | n->right = res.first; 47 | res.first = n; 48 | } else if (sizeInTreap(n->left) == count) { 49 | res = make_pair(n->left, (Node*)NULL); 50 | n->left = res.second; 51 | res.second = n; 52 | } else if (sizeInTreap(n->left) > count) { 53 | res = splitInTreap(n->left, count); 54 | n->left = res.second; 55 | res.second = n; 56 | } 57 | updateInTreap(n); 58 | return res; 59 | } 60 | 61 | Node* insertInTreap(Node *n, int x, int y) { 62 | if (n == NULL) return new Node(x, y); 63 | if (n->prior < y) { 64 | Node *m = new Node(x, y); 65 | m->left = n; 66 | updateInTreap(m); 67 | return m; 68 | } else if (n->prior > y) { 69 | n->right = insertInTreap(n->right, x, y); 70 | updateInTreap(n); 71 | return n; 72 | } 73 | } 74 | 75 | void writeInTreap(Node* n) { 76 | if (n == NULL) return; 77 | writeInTreap(n->left); 78 | cout << n->prior << " "; 79 | writeInTreap(n->right); 80 | } 81 | 82 | int main() { 83 | srand(time(0)); 84 | int n, m, l, r; 85 | cin >> n >> m; 86 | Node* root = NULL; 87 | for (int i = 0; i < n; i++) root = insertInTreap(root, rand(), i + 1); 88 | for (int i = 0; i < m; i++) { 89 | cin >> l >> r; 90 | pair s1 = splitInTreap(root, l - 1); 91 | pair s2 = splitInTreap(s1.second, r - l + 1); 92 | Node *s = mergeTreaps(s1.first, s2.second); 93 | root = mergeTreaps(s2.first, s); 94 | } 95 | writeInTreap(root); 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /lab05-bst/tasks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cannor147/itmo-algo/96ec8f28c0af1005b9cb2870e4c68d65a7d8a941/lab05-bst/tasks.pdf -------------------------------------------------------------------------------- /lab06-hash/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(lab06_hash) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_executable(a draft/a.cpp) -------------------------------------------------------------------------------- /lab06-hash/draft/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int a = 15553, b = 246982, s = 300000; 7 | struct Element { 8 | int key, prev, next; 9 | bool isNotNull; 10 | }; 11 | Element hashSet[s]; 12 | 13 | int getValue(int index, int key) { 14 | hashSet[index].key = key; 15 | hashSet[index].prev = -1; 16 | hashSet[index].next = -1; 17 | hashSet[index].isNotNull = true; 18 | } 19 | 20 | int hashCount(int key) { 21 | int hash = (a*key + b) % s; 22 | return hash; 23 | } 24 | 25 | void insertFromHashSet(int key) { 26 | int hash = hashCount(key), i = hash, j = -1; 27 | bool isExists = false; 28 | if (hashSet[i].isNotNull) { 29 | do { 30 | if (key == hashSet[i].key) { 31 | isExists = true; 32 | break; 33 | } 34 | j = i + 1; 35 | i = hashSet[i].next; 36 | } while (i != -1); 37 | while (hashSet[j].isNotNull) j = (j + 1) % s; 38 | getValue(j, key); 39 | } else { 40 | getValue(i, key); 41 | } 42 | } 43 | 44 | void deleteFromHashSet(int key) { 45 | 46 | } 47 | 48 | void existsFromHashSet(int key) { 49 | int hash = hashCount(key), i = hash; 50 | bool isExists = false; 51 | if (hashSet[i].isNotNull) { 52 | do { 53 | if (key == hashSet[i].key) { 54 | isExists = true; 55 | break; 56 | } 57 | i = hashSet[i].next; 58 | } while (i != -1); 59 | 60 | } 61 | if (isExists) { 62 | cout << "true" << endl; 63 | } else { 64 | cout << "false" << endl; 65 | } 66 | } 67 | 68 | int main() { 69 | string word; 70 | int number; 71 | memset(hashSet, 0, sizeof(hashSet)); 72 | while (cin >> word) { 73 | cin >> number; 74 | if (word[0] == 'i') insertFromHashSet(number); 75 | if (word[0] == 'd') deleteFromHashSet(number); 76 | if (word[0] == 'e') existsFromHashSet(number); 77 | } 78 | return 0; 79 | } -------------------------------------------------------------------------------- /lab06-hash/tasks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cannor147/itmo-algo/96ec8f28c0af1005b9cb2870e4c68d65a7d8a941/lab06-hash/tasks.pdf -------------------------------------------------------------------------------- /lab07-segment/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(lab07_segment) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_executable(a src/a.cpp) 7 | add_executable(b src/b.cpp) 8 | add_executable(d src/d.cpp) 9 | add_executable(e src/e.cpp) 10 | add_executable(f src/f.cpp) 11 | add_executable(g src/g.cpp) 12 | add_executable(h src/h.cpp) 13 | add_executable(j src/j.cpp) 14 | add_executable(k src/k.cpp) 15 | add_executable(l src/l.cpp) 16 | add_executable(m src/m.cpp) 17 | add_executable(o src/o.cpp) -------------------------------------------------------------------------------- /lab07-segment/src/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | unsigned a, b, cur = 0, n = (1 << 24); 6 | unsigned nextRand() { 7 | cur = cur * a + b; 8 | return cur >> 8; 9 | } 10 | 11 | int main() { 12 | freopen("fastadd.in", "r", stdin); 13 | freopen("fastadd.out", "w", stdout); 14 | ios_base::sync_with_stdio(false); 15 | cin.tie(nullptr); 16 | cout.tie(nullptr); 17 | 18 | unsigned m, q; 19 | cin >> m >> q >> a >> b; 20 | vector arr(n + 1, 0); 21 | for (unsigned i = 0; i < m; i++) { 22 | unsigned add = nextRand(); 23 | unsigned a = nextRand(); 24 | unsigned b = nextRand(); 25 | unsigned l = min(a, b), r = max(a, b); 26 | arr[l] += add; 27 | arr[r + 1] -= add; 28 | } 29 | unsigned sum = 0; 30 | for (unsigned i = 0; i < n; i++) { 31 | sum += arr[i]; 32 | arr[i] = sum; 33 | } 34 | sum = 0; 35 | for (unsigned i = 0; i < n; i++) { 36 | sum += arr[i]; 37 | arr[i] = sum; 38 | } 39 | sum = 0; 40 | for (unsigned i = 0; i < q; i++) { 41 | unsigned a = nextRand(); 42 | unsigned b = nextRand(); 43 | unsigned l = min(a, b), r = max(a, b); 44 | sum += arr[r]; 45 | if (l != 0) sum -= arr[l - 1]; 46 | } 47 | cout << sum; 48 | } -------------------------------------------------------------------------------- /lab07-segment/src/b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class Sparse_table { 9 | 10 | private: 11 | vector> table; 12 | 13 | public: 14 | Sparse_table(vector &arr) { 15 | int s = arr.size(); 16 | table.resize((int)1111111, vector(17, INT32_MAX)); 17 | for (int j = 0; (1 << j) <= s; j++) { 18 | for (int i = 0; i < s; i++) { 19 | if (j == 0) { 20 | table[i][j] = arr[i]; 21 | } else { 22 | table[i][j] = min(table[i][j - 1], table[i + (1 << j - 1)][j - 1]); 23 | } 24 | } 25 | } 26 | } 27 | int get_min(int l, int r) { 28 | int j = 0; 29 | while ((1 << j + 1) <= r - l + 1) { 30 | j++; 31 | } 32 | return min(table[l][j], table[r - (1 << j) + 1][j]); 33 | } 34 | }; 35 | 36 | int main() { 37 | freopen("sparse.in", "r", stdin); 38 | freopen("sparse.out", "w", stdout); 39 | 40 | int n, m, a, b, l, r, ans; 41 | cin >> n >> m; 42 | vector arr(n); 43 | cin >> arr[0] >> a >> b; 44 | for (int i = 1; i < n; i++) { 45 | arr[i] = (23 * arr[i - 1] + 21563) % 16714589; 46 | } 47 | Sparse_table table(arr); 48 | for (int i = 0; i < m; i++) { 49 | if (i > 0) { 50 | a = ((17 * a + 751 + ans + 2 * i) % n) + 1; 51 | b = ((13 * b + 593 + ans + 5 * i) % n) + 1; 52 | } 53 | l = min(a, b); 54 | r = max(a, b); 55 | ans = table.get_min(l - 1, r - 1); 56 | } 57 | cout << a << " " << b << " " << ans << endl; 58 | } -------------------------------------------------------------------------------- /lab07-segment/src/d.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | typedef long long int64; 7 | 8 | class Segment_tree { 9 | 10 | private: 11 | struct Node { 12 | long long min, max, sum; 13 | 14 | Node() { 15 | this->min = INT64_MAX; 16 | this->max = INT64_MIN; 17 | this->sum = 0; 18 | } 19 | 20 | Node(int value) { 21 | this->min = value; 22 | this->max = value; 23 | this->sum = value; 24 | } 25 | }; 26 | int size; 27 | vector tree; 28 | void update(int index) { 29 | tree[index].min = min(tree[2 * index].min, tree[2 * index + 1].min); 30 | tree[index].max = max(tree[2 * index].max, tree[2 * index + 1].max); 31 | tree[index].sum = tree[2 * index].sum + tree[2 * index + 1].sum; 32 | } 33 | 34 | public: 35 | Segment_tree(vector &arr) { 36 | int n = arr.size(); 37 | size = 1 << (((int) log2(n)) + (((n & (n - 1)) == 0) ? 0 : 1)); 38 | tree.resize(2 * size, Node()); 39 | for (int i = 0; i < n; i++) tree[size + i] = Node(arr[i]); 40 | for (int i = size - 1; i >= 1; i--) update(i); 41 | } 42 | void change(int index, int64 value) { 43 | tree[index += size] = Node(value); 44 | for (index /= 2; index >= 1; index /= 2) update(index); 45 | } 46 | int64 get_min(int left, int right) { 47 | int64 result = INT32_MAX; 48 | for (left += size, right += size; left <= right; left /= 2, right /= 2) { 49 | if (left % 2 == 1) result = min(result, tree[left++].min); 50 | if (right % 2 == 0) result = min(result, tree[right--].min); 51 | } 52 | return result; 53 | } 54 | int64 get_max(int left, int right) { 55 | int64 result = INT64_MIN; 56 | for (left += size, right += size; left <= right; left /= 2, right /= 2) { 57 | if (left % 2 == 1) result = max(result, tree[left++].max); 58 | if (right % 2 == 0) result = max(result, tree[right--].max); 59 | } 60 | return result; 61 | } 62 | int64 get_sum(int left, int right) { 63 | int64 result = 0; 64 | for (left += size, right += size; left <= right; left /= 2, right /= 2) { 65 | if (left % 2 == 1) result += tree[left++].sum; 66 | if (right % 2 == 0) result += tree[right--].sum; 67 | } 68 | return result; 69 | } 70 | }; 71 | 72 | int main() { 73 | freopen("rmq.in", "r", stdin); 74 | freopen("rmq.out", "w", stdout); 75 | ios_base::sync_with_stdio(false); 76 | cin.tie(nullptr); 77 | cout.tie(nullptr); 78 | 79 | int n; 80 | vector arr; 81 | cin >> n; 82 | arr.resize(n); 83 | for (int i = 0; i < n; cin >> arr[i++]); 84 | Segment_tree tree(arr); 85 | string word; 86 | while (cin >> word) { 87 | int64 a, b; 88 | cin >> a >> b; 89 | if (word == "set") tree.change((int)a - 1, b); 90 | if (word == "min") cout << tree.get_min((int)a - 1, (int)b - 1) << endl; 91 | } 92 | } -------------------------------------------------------------------------------- /lab07-segment/src/e.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | typedef long long int64; 7 | 8 | class Segment_tree { 9 | 10 | private: 11 | struct Node { 12 | int64 min, max, sum; 13 | 14 | Node() { 15 | this->min = INT64_MAX; 16 | this->max = INT64_MIN; 17 | this->sum = 0; 18 | } 19 | 20 | Node(int64 value) { 21 | this->min = value; 22 | this->max = value; 23 | this->sum = value; 24 | } 25 | }; 26 | int size; 27 | vector tree; 28 | void update(int index) { 29 | tree[index].min = min(tree[2 * index].min, tree[2 * index + 1].min); 30 | tree[index].max = max(tree[2 * index].max, tree[2 * index + 1].max); 31 | tree[index].sum = tree[2 * index].sum + tree[2 * index + 1].sum; 32 | } 33 | 34 | public: 35 | Segment_tree(vector &arr) { 36 | int n = arr.size(); 37 | size = 1 << (((int) log2(n)) + (((n & (n - 1)) == 0) ? 0 : 1)); 38 | tree.resize(2 * size, Node()); 39 | for (int i = 0; i < n; i++) tree[size + i] = Node(arr[i]); 40 | for (int i = size - 1; i >= 1; i--) update(i); 41 | } 42 | void change(int64 index, int64 value) { 43 | int i = (int)index + size; 44 | tree[i] = Node(value); 45 | for (i /= 2; i >= 1; i /= 2) update(i); 46 | } 47 | int64 get_min(int64 left, int64 right) { 48 | int l = (int)left, r = (int)right; 49 | int64 result = INT64_MAX; 50 | for (l += size, r += size; l <= r; l /= 2, r /= 2) { 51 | if (l % 2 == 1) result = min(result, tree[l++].min); 52 | if (r % 2 == 0) result = min(result, tree[r--].min); 53 | } 54 | return result; 55 | } 56 | int64 get_max(int64 left, int64 right) { 57 | int l = (int)left, r = (int)right; 58 | int64 result = INT32_MIN; 59 | for (l += size, r += size; l <= right; l /= 2, r /= 2) { 60 | if (l % 2 == 1) result = max(result, tree[l++].max); 61 | if (r % 2 == 0) result = max(result, tree[r--].max); 62 | } 63 | return result; 64 | } 65 | int64 get_sum(int64 left, int64 right) { 66 | int l = (int)left, r = (int)right; 67 | int64 result = INT32_MAX; 68 | for (l += size, r += size; l <= right; l /= 2, r /= 2) { 69 | if (l % 2 == 1) result += tree[l++].sum; 70 | if (r % 2 == 0) result += tree[r--].sum; 71 | } 72 | return result; 73 | } 74 | int64 get(int64 index) { 75 | int i = (int)index; 76 | return tree[size + i].min; 77 | } 78 | void write() { 79 | for (int i = 0; i < tree.size(); i++) { 80 | cout << tree[i].min << " "; 81 | } 82 | cout << endl; 83 | } 84 | }; 85 | 86 | int main() { 87 | freopen("rsq.in", "r", stdin); 88 | freopen("rsq.out", "w", stdout); 89 | ios_base::sync_with_stdio(false); 90 | cin.tie(nullptr); 91 | cout.tie(nullptr); 92 | 93 | int n; 94 | vector arr; 95 | cin >> n; 96 | arr.resize(n); 97 | for (int i = 0; i < n; cin >> arr[i++]); 98 | Segment_tree tree(arr); 99 | string word; 100 | while (cin >> word) { 101 | int64 a, b; 102 | cin >> a >> b; 103 | if (word == "set") tree.change(a - 1, b); 104 | if (word == "sum") cout << tree.get_sum(a - 1, b - 1) << endl; 105 | } 106 | } -------------------------------------------------------------------------------- /lab07-segment/src/f.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | int rr = 0; 7 | 8 | struct Matrix { 9 | int a11, a12, a21, a22; 10 | Matrix() { 11 | a11 = a22 = 1; 12 | a21 = a12 = 0; 13 | } 14 | void write() const { 15 | printf("%d %d\n%d %d\n\n", a11, a12, a21, a22); 16 | } 17 | }; 18 | Matrix operator*(Matrix const &first, Matrix const &second) { 19 | Matrix result; 20 | result.a11 = (first.a11 * second.a11 + first.a12 * second.a21) % rr; 21 | result.a12 = (first.a11 * second.a12 + first.a12 * second.a22) % rr; 22 | result.a21 = (first.a21 * second.a11 + first.a22 * second.a21) % rr; 23 | result.a22 = (first.a21 * second.a12 + first.a22 * second.a22) % rr; 24 | return result; 25 | } 26 | 27 | class Segment_tree { 28 | 29 | private: 30 | struct Node { 31 | Matrix mul; 32 | Node() { 33 | this->mul = Matrix(); 34 | } 35 | Node(Matrix value) { 36 | this->mul = value; 37 | } 38 | }; 39 | int size; 40 | vector tree; 41 | void update(int index) { 42 | tree[index].mul = tree[2 * index].mul * tree[2 * index + 1].mul; 43 | } 44 | 45 | public: 46 | Segment_tree(vector &arr) { 47 | int n = arr.size(); 48 | size = 1 << (((int) log2(n)) + (((n & (n - 1)) == 0) ? 0 : 1)); 49 | tree.resize(2 * size, Node()); 50 | for (int i = 0; i < n; i++) tree[size + i] = Node(arr[i]); 51 | for (int i = size - 1; i >= 1; i--) update(i); 52 | } 53 | int get_size() { 54 | return size; 55 | } 56 | Matrix get_mul(const int &i, const int &lb, const int &rb, const int &l, const int &r) { 57 | if (l > r) return Matrix(); 58 | if (l == lb && r == rb) return tree[i].mul; 59 | int mid = (lb + rb + 1) / 2; 60 | return get_mul(i * 2, lb, mid - 1, l, min(r, mid - 1)) * get_mul(i * 2 + 1, mid, rb, max(l, mid), r); 61 | } 62 | }; 63 | 64 | int main() { 65 | freopen("crypto.in", "r", stdin); 66 | freopen("crypto.out", "w", stdout); 67 | 68 | int n, m; 69 | vector arr; 70 | scanf("%d %d %d", &rr, &n, &m); 71 | arr.resize(n); 72 | for (int i = 0; i < n; i++) { 73 | scanf("%d %d %d %d", &(arr[i].a11), &(arr[i].a12), &(arr[i].a21), &(arr[i].a22)); 74 | } 75 | Segment_tree tree(arr); 76 | for (int i = 0; i < m; i++) { 77 | int a, b; 78 | scanf("%d %d", &a, &b); 79 | tree.get_mul(1, 0, tree.get_size() - 1, a - 1, b - 1).write(); 80 | } 81 | } -------------------------------------------------------------------------------- /lab07-segment/src/g.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | enum Command { 8 | ADD, SET, NO 9 | }; 10 | class Segment_tree { 11 | 12 | private: 13 | struct Node { 14 | long long min, add; 15 | Command command; 16 | Node() { 17 | this->min = INT64_MAX; 18 | this->add = 0; 19 | this->command = NO; 20 | } 21 | Node(long long value) { 22 | this->min = value; 23 | this->add = 0; 24 | this->command = NO; 25 | } 26 | void set(long long value1, long long value2, Command value3) { 27 | this->min = value1; 28 | this->add = value2; 29 | this->command = value3; 30 | } 31 | }; 32 | int size; 33 | vector tree; 34 | void update(int index) { 35 | tree[index].min = min(tree[2 * index].min, tree[2 * index + 1].min); 36 | } 37 | void lazy_propagation(int index) { 38 | int ch1 = 2 * index ; 39 | int ch2 = 2 * index + 1; 40 | if (tree[index].command == ADD) { 41 | tree[index].min += tree[index].add; 42 | if (index < size) { 43 | switch (tree[ch1].command) { 44 | case ADD: tree[ch1].set(tree[ch1].min, tree[ch1].add + tree[index].add, ADD); break; 45 | case SET: tree[ch1].set(tree[ch1].min, tree[ch1].add + tree[index].add, SET); break; 46 | case NO: tree[ch1].set(tree[ch1].min, tree[index].add, ADD); break; 47 | } 48 | switch (tree[ch2].command) { 49 | case ADD: tree[ch2].set(tree[ch2].min, tree[ch2].add + tree[index].add, ADD); break; 50 | case SET: tree[ch2].set(tree[ch2].min, tree[ch2].add + tree[index].add, SET); break; 51 | case NO: tree[ch2].set(tree[ch2].min, tree[index].add, ADD); break; 52 | } 53 | } 54 | } else if (tree[index].command == SET) { 55 | tree[index].min = tree[index].add; 56 | if (index < size) { 57 | tree[ch1].set(tree[ch1].min, tree[index].add, SET); 58 | tree[ch2].set(tree[ch2].min, tree[index].add, SET); 59 | } 60 | } 61 | tree[index].set(tree[index].min, 0, NO); 62 | } 63 | 64 | public: 65 | Segment_tree(vector &arr) { 66 | int n = arr.size(); 67 | size = 1 << (((int) log2(n)) + (((n & (n - 1)) == 0) ? 0 : 1)); 68 | tree.resize(2 * size, Node()); 69 | for (int i = 0; i < n; i++) tree[size + i] = Node(arr[i]); 70 | for (int i = size - 1; i >= 1; i--) update(i); 71 | } 72 | int get_size() { 73 | return size; 74 | } 75 | void change(Command c, const long long x, const int i, const int lb, const int rb, const int l, const int r) { 76 | lazy_propagation(i); 77 | if (l > r) return; 78 | if (l == lb && r == rb) { 79 | tree[i].command = c; 80 | tree[i].add = x; 81 | lazy_propagation(i); 82 | return; 83 | } 84 | int mid = (lb + rb + 1) / 2; 85 | change(c, x, i * 2, lb, mid - 1, l, min(r, mid - 1)); 86 | change(c, x, i * 2 + 1, mid, rb, max(l, mid), r); 87 | update(i); 88 | } 89 | long long get_min(const int i, const int lb, const int rb, const int l, const int r) { 90 | lazy_propagation(i); 91 | if (l > r) return INT64_MAX; 92 | if (l == lb && r == rb) return tree[i].min; 93 | int mid = (lb + rb + 1) / 2; 94 | return min(get_min(i * 2, lb, mid - 1, l, min(r, mid - 1)), get_min(i * 2 + 1, mid, rb, max(l, mid), r)); 95 | } 96 | }; 97 | 98 | int main() { 99 | freopen("rmq2.in", "r", stdin); 100 | freopen("rmq2.out", "w", stdout); 101 | ios_base::sync_with_stdio(false); 102 | cin.tie(nullptr); 103 | cout.tie(nullptr); 104 | 105 | int n; 106 | vector arr; 107 | cin >> n; 108 | arr.resize(n); 109 | for (int i = 0; i < n; i++) { 110 | cin >> arr[i]; 111 | } 112 | Segment_tree tree(arr); 113 | string word; 114 | while (cin >> word) { 115 | int a, b; 116 | cin >> a >> b; 117 | if (word == "min") { 118 | cout << tree.get_min(1, 0, tree.get_size() - 1, a - 1, b - 1) << endl; 119 | } else { 120 | long long c; 121 | cin >> c; 122 | if (word == "set") tree.change(SET, c, 1, 0, tree.get_size() - 1, a - 1, b - 1); 123 | if (word == "add") tree.change(ADD, c, 1, 0, tree.get_size() - 1, a - 1, b - 1); 124 | } 125 | } 126 | } -------------------------------------------------------------------------------- /lab07-segment/src/h.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | typedef long long int64; 7 | 8 | class Segment_tree { 9 | 10 | private: 11 | struct Node { 12 | int64 min, max, sum; 13 | 14 | Node() { 15 | this->min = INT64_MAX; 16 | this->max = INT64_MIN; 17 | this->sum = 0; 18 | } 19 | 20 | Node(int64 value) { 21 | this->min = value; 22 | this->max = value; 23 | this->sum = value; 24 | } 25 | }; 26 | int size; 27 | vector tree; 28 | void update(int index) { 29 | tree[index].min = min(tree[2 * index].min, tree[2 * index + 1].min); 30 | tree[index].max = max(tree[2 * index].max, tree[2 * index + 1].max); 31 | tree[index].sum = tree[2 * index].sum + tree[2 * index + 1].sum; 32 | } 33 | 34 | public: 35 | Segment_tree(vector &arr) { 36 | int n = arr.size(); 37 | size = 1 << (((int) log2(n)) + (((n & (n - 1)) == 0) ? 0 : 1)); 38 | tree.resize(2 * size, Node()); 39 | for (int i = 0; i < n; i++) tree[size + i] = Node(arr[i]); 40 | for (int i = size - 1; i >= 1; i--) update(i); 41 | } 42 | void change(int64 index, int64 value) { 43 | int i = (int)index + size; 44 | tree[i] = Node(value); 45 | for (i /= 2; i >= 1; i /= 2) update(i); 46 | } 47 | int64 get_min(int64 left, int64 right) { 48 | int l = (int)left, r = (int)right; 49 | int64 result = INT64_MAX; 50 | for (l += size, r += size; l <= r; l /= 2, r /= 2) { 51 | if (l % 2 == 1) result = min(result, tree[l++].min); 52 | if (r % 2 == 0) result = min(result, tree[r--].min); 53 | } 54 | return result; 55 | } 56 | int64 get_max(int64 left, int64 right) { 57 | int l = (int)left, r = (int)right; 58 | int64 result = INT32_MIN; 59 | for (l += size, r += size; l <= right; l /= 2, r /= 2) { 60 | if (l % 2 == 1) result = max(result, tree[l++].max); 61 | if (r % 2 == 0) result = max(result, tree[r--].max); 62 | } 63 | return result; 64 | } 65 | int64 get_sum(int64 left, int64 right) { 66 | int l = (int)left, r = (int)right; 67 | int64 result = INT32_MAX; 68 | for (l += size, r += size; l <= right; l /= 2, r /= 2) { 69 | if (l % 2 == 1) result += tree[l++].sum; 70 | if (r % 2 == 0) result += tree[r--].sum; 71 | } 72 | return result; 73 | } 74 | int64 get(int64 index) { 75 | int i = (int)index; 76 | return tree[size + i].min; 77 | } 78 | void write() { 79 | for (int i = 0; i < tree.size(); i++) { 80 | cout << tree[i].min << " "; 81 | } 82 | cout << endl; 83 | } 84 | }; 85 | 86 | int main() { 87 | freopen("parking.in", "r", stdin); 88 | freopen("parking.out", "w", stdout); 89 | ios_base::sync_with_stdio(false); 90 | cin.tie(nullptr); 91 | cout.tie(nullptr); 92 | 93 | int n, m; 94 | vector arr; 95 | cin >> n >> m; 96 | arr.resize(n); 97 | for (int i = 0; i < n; i++) arr[i] = i; 98 | Segment_tree tree(arr); 99 | for (int i = 0; i < m; i++) { 100 | string word; 101 | int64 index; 102 | cin >> word >> index; 103 | index--; 104 | if (word == "enter") { 105 | if (tree.get(index) == INT64_MAX) { 106 | int64 tmp = tree.get_min(index, n - 1); 107 | if (tmp == INT64_MAX) { 108 | index = tree.get_min(0, index - 1); 109 | } else { 110 | index = tmp; 111 | } 112 | } 113 | tree.change(index, INT64_MAX); 114 | cout << index + 1 << endl; 115 | } 116 | if (word == "exit") tree.change(index, index); 117 | } 118 | } -------------------------------------------------------------------------------- /lab07-segment/src/j.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | const int rr = 1000000; 8 | 9 | enum Command { 10 | ADD, SET, NO 11 | }; 12 | class Segment_tree { 13 | 14 | private: 15 | struct Node { 16 | long long max, add; 17 | Command command; 18 | Node() { 19 | this->max = 0; 20 | this->add = 0; 21 | this->command = NO; 22 | } 23 | Node(long long value) { 24 | this->max = value; 25 | this->add = 0; 26 | this->command = NO; 27 | } 28 | void set(long long value1, long long value2, Command value3) { 29 | this->max = value1; 30 | this->add = value2; 31 | this->command = value3; 32 | } 33 | }; 34 | int size; 35 | vector tree; 36 | void update(int index) { 37 | tree[index].max = max(tree[2 * index].max, tree[2 * index + 1].max); 38 | } 39 | void lazy_propagation(int index) { 40 | int ch1 = 2 * index ; 41 | int ch2 = 2 * index + 1; 42 | if (tree[index].command == ADD) { 43 | tree[index].max += tree[index].add; 44 | if (index < size) { 45 | switch (tree[ch1].command) { 46 | case ADD: tree[ch1].set(tree[ch1].max, tree[ch1].add + tree[index].add, ADD); break; 47 | case SET: tree[ch1].set(tree[ch1].max, tree[ch1].add + tree[index].add, SET); break; 48 | case NO: tree[ch1].set(tree[ch1].max, tree[index].add, ADD); break; 49 | } 50 | switch (tree[ch2].command) { 51 | case ADD: tree[ch2].set(tree[ch2].max, tree[ch2].add + tree[index].add, ADD); break; 52 | case SET: tree[ch2].set(tree[ch2].max, tree[ch2].add + tree[index].add, SET); break; 53 | case NO: tree[ch2].set(tree[ch2].max, tree[index].add, ADD); break; 54 | } 55 | } 56 | } else if (tree[index].command == SET) { 57 | tree[index].max = tree[index].add; 58 | if (index < size) { 59 | tree[ch1].set(tree[ch1].max, tree[index].add, SET); 60 | tree[ch2].set(tree[ch2].max, tree[index].add, SET); 61 | } 62 | } 63 | tree[index].set(tree[index].max, 0, NO); 64 | } 65 | 66 | public: 67 | Segment_tree(vector &arr) { 68 | int n = arr.size(); 69 | size = 1 << (((int) log2(n)) + (((n & (n - 1)) == 0) ? 0 : 1)); 70 | tree.resize(2 * size, Node()); 71 | for (int i = 0; i < n; i++) tree[size + i] = Node(arr[i]); 72 | for (int i = size - 1; i >= 1; i--) update(i); 73 | } 74 | int get_size() { 75 | return size; 76 | } 77 | void change(Command c, const long long x, const int i, const int lb, const int rb, const int l, const int r) { 78 | lazy_propagation(i); 79 | if (l > r) return; 80 | if (l == lb && r == rb) { 81 | tree[i].command = c; 82 | tree[i].add = x; 83 | lazy_propagation(i); 84 | return; 85 | } 86 | int mid = (lb + rb + 1) / 2; 87 | change(c, x, i * 2, lb, mid - 1, l, min(r, mid - 1)); 88 | change(c, x, i * 2 + 1, mid, rb, max(l, mid), r); 89 | update(i); 90 | } 91 | long long get_max(const int i, const int lb, const int rb, const int l, const int r) { 92 | lazy_propagation(i); 93 | if (l > r) return 0; 94 | if (l == lb && r == rb) return tree[i].max; 95 | int mid = (lb + rb + 1) / 2; 96 | return max(get_max(i * 2, lb, mid - 1, l, min(r, mid - 1)), get_max(i * 2 + 1, mid, rb, max(l, mid), r)); 97 | } 98 | long long get_index_max(const int i, const int l, const int r) { 99 | lazy_propagation(i); 100 | if (i >= size) return l - rr; 101 | lazy_propagation(2 * i); 102 | lazy_propagation(2 * i + 1); 103 | int mid = (l + r + 1) / 2; 104 | if (tree[2 * i].max == tree[i].max) { 105 | return get_index_max(i * 2, l, min(r, mid - 1)); 106 | } else { 107 | return get_index_max(i * 2 + 1, max(l, mid), r); 108 | } 109 | } 110 | }; 111 | struct X { 112 | bool is_closing; 113 | int my_x, upper_y, lower_y; 114 | 115 | X(bool is_closing, int my_x, int lower_y, int upper_y) { 116 | this->is_closing = is_closing; 117 | this->my_x = my_x + rr; 118 | this->lower_y = lower_y + rr; 119 | this->upper_y = upper_y + rr; 120 | } 121 | bool operator<(const X &arg) { 122 | return (this->my_x < arg.my_x) || ((this->my_x == arg.my_x) && (this->is_closing < arg.is_closing)); 123 | } 124 | int get_x() { 125 | return my_x - rr; 126 | } 127 | }; 128 | 129 | int main() { 130 | freopen("windows.in", "r", stdin); 131 | freopen("windows.out", "w", stdout); 132 | ios_base::sync_with_stdio(false); 133 | cin.tie(nullptr); 134 | cout.tie(nullptr); 135 | 136 | int n; 137 | vector arr(2 * rr + 1, 0); 138 | vector coordinates; 139 | cin >> n; 140 | for (int i = 0; i < n; i++) { 141 | int x1, y1, x2, y2; 142 | cin >> x1 >> y1 >> x2 >> y2; 143 | coordinates.emplace_back(false, x1, y1, y2); 144 | coordinates.emplace_back(true, x2, y1, y2); 145 | } 146 | sort(coordinates.begin(), coordinates.end()); 147 | Segment_tree tree(arr); 148 | long long max_x = 0, max_y = 0, max_number = 0; 149 | for (int i = 0; i < 2 * n; i++) { 150 | if (coordinates[i].is_closing) { 151 | tree.change(ADD, -1, 1, 0, tree.get_size() - 1, coordinates[i].lower_y, coordinates[i].upper_y); 152 | } else { 153 | tree.change(ADD, 1, 1, 0, tree.get_size() - 1, coordinates[i].lower_y, coordinates[i].upper_y); 154 | long long tmp = tree.get_max(1, 0, tree.get_size() - 1, 0, tree.get_size() - 1); 155 | if (tmp > max_number) { 156 | max_number = tmp; 157 | max_x = coordinates[i].get_x(); 158 | max_y = tree.get_index_max(1, 0, tree.get_size() - 1); 159 | } 160 | } 161 | } 162 | cout << max_number << endl << max_x << " " << max_y; 163 | } -------------------------------------------------------------------------------- /lab07-segment/src/k.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | struct P { 8 | int index, depth; 9 | P() { 10 | this->depth = INT32_MAX; 11 | this->index = 0; 12 | } 13 | P(int index, int depth) { 14 | this->index = index; 15 | this->depth = depth; 16 | } 17 | }; 18 | P min(const P &first, const P &second) { 19 | if (first.depth < second.depth) { 20 | return first; 21 | } else { 22 | return second; 23 | } 24 | } 25 | 26 | class Segment_tree { 27 | 28 | private: 29 | struct Node { 30 | P min; 31 | 32 | Node() { 33 | this->min = P(); 34 | } 35 | 36 | Node(P value) { 37 | this->min = value; 38 | } 39 | }; 40 | int size; 41 | vector tree; 42 | void update(int index) { 43 | tree[index].min = min(tree[2 * index].min, tree[2 * index + 1].min); 44 | } 45 | 46 | public: 47 | Segment_tree(vector

&arr) { 48 | int n = arr.size(); 49 | size = 1 << (((int) log2(n)) + (((n & (n - 1)) == 0) ? 0 : 1)); 50 | tree.resize(2 * size, Node()); 51 | for (int i = 0; i < n; i++) tree[size + i] = Node(arr[i]); 52 | for (int i = size - 1; i >= 1; i--) update(i); 53 | } 54 | int get_size() { 55 | return size; 56 | } 57 | P get_min(const int i, const int lb, const int rb, const int l, const int r) { 58 | if (l > r) return P(); 59 | if (l == lb && r == rb) return tree[i].min; 60 | int mid = (lb + rb + 1) / 2; 61 | return min(get_min(i * 2, lb, mid - 1, l, min(r, mid - 1)), get_min(i * 2 + 1, mid, rb, max(l, mid), r)); 62 | } 63 | }; 64 | class Binary_tree { 65 | 66 | private: 67 | struct Node { 68 | int number; 69 | vector children; 70 | Node() { 71 | this->number = 0; 72 | } 73 | Node(int number) { 74 | this->number = number; 75 | } 76 | }; 77 | vector nodes; 78 | 79 | public: 80 | Binary_tree() { 81 | nodes.emplace_back(0); 82 | } 83 | int size() { 84 | return nodes.size(); 85 | } 86 | int add_node(int number) { 87 | nodes[number - 1].children.push_back(size()); 88 | nodes.emplace_back(size()); 89 | } 90 | void count_arr(vector

*arr, int number, int depth) { 91 | arr->emplace_back(number + 1, depth); 92 | for (int &i : nodes[number].children) { 93 | count_arr(arr, i, depth + 1); 94 | arr->emplace_back(number + 1, depth); 95 | } 96 | } 97 | }; 98 | 99 | int main() { 100 | freopen("lca.in", "r", stdin); 101 | freopen("lca.out", "w", stdout); 102 | ios_base::sync_with_stdio(false); 103 | cin.tie(nullptr); 104 | cout.tie(nullptr); 105 | 106 | int k; 107 | cin >> k; 108 | vector> queries; 109 | Binary_tree bin_tree; 110 | string word; 111 | while (cin >> word) { 112 | int a, b; 113 | cin >> a >> b; 114 | if (word == "ADD") bin_tree.add_node(a); 115 | if (word == "GET") queries.emplace_back(a, b); 116 | } 117 | vector

arr; 118 | bin_tree.count_arr(&arr, 0, 0); 119 | int s = bin_tree.size(); 120 | vector> pos(s + 1, make_pair(-1, -1)); 121 | for (int i = 0; i < arr.size(); i++) { 122 | P &c = arr[i]; 123 | if (pos[c.index].first == -1) pos[c.index].first = i; 124 | pos[c.index].second = i; 125 | } 126 | Segment_tree tree(arr); 127 | for (int j = 0; j < queries.size(); j++) { 128 | int l = min(pos[queries[j].first].first, pos[queries[j].second].first); 129 | int r = max(pos[queries[j].first].second, pos[queries[j].second].second); 130 | P ans = tree.get_min(1, 0, tree.get_size() - 1, l, r); 131 | cout << ans.index << endl; 132 | } 133 | } -------------------------------------------------------------------------------- /lab07-segment/src/l.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | unsigned a, b, cur = 0; 8 | unsigned nextRand17() { 9 | cur = cur * a + b; 10 | return cur >> 15; 11 | } 12 | unsigned nextRand24() { 13 | cur = cur * a + b; 14 | return cur >> 8; 15 | } 16 | 17 | vector operator*(vector const &first, vector const &second) { 18 | vector result; 19 | unsigned i = 0, j = 0; 20 | while (i < first.size() || j < second.size()) { 21 | if (i >= first.size()) { 22 | result.push_back(second[j]); 23 | j++; 24 | } else if (j >= second.size()) { 25 | result.push_back(first[i]); 26 | i++; 27 | } else { 28 | if (first[i] <= second[j]) { 29 | result.push_back(first[i]); 30 | i++; 31 | } else { 32 | result.push_back(second[j]); 33 | j++; 34 | } 35 | } 36 | } 37 | return result; 38 | } 39 | class Segment_tree { 40 | 41 | private: 42 | struct Node { 43 | vector sorted; 44 | Node() { 45 | sorted.resize(0); 46 | } 47 | Node(unsigned value) { 48 | this->sorted.push_back(value); 49 | } 50 | }; 51 | unsigned size; 52 | vector tree; 53 | void update(unsigned index) { 54 | tree[index].sorted = tree[2 * index].sorted * tree[2 * index + 1].sorted; 55 | } 56 | 57 | public: 58 | Segment_tree(vector &arr) { 59 | unsigned n = arr.size(); 60 | size = 1 << (((unsigned) log2(n)) + (((n & (n - 1)) == 0) ? 0 : 1)); 61 | tree.resize(2 * size, Node()); 62 | for (unsigned i = 0; i < n; i++) tree[size + i] = Node(arr[i]); 63 | for (unsigned i = size - 1; i >= 1; i--) update(i); 64 | } 65 | unsigned get_size() { 66 | return size; 67 | } 68 | unsigned get_ans(const unsigned x, const unsigned y, const unsigned &i, const unsigned &lb, const unsigned &rb, const unsigned &l, const unsigned &r) { 69 | if (l > r) return 0; 70 | if (l == lb && r == rb) return count(x, y, tree[i].sorted); 71 | unsigned mid = (lb + rb + 1) / 2; 72 | return get_ans(x, y, i * 2, lb, mid - 1, l, min(r, mid - 1)) + get_ans(x, y, i * 2 + 1, mid, rb, max(l, mid), r); 73 | } 74 | unsigned count(unsigned x, unsigned y, vector &v) { 75 | if (v.size() == 1) { 76 | if (v[0] >= x && v[0] <= y) { 77 | return 1; 78 | } else { 79 | return 0; 80 | } 81 | } 82 | auto w1 = static_cast(distance(v.begin(), lower_bound(v.begin(), v.end(), x)) + 4); 83 | auto w2 = static_cast(distance(v.begin(), upper_bound(v.begin(), v.end(), y)) + 4); 84 | unsigned ans = w2 - w1; 85 | return ans; 86 | } 87 | }; 88 | 89 | int main() { 90 | freopen("find2d.in", "r", stdin); 91 | freopen("find2d.out", "w", stdout); 92 | 93 | unsigned n = (1 << 17), q; 94 | vector arr(n); 95 | cin >> q >> a >> b; 96 | arr.resize(n); 97 | for (unsigned i = 0; i < n; i++) { 98 | arr[i] = nextRand24(); 99 | } 100 | unsigned sum = 0; 101 | Segment_tree tree(arr); 102 | for (unsigned i = 0; i < q; i++) { 103 | unsigned ll = nextRand17(); 104 | unsigned rr = nextRand17(); 105 | unsigned l = min(ll, rr), r = max(ll, rr); 106 | unsigned xx = nextRand24(); 107 | unsigned yy = nextRand24(); 108 | unsigned x = min(xx, yy), y = max(xx, yy); 109 | unsigned c = tree.get_ans(x, y, 1, 0, tree.get_size() - 1, l, r); 110 | b += c; 111 | sum += c; 112 | } 113 | cout << sum; 114 | } -------------------------------------------------------------------------------- /lab07-segment/src/m.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | struct P { 8 | int index, depth; 9 | P() { 10 | this->depth = INT32_MAX; 11 | this->index = 0; 12 | } 13 | P(int index, int depth) { 14 | this->index = index; 15 | this->depth = depth; 16 | } 17 | }; 18 | P min(const P &first, const P &second) { 19 | if (first.depth < second.depth) { 20 | return first; 21 | } else { 22 | return second; 23 | } 24 | } 25 | class Sparse_table { 26 | 27 | private: 28 | vector> table; 29 | 30 | public: 31 | Sparse_table(vector

&arr) { 32 | int s = arr.size(); 33 | table.resize((int)444444, vector

(20, P())); 34 | for (int j = 0; (1 << j) <= s; j++) { 35 | for (int i = 0; i < s; i++) { 36 | if (j == 0) { 37 | table[i][j] = arr[i]; 38 | } else { 39 | table[i][j] = min(table[i][j - 1], table[i + (1 << j - 1)][j - 1]); 40 | } 41 | } 42 | } 43 | } 44 | P get_min(int l, int r) { 45 | int j = 0; 46 | while ((1 << j + 1) <= r - l + 1) { 47 | j++; 48 | } 49 | return min(table[l][j], table[r - (1 << j) + 1][j]); 50 | } 51 | }; 52 | class Binary_tree { 53 | 54 | private: 55 | struct Node { 56 | int number; 57 | vector children; 58 | Node() { 59 | this->number = 0; 60 | } 61 | Node(int number) { 62 | this->number = number; 63 | } 64 | }; 65 | vector nodes; 66 | 67 | public: 68 | Binary_tree(int n) { 69 | for (int i = 0; i < n; i++) { 70 | nodes.emplace_back(i); 71 | } 72 | } 73 | int size() { 74 | return nodes.size(); 75 | } 76 | int add_node(int parent, int number) { 77 | nodes[parent].children.push_back(number); 78 | } 79 | void count_arr(vector

*arr, int number, int depth) { 80 | arr->emplace_back(number, depth); 81 | for (int &i : nodes[number].children) { 82 | count_arr(arr, i, depth + 1); 83 | arr->emplace_back(number, depth); 84 | } 85 | } 86 | }; 87 | 88 | int main() { 89 | freopen("lca_rmq.in", "r", stdin); 90 | freopen("lca_rmq.out", "w", stdout); 91 | ios_base::sync_with_stdio(false); 92 | cin.tie(nullptr); 93 | cout.tie(nullptr); 94 | 95 | int n, m; 96 | cin >> n >> m; 97 | Binary_tree bin_tree(n); 98 | string word; 99 | for (int i = 1; i < n; i++) { 100 | int p; 101 | cin >> p; 102 | bin_tree.add_node(p, i); 103 | } 104 | vector

arr; 105 | bin_tree.count_arr(&arr, 0, 0); 106 | int s = bin_tree.size(); 107 | vector> pos(s, make_pair(-1, -1)); 108 | for (int i = 0; i < arr.size(); i++) { 109 | P &c = arr[i]; 110 | if (pos[c.index].first == -1) pos[c.index].first = i; 111 | pos[c.index].second = i; 112 | } 113 | 114 | int x, y, z; 115 | vector h(2 * m + 1); 116 | cin >> h[1] >> h[2] >> x >> y >> z; 117 | for (int i = 3; i < h.size(); i++) { 118 | h[i] = (int)(((long long)x * (long long)h[i - 2] + (long long)y * (long long)h[i - 1] + (long long)z) % n); 119 | } 120 | 121 | Sparse_table table(arr); 122 | P ans; 123 | long long sum = 0; 124 | int q1 = h[1], q2 = h[2]; 125 | for (int j = 1; j <= m; j++) { 126 | int l = min(pos[q1].first, pos[q2].first); 127 | int r = max(pos[q1].second, pos[q2].second); 128 | ans = table.get_min(l, r); 129 | sum += ans.index; 130 | q1 = ((h[2 * j + 1] + ans.index) % n); 131 | q2 = h[2 * j + 2]; 132 | } 133 | cout << sum; 134 | } -------------------------------------------------------------------------------- /lab07-segment/src/o.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * todo: make normal version of HLD 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | struct P { 14 | int index, depth; 15 | P() { 16 | this->depth = INT32_MAX; 17 | this->index = 0; 18 | } 19 | P(int index, int depth) { 20 | this->index = index; 21 | this->depth = depth; 22 | } 23 | }; 24 | P min(const P &first, const P &second) { 25 | if (first.depth < second.depth) { 26 | return first; 27 | } else { 28 | return second; 29 | } 30 | } 31 | 32 | class Segment_tree { 33 | 34 | private: 35 | struct Node { 36 | P min; 37 | 38 | Node() { 39 | this->min = P(); 40 | } 41 | 42 | Node(P value) { 43 | this->min = value; 44 | } 45 | }; 46 | int size; 47 | vector tree; 48 | void update(int index) { 49 | tree[index].min = min(tree[2 * index].min, tree[2 * index + 1].min); 50 | } 51 | 52 | public: 53 | Segment_tree(vector

&arr) { 54 | int n = arr.size(); 55 | size = 1 << (((int) log2(n)) + (((n & (n - 1)) == 0) ? 0 : 1)); 56 | tree.resize(2 * size, Node()); 57 | for (int i = 0; i < n; i++) tree[size + i] = Node(arr[i]); 58 | for (int i = size - 1; i >= 1; i--) update(i); 59 | } 60 | int get_size() { 61 | return size; 62 | } 63 | P get_min(const int i, const int lb, const int rb, const int l, const int r) { 64 | if (l > r) return P(); 65 | if (l == lb && r == rb) return tree[i].min; 66 | int mid = (lb + rb + 1) / 2; 67 | return min(get_min(i * 2, lb, mid - 1, l, min(r, mid - 1)), get_min(i * 2 + 1, mid, rb, max(l, mid), r)); 68 | } 69 | }; 70 | class My_tree { 71 | 72 | private: 73 | struct Node { 74 | int number; 75 | vector children; 76 | Node() { 77 | this->number = 0; 78 | } 79 | Node(int number) { 80 | this->number = number; 81 | } 82 | }; 83 | vector visited; 84 | vector nodes; 85 | vector depth, parent; 86 | vector> g; 87 | vector> minimum; 88 | vector> dp; 89 | vector to_binary(int k) { 90 | vector res(0); 91 | while (k > 0) { 92 | res.push_back((bool)(k % 2)); 93 | k /= 2; 94 | } 95 | return res; 96 | } 97 | void dfs(int v, int p, int d) { 98 | if (visited[v]) { 99 | return; 100 | } 101 | visited[v] = true; 102 | parent[v] = p; 103 | depth[v] = d; 104 | for (auto x : g[v]) { 105 | int to = x.first; 106 | dfs(to, v, d + 1); 107 | } 108 | } 109 | void precalc(int size, int log_size) { 110 | for (int jump = 0; jump < log_size; jump++) { 111 | for (int v = 0; v < size; v++) { 112 | if (jump == 0) { 113 | dp[v][jump] = parent[v]; 114 | minimum[v][jump] = g[parent[v]][v]; 115 | } 116 | else { 117 | dp[v][jump] = dp[dp[v][jump - 1]][jump - 1]; 118 | minimum[v][jump] = min(minimum[v][jump - 1], minimum[dp[v][jump - 1]][jump - 1]); 119 | } 120 | } 121 | } 122 | } 123 | 124 | public: 125 | My_tree(int size) { 126 | nodes.resize(size); 127 | visited.resize(size, false); 128 | depth.resize(size); 129 | parent.resize(size); 130 | g.resize(size); 131 | int log_size = (int)log2(size) + 1; 132 | minimum.resize(size, vector(log_size, INT32_MAX)); 133 | dp.resize(size, vector(log_size, 0)); 134 | } 135 | int size() { 136 | return nodes.size(); 137 | } 138 | int add_node(int parent, int index, int cost) { 139 | nodes[parent].children.push_back(index); 140 | g[parent][index] = cost; 141 | } 142 | void count_arr(vector

*arr, int number, int depth) { 143 | arr->emplace_back(number, depth); 144 | for (int &i : nodes[number].children) { 145 | count_arr(arr, i, depth + 1); 146 | arr->emplace_back(number, depth); 147 | } 148 | } 149 | void calculate() { 150 | dfs(0, 0, 0); 151 | precalc(minimum.size(), minimum[0].size()); 152 | } 153 | int get_min(int u, int v, int lca) { 154 | auto jumps_v = to_binary(depth[v] - depth[lca]); 155 | auto jumps_u = to_binary(depth[u] - depth[lca]); 156 | int ans = INT32_MAX; 157 | for (int i = 0; i < jumps_u.size(); i++) { 158 | if (jumps_u[i]) { 159 | ans = min(ans, minimum[u][i]); 160 | u = dp[u][i]; 161 | } 162 | } 163 | for (int i = 0; i < jumps_v.size(); i++) { 164 | if (jumps_v[i]) { 165 | ans = min(ans, minimum[v][i]); 166 | v = dp[v][i]; 167 | } 168 | } 169 | return ans; 170 | } 171 | }; 172 | 173 | int main() { 174 | freopen("minonpath.in", "r", stdin); 175 | freopen("minonpath.out", "w", stdout); 176 | ios_base::sync_with_stdio(false); 177 | cin.tie(nullptr); 178 | cout.tie(nullptr); 179 | 180 | int n, m; 181 | cin >> n; 182 | My_tree tree1(n); 183 | for (int i = 1; i < n; i++) { 184 | int a, b; 185 | cin >> a >> b; 186 | tree1.add_node(a - 1, i, b); 187 | } 188 | vector

arr; 189 | tree1.count_arr(&arr, 0, 0); 190 | vector> pos(n, make_pair(-1, -1)); 191 | for (int i = 0; i < arr.size(); i++) { 192 | P &c = arr[i]; 193 | if (pos[c.index].first == -1) pos[c.index].first = i; 194 | pos[c.index].second = i; 195 | } 196 | Segment_tree tree(arr); 197 | cin >> m; 198 | tree1.calculate(); 199 | for (int j = 0; j < m; j++) { 200 | int q1, q2; 201 | cin >> q1 >> q2; 202 | int l = min(pos[q1 - 1].first, pos[q2 - 1].first); 203 | int r = max(pos[q1 - 1].second, pos[q2 - 1].second); 204 | int lca = tree.get_min(1, 0, tree.get_size() - 1, l, r).index; 205 | int result = tree1.get_min(q1 - 1, q2 - 1, lca); 206 | cout << result << endl; 207 | } 208 | } -------------------------------------------------------------------------------- /lab07-segment/tasks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cannor147/itmo-algo/96ec8f28c0af1005b9cb2870e4c68d65a7d8a941/lab07-segment/tasks.pdf -------------------------------------------------------------------------------- /lab08-sortnet/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(lab08_sortnet) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_executable(b draft/b.cpp) -------------------------------------------------------------------------------- /lab08-sortnet/draft/b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | class Sorting_network { 7 | 8 | private: 9 | int number; 10 | vector>> layers; 11 | void add_head(int k, int first, int last) { 12 | 13 | } 14 | void add_layers(int k, int first, int last) { 15 | if (first == last) return; 16 | int r = (last - first + 1) / 2; 17 | if (k >= layers.size()) layers.push_back({}); 18 | for (int i = first; i < first + r; i++) { 19 | layers[k].push_back(make_pair(i, last - i + first)); 20 | } 21 | if ((last - first + 1) % 2 != 0) { 22 | k++; 23 | if (k >= layers.size()) layers.push_back({}); 24 | layers[k].push_back(make_pair(first + r, last)); 25 | } 26 | k++; 27 | add_layers(k, first, last - r); 28 | add_layers(k, last - r + 1, last); 29 | } 30 | 31 | public: 32 | Sorting_network() { 33 | this->number = 0; 34 | this->layers.resize(0); 35 | } 36 | Sorting_network(int number, vector>> layers) { 37 | this->number = number; 38 | this->layers = layers; 39 | } 40 | int get_size() { 41 | return layers.size(); 42 | } 43 | vector sort(vector original) { 44 | for (int i = 0; i < get_size(); i++) { 45 | for (int j = 0; j < layers[i].size(); j++) { 46 | bool x = original[layers[i][j].first]; 47 | bool y = original[layers[i][j].second]; 48 | original[layers[i][j].first] = min(x, y); 49 | original[layers[i][j].second] = max(x, y); 50 | } 51 | } 52 | return original; 53 | } 54 | bool is_sorted(vector &original) { 55 | auto result = sort(original); 56 | for (int i = 1; i < result.size(); i++) { 57 | if (result[i] < result[i - 1]) { 58 | return false; 59 | } 60 | } 61 | return true; 62 | } 63 | bool check() { 64 | int i = 0; 65 | bool ans = true; 66 | vector original(number, false); 67 | while (i < (1 << number)) { 68 | int k = i; 69 | for (int j = 0; j < number; j++) { 70 | original[j] = k % 2; 71 | k /= 2; 72 | } 73 | ans &= is_sorted(original); 74 | if (!ans) return false; 75 | i++; 76 | } 77 | return true; 78 | } 79 | void generate(int n) { 80 | number = n; 81 | add_head(0, 1, n); 82 | int k = layers.size(); 83 | add_layers(k, 1, n); 84 | } 85 | void print() { 86 | int n = number, m = 0, k = layers.size(); 87 | for (int i = 0; i < k; i++) { 88 | m += layers[i].size(); 89 | } 90 | cout << n << " " << m << " " << k << endl; 91 | for (int i = 0; i < k; i++) { 92 | cout << layers[i].size() << " "; 93 | for (int j = 0; j < layers[i].size(); j++) { 94 | cout << layers[i][j].first << " " << layers[i][j].second << " "; 95 | } 96 | cout << endl; 97 | } 98 | } 99 | }; 100 | 101 | int main() { 102 | int n; 103 | cin >> n; 104 | Sorting_network my_network; 105 | my_network.generate(n); 106 | my_network.print(); 107 | return 0; 108 | } -------------------------------------------------------------------------------- /lab08-sortnet/tasks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cannor147/itmo-algo/96ec8f28c0af1005b9cb2870e4c68d65a7d8a941/lab08-sortnet/tasks.pdf -------------------------------------------------------------------------------- /lab09-dfs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(lab09_dfs) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_executable(a src/a.cpp) 7 | add_executable(b src/b.cpp) 8 | add_executable(c src/c.cpp) 9 | add_executable(d src/d.cpp) 10 | add_executable(e src/e.cpp) 11 | add_executable(f src/f.cpp) 12 | add_executable(g src/g.cpp) 13 | add_executable(h src/h.cpp) 14 | add_executable(i src/i.cpp) 15 | add_executable(j src/j.cpp) 16 | add_executable(k src/k.cpp) 17 | add_executable(l src/l.cpp) 18 | add_executable(m src/m.cpp) 19 | add_executable(n src/n.cpp) 20 | add_executable(o src/o.cpp) 21 | add_executable(p src/p.cpp) 22 | add_executable(q src/q.cpp) 23 | add_executable(s src/s.cpp) -------------------------------------------------------------------------------- /lab09-dfs/src/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class oriental_graph { 9 | 10 | private: 11 | vector> matrix; 12 | 13 | bool dfs(size_t i, vector &colors, vector &result) { 14 | bool f = true; 15 | if (colors[i] == 0) { 16 | colors[i]++; 17 | for (size_t d : matrix[i]) { 18 | f &= dfs(d, colors, result); 19 | } 20 | colors[i]++; 21 | result.push_back(i); 22 | } else if (colors[i] == 1) { 23 | f = false; 24 | } 25 | return f; 26 | } 27 | 28 | public: 29 | explicit oriental_graph(size_t n) { 30 | matrix = vector>(n, vector()); 31 | } 32 | size_t getSize() { 33 | return matrix.size(); 34 | } 35 | bool getEdge(size_t i, size_t j) { 36 | for (size_t d : matrix[i]) { 37 | if (d == j) return true; 38 | } 39 | return false; 40 | } 41 | void setEdge(size_t i, size_t j) { 42 | matrix[i].push_back(j); 43 | } 44 | vector top_sort() { 45 | vector colors(getSize(), 0); 46 | vector result; 47 | bool f = true; 48 | for (size_t d = 0; d < getSize(); d++) { 49 | f &= dfs(d, colors, result); 50 | } 51 | if (!f) { 52 | result.clear(); 53 | } else { 54 | std::reverse(result.begin(), result.end()); 55 | } 56 | return result; 57 | } 58 | }; 59 | 60 | int main() { 61 | size_t n, m; 62 | cin >> n >> m; 63 | oriental_graph g(n); 64 | for (size_t i = 0; i < m; i++) { 65 | size_t a, b; 66 | cin >> a >> b; 67 | g.setEdge(a - 1, b - 1); 68 | } 69 | vector t = g.top_sort(); 70 | if (t.empty()) { 71 | cout << -1; 72 | } else { 73 | for (size_t i = 0; i < t.size(); i++) { 74 | cout << t[i] + 1 << " "; 75 | } 76 | } 77 | return 0; 78 | } -------------------------------------------------------------------------------- /lab09-dfs/src/b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class oriental_graph { 9 | 10 | private: 11 | class edge { 12 | private: 13 | size_t index; 14 | int weight; 15 | public: 16 | edge() { 17 | index = 0; 18 | weight = 0; 19 | } 20 | explicit edge(size_t i, int w = 0) { 21 | index = i; 22 | weight = w; 23 | } 24 | size_t get_index() { 25 | return index; 26 | } 27 | int get_weight() { 28 | return weight; 29 | } 30 | }; 31 | vector> matrix; 32 | 33 | bool dfs_ts(size_t i, vector &colors, vector &result) { 34 | bool f = true; 35 | if (colors[i] == 0) { 36 | colors[i]++; 37 | for (edge e : matrix[i]) { 38 | f &= dfs_ts(e.get_index(), colors, result); 39 | } 40 | colors[i]++; 41 | result.push_back(i); 42 | } else if (colors[i] == 1) { 43 | f = false; 44 | } 45 | return f; 46 | } 47 | void dfs_c1(size_t i, vector &colors, vector &order) { 48 | if (colors[i]) return; 49 | colors[i] = 1; 50 | for (edge e : matrix[i]) { 51 | dfs_c1(e.get_index(), colors, order); 52 | } 53 | order.push_back(i); 54 | } 55 | void dfs_c2(size_t i, vector &colors, vector &scc) { 56 | if (colors[i]) return; 57 | colors[i] = 1; 58 | scc.push_back(i); 59 | for (edge e : matrix[i]) { 60 | dfs_c2(e.get_index(), colors, scc); 61 | } 62 | } 63 | 64 | public: 65 | oriental_graph() { 66 | matrix = vector>(); 67 | } 68 | explicit oriental_graph(size_t n) { 69 | matrix = vector>(n, vector()); 70 | } 71 | size_t size() { 72 | return matrix.size(); 73 | } 74 | void add_edge(size_t i, size_t j, size_t w = 0) { 75 | matrix[i].emplace_back(j, w); 76 | } 77 | void add_vertex() { 78 | matrix.push_back(vector()); 79 | } 80 | 81 | vector top_sort() { 82 | vector colors(size(), 0); 83 | vector result; 84 | bool f = true; 85 | for (size_t d = 0; d < size(); d++) { 86 | f &= dfs_ts(d, colors, result); 87 | } 88 | if (!f) { 89 | result.clear(); 90 | } else { 91 | std::reverse(result.begin(), result.end()); 92 | } 93 | return result; 94 | } 95 | oriental_graph transpose() { 96 | oriental_graph result(size()); 97 | for (size_t i = 0; i < size(); i++) { 98 | for (size_t j = 0; j < matrix[i].size(); j++) { 99 | result.add_edge(matrix[i][j].get_index(), i); 100 | } 101 | } 102 | return result; 103 | } 104 | vector get_condensation(size_t &k) { 105 | vector colors(size(), 0), order, result(size()); 106 | for (size_t i = 0; i < size(); i++) { 107 | dfs_c1(i, colors, order); 108 | } 109 | colors = vector(size(), 0); 110 | oriental_graph trans = transpose(); 111 | for (size_t i = 0; i < size(); i++) { 112 | vector scc; 113 | trans.dfs_c2(order[size() - i - 1], colors, scc); 114 | for (size_t j = 0; j < scc.size(); j++) { 115 | result[scc[j]] = k; 116 | } 117 | if (scc.size() > 0) k++; 118 | scc.clear(); 119 | } 120 | return result; 121 | } 122 | }; 123 | 124 | int main() { 125 | size_t n, m; 126 | cin >> n >> m; 127 | oriental_graph g(n); 128 | for (size_t i = 0; i < m; i++) { 129 | size_t a, b; 130 | cin >> a >> b; 131 | g.add_edge(a - 1, b - 1); 132 | } 133 | size_t k = 0; 134 | vector t = g.get_condensation(k); 135 | cout << k << endl; 136 | for (size_t i = 0; i < t.size(); i++) { 137 | cout << t[i] + 1 << " "; 138 | } 139 | return 0; 140 | } -------------------------------------------------------------------------------- /lab09-dfs/src/c.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class oriental_graph { 9 | 10 | private: 11 | class edge { 12 | private: 13 | size_t index; 14 | int weight; 15 | public: 16 | edge() { 17 | index = 0; 18 | weight = 0; 19 | } 20 | explicit edge(size_t i, int w = 0) { 21 | index = i; 22 | weight = w; 23 | } 24 | size_t get_index() { 25 | return index; 26 | } 27 | int get_weight() { 28 | return weight; 29 | } 30 | }; 31 | vector> matrix; 32 | 33 | bool dfs_ts(size_t i, vector &colors, vector &result) { 34 | bool f = true; 35 | if (colors[i] == 0) { 36 | colors[i]++; 37 | for (edge e : matrix[i]) { 38 | f &= dfs_ts(e.get_index(), colors, result); 39 | } 40 | colors[i]++; 41 | result.push_back(i); 42 | } else if (colors[i] == 1) { 43 | f = false; 44 | } 45 | return f; 46 | } 47 | void dfs_c1(size_t i, vector &colors, vector &order) { 48 | if (colors[i]) return; 49 | colors[i] = 1; 50 | for (edge e : matrix[i]) { 51 | dfs_c1(e.get_index(), colors, order); 52 | } 53 | order.push_back(i); 54 | } 55 | void dfs_c2(size_t i, vector &colors, vector &scc) { 56 | if (colors[i]) return; 57 | colors[i] = 1; 58 | scc.push_back(i); 59 | for (edge e : matrix[i]) { 60 | dfs_c2(e.get_index(), colors, scc); 61 | } 62 | } 63 | 64 | public: 65 | oriental_graph() { 66 | matrix = vector>(); 67 | } 68 | explicit oriental_graph(size_t n) { 69 | matrix = vector>(n, vector()); 70 | } 71 | size_t size() { 72 | return matrix.size(); 73 | } 74 | void add_edge(size_t i, size_t j, size_t w = 0) { 75 | matrix[i].emplace_back(j, w); 76 | } 77 | void add_vertex() { 78 | matrix.push_back(vector()); 79 | } 80 | 81 | vector top_sort() { 82 | vector colors(size(), 0); 83 | vector result; 84 | bool f = true; 85 | for (size_t d = 0; d < size(); d++) { 86 | f &= dfs_ts(d, colors, result); 87 | } 88 | if (!f) { 89 | result.clear(); 90 | } else { 91 | std::reverse(result.begin(), result.end()); 92 | } 93 | return result; 94 | } 95 | oriental_graph transpose() { 96 | oriental_graph result(size()); 97 | for (size_t i = 0; i < size(); i++) { 98 | for (size_t j = 0; j < matrix[i].size(); j++) { 99 | result.add_edge(matrix[i][j].get_index(), i); 100 | } 101 | } 102 | return result; 103 | } 104 | vector get_condensation(size_t &k) { 105 | vector colors(size(), 0), order, result(size()); 106 | for (size_t i = 0; i < size(); i++) { 107 | dfs_c1(i, colors, order); 108 | } 109 | colors = vector(size(), 0); 110 | oriental_graph trans = transpose(); 111 | for (size_t i = 0; i < size(); i++) { 112 | vector scc; 113 | trans.dfs_c2(order[size() - i - 1], colors, scc); 114 | for (size_t j = 0; j < scc.size(); j++) { 115 | result[scc[j]] = k; 116 | } 117 | if (scc.size() > 0) k++; 118 | scc.clear(); 119 | } 120 | return result; 121 | } 122 | long long get_path(size_t i, size_t j) { 123 | vector dw(size(), INT32_MAX); 124 | dw[i] = 0; 125 | 126 | vector ts = top_sort(); 127 | size_t d; 128 | for (d = 0; d < size(); d++) { 129 | if (ts[d] == i) break; 130 | } 131 | for (; d < size(); d++) { 132 | for (auto r : matrix[ts[d]]) { 133 | dw[r.get_index()] = min(dw[r.get_index()], dw[ts[d]] + r.get_weight()); 134 | } 135 | } 136 | return dw[j]; 137 | } 138 | }; 139 | 140 | int main() { 141 | size_t n, m, s, t; 142 | cin >> n >> m >> s >> t; 143 | oriental_graph g(n); 144 | for (size_t i = 0; i < m; i++) { 145 | size_t a, b; 146 | int c; 147 | cin >> a >> b >> c; 148 | g.add_edge(a - 1, b - 1, c); 149 | } 150 | long long k = g.get_path(s - 1, t - 1); 151 | if (k == INT32_MAX) { 152 | cout << "Unreachable"; 153 | } else { 154 | cout << k; 155 | } 156 | return 0; 157 | } -------------------------------------------------------------------------------- /lab09-dfs/src/d.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class oriental_graph { 9 | 10 | private: 11 | class edge { 12 | private: 13 | size_t index; 14 | int weight; 15 | public: 16 | edge() { 17 | index = 0; 18 | weight = 0; 19 | } 20 | explicit edge(size_t i, int w = 0) { 21 | index = i; 22 | weight = w; 23 | } 24 | size_t get_index() { 25 | return index; 26 | } 27 | int get_weight() { 28 | return weight; 29 | } 30 | }; 31 | vector> matrix; 32 | 33 | bool dfs_ts(size_t i, vector &colors, vector &result) { 34 | bool f = true; 35 | if (colors[i] == 0) { 36 | colors[i]++; 37 | for (edge &e : matrix[i]) { 38 | f &= dfs_ts(e.get_index(), colors, result); 39 | } 40 | colors[i]++; 41 | result.push_back(i); 42 | } else if (colors[i] == 1) { 43 | f = false; 44 | } 45 | return f; 46 | } 47 | void dfs_c1(size_t i, vector &colors, vector &order) { 48 | if (colors[i]) return; 49 | colors[i] = 1; 50 | for (edge &e : matrix[i]) { 51 | dfs_c1(e.get_index(), colors, order); 52 | } 53 | order.push_back(i); 54 | } 55 | void dfs_c2(size_t i, vector &colors, vector &scc) { 56 | if (colors[i]) return; 57 | colors[i] = 1; 58 | scc.push_back(i); 59 | for (edge &e : matrix[i]) { 60 | dfs_c2(e.get_index(), colors, scc); 61 | } 62 | } 63 | bool dfs_cycl(size_t i, vector &colors, stack &st) { 64 | bool f = true; 65 | if (colors[i] == 0) { 66 | colors[i]++; 67 | st.push(i); 68 | for (edge &e : matrix[i]) { 69 | f &= dfs_cycl(e.get_index(), colors, st); 70 | if (!f) return false; 71 | } 72 | st.pop(); 73 | colors[i]++; 74 | } else if (colors[i] == 1) { 75 | st.push(i); 76 | f = false; 77 | } 78 | return f; 79 | } 80 | size_t dfs_odd(size_t i, vector &ans_odd, vector &ans_even) { 81 | if (ans_odd[i] == 2) { 82 | ans_odd[i] = 1; 83 | if (matrix[i].empty()) ans_odd[i] = 0; 84 | for (auto &e : matrix[i]) { 85 | ans_odd[i] &= dfs_even(e.get_index(), ans_odd, ans_even); 86 | } 87 | } 88 | return ans_odd[i]; 89 | } 90 | size_t dfs_even(size_t i, vector &ans_odd, vector &ans_even) { 91 | if (ans_even[i] == 2) { 92 | ans_even[i] = 1; 93 | for (auto &e : matrix[i]) { 94 | ans_even[i] &= dfs_odd(e.get_index(), ans_odd, ans_even); 95 | } 96 | } 97 | return ans_even[i]; 98 | } 99 | 100 | public: 101 | oriental_graph() { 102 | matrix = vector>(); 103 | } 104 | explicit oriental_graph(size_t n) { 105 | matrix = vector>(n, vector()); 106 | } 107 | size_t size() { 108 | return matrix.size(); 109 | } 110 | void add_edge(size_t i, size_t j, size_t w = 0) { 111 | matrix[i].emplace_back(j, w); 112 | } 113 | void add_vertex() { 114 | matrix.push_back(vector()); 115 | } 116 | 117 | vector top_sort() { 118 | vector colors(size(), 0); 119 | vector result; 120 | bool f = true; 121 | for (size_t d = 0; d < size(); d++) { 122 | f &= dfs_ts(d, colors, result); 123 | } 124 | if (!f) { 125 | result.clear(); 126 | } else { 127 | std::reverse(result.begin(), result.end()); 128 | } 129 | return result; 130 | } 131 | oriental_graph transpose() { 132 | oriental_graph result(size()); 133 | for (size_t i = 0; i < size(); i++) { 134 | for (size_t j = 0; j < matrix[i].size(); j++) { 135 | result.add_edge(matrix[i][j].get_index(), i); 136 | } 137 | } 138 | return result; 139 | } 140 | vector get_condensation(size_t &k) { 141 | vector colors(size(), 0), order, result(size()); 142 | for (size_t i = 0; i < size(); i++) { 143 | dfs_c1(i, colors, order); 144 | } 145 | colors = vector(size(), 0); 146 | oriental_graph trans = transpose(); 147 | for (size_t i = 0; i < size(); i++) { 148 | vector scc; 149 | trans.dfs_c2(order[size() - i - 1], colors, scc); 150 | for (size_t j = 0; j < scc.size(); j++) { 151 | result[scc[j]] = k; 152 | } 153 | if (scc.size() > 0) k++; 154 | scc.clear(); 155 | } 156 | return result; 157 | } 158 | long long get_path(size_t i, size_t j) { 159 | vector dw(size(), INT32_MAX); 160 | dw[i] = 0; 161 | 162 | vector ts = top_sort(); 163 | size_t d; 164 | for (d = 0; d < size(); d++) { 165 | if (ts[d] == i) break; 166 | } 167 | for (; d < size(); d++) { 168 | for (auto r : matrix[ts[d]]) { 169 | dw[r.get_index()] = min(dw[r.get_index()], dw[ts[d]] + r.get_weight()); 170 | } 171 | } 172 | return dw[j]; 173 | } 174 | vector cycle() { 175 | vector colors(size(), 0), result; 176 | stack st; 177 | for (size_t i = 0; i < size(); i++) { 178 | bool f = dfs_cycl(i, colors, st); 179 | if (!f) { 180 | result.push_back(st.top()); 181 | st.pop(); 182 | while (st.top() != result[0]) { 183 | result.push_back(st.top()); 184 | st.pop(); 185 | } 186 | std::reverse(result.begin(), result.end()); 187 | break; 188 | } 189 | } 190 | return result; 191 | } 192 | bool odd_path(size_t i) { 193 | size_t result = 0; 194 | vector ans_even(size(), 2), ans_odd(size(), 2); 195 | for (auto &e : matrix[i]) { 196 | result |= dfs_even(e.get_index(), ans_odd, ans_even); 197 | } 198 | return result != 0; 199 | } 200 | }; 201 | 202 | int main() { 203 | size_t n, m, t; 204 | cin >> n >> m >> t; 205 | oriental_graph g(n); 206 | for (size_t i = 0; i < m; i++) { 207 | size_t a, b; 208 | cin >> a >> b; 209 | g.add_edge(a - 1, b - 1); 210 | } 211 | bool f = g.odd_path(t - 1); 212 | if (f) { 213 | cout << "First player wins" << endl; 214 | } else { 215 | cout << "Second player wins" << endl; 216 | } 217 | return 0; 218 | } -------------------------------------------------------------------------------- /lab09-dfs/src/e.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class oriental_graph { 9 | 10 | private: 11 | class edge { 12 | private: 13 | size_t index; 14 | int weight; 15 | public: 16 | edge() { 17 | index = 0; 18 | weight = 0; 19 | } 20 | explicit edge(size_t i, int w = 0) { 21 | index = i; 22 | weight = w; 23 | } 24 | size_t get_index() { 25 | return index; 26 | } 27 | int get_weight() { 28 | return weight; 29 | } 30 | }; 31 | vector> matrix; 32 | 33 | bool dfs_ts(size_t i, vector &colors, vector &result) { 34 | bool f = true; 35 | if (colors[i] == 0) { 36 | colors[i]++; 37 | for (edge e : matrix[i]) { 38 | f &= dfs_ts(e.get_index(), colors, result); 39 | } 40 | colors[i]++; 41 | result.push_back(i); 42 | } else if (colors[i] == 1) { 43 | f = false; 44 | } 45 | return f; 46 | } 47 | void dfs_c1(size_t i, vector &colors, vector &order) { 48 | if (colors[i]) return; 49 | colors[i] = 1; 50 | for (edge e : matrix[i]) { 51 | dfs_c1(e.get_index(), colors, order); 52 | } 53 | order.push_back(i); 54 | } 55 | void dfs_c2(size_t i, vector &colors, vector &scc) { 56 | if (colors[i]) return; 57 | colors[i] = 1; 58 | scc.push_back(i); 59 | for (edge e : matrix[i]) { 60 | dfs_c2(e.get_index(), colors, scc); 61 | } 62 | } 63 | bool dfs_cycl(size_t i, vector &colors, stack &st) { 64 | bool f = true; 65 | if (colors[i] == 0) { 66 | colors[i]++; 67 | st.push(i); 68 | for (edge e : matrix[i]) { 69 | f &= dfs_cycl(e.get_index(), colors, st); 70 | if (!f) return false; 71 | } 72 | st.pop(); 73 | colors[i]++; 74 | } else if (colors[i] == 1) { 75 | st.push(i); 76 | f = false; 77 | } 78 | return f; 79 | } 80 | 81 | 82 | public: 83 | oriental_graph() { 84 | matrix = vector>(); 85 | } 86 | explicit oriental_graph(size_t n) { 87 | matrix = vector>(n, vector()); 88 | } 89 | size_t size() { 90 | return matrix.size(); 91 | } 92 | void add_edge(size_t i, size_t j, size_t w = 0) { 93 | matrix[i].emplace_back(j, w); 94 | } 95 | void add_vertex() { 96 | matrix.push_back(vector()); 97 | } 98 | 99 | vector top_sort() { 100 | vector colors(size(), 0); 101 | vector result; 102 | bool f = true; 103 | for (size_t d = 0; d < size(); d++) { 104 | f &= dfs_ts(d, colors, result); 105 | } 106 | if (!f) { 107 | result.clear(); 108 | } else { 109 | std::reverse(result.begin(), result.end()); 110 | } 111 | return result; 112 | } 113 | oriental_graph transpose() { 114 | oriental_graph result(size()); 115 | for (size_t i = 0; i < size(); i++) { 116 | for (size_t j = 0; j < matrix[i].size(); j++) { 117 | result.add_edge(matrix[i][j].get_index(), i); 118 | } 119 | } 120 | return result; 121 | } 122 | vector get_condensation(size_t &k) { 123 | vector colors(size(), 0), order, result(size()); 124 | for (size_t i = 0; i < size(); i++) { 125 | dfs_c1(i, colors, order); 126 | } 127 | colors = vector(size(), 0); 128 | oriental_graph trans = transpose(); 129 | for (size_t i = 0; i < size(); i++) { 130 | vector scc; 131 | trans.dfs_c2(order[size() - i - 1], colors, scc); 132 | for (size_t j = 0; j < scc.size(); j++) { 133 | result[scc[j]] = k; 134 | } 135 | if (scc.size() > 0) k++; 136 | scc.clear(); 137 | } 138 | return result; 139 | } 140 | long long get_path(size_t i, size_t j) { 141 | vector dw(size(), INT32_MAX); 142 | dw[i] = 0; 143 | 144 | vector ts = top_sort(); 145 | size_t d; 146 | for (d = 0; d < size(); d++) { 147 | if (ts[d] == i) break; 148 | } 149 | for (; d < size(); d++) { 150 | for (auto r : matrix[ts[d]]) { 151 | dw[r.get_index()] = min(dw[r.get_index()], dw[ts[d]] + r.get_weight()); 152 | } 153 | } 154 | return dw[j]; 155 | } 156 | vector cycle() { 157 | vector colors(size(), 0), result; 158 | stack st; 159 | for (size_t i = 0; i < size(); i++) { 160 | bool f = dfs_cycl(i, colors, st); 161 | if (!f) { 162 | result.push_back(st.top()); 163 | st.pop(); 164 | while (st.top() != result[0]) { 165 | result.push_back(st.top()); 166 | st.pop(); 167 | } 168 | std::reverse(result.begin(), result.end()); 169 | break; 170 | } 171 | } 172 | return result; 173 | } 174 | }; 175 | 176 | int main() { 177 | size_t n, m; 178 | cin >> n >> m; 179 | oriental_graph g(n); 180 | for (size_t i = 0; i < m; i++) { 181 | size_t a, b; 182 | cin >> a >> b; 183 | g.add_edge(a - 1, b - 1); 184 | } 185 | vector c = g.cycle(); 186 | if (c.empty()) { 187 | cout << "NO" << endl; 188 | } else { 189 | cout << "YES" << endl; 190 | for (size_t i = 0; i < c.size(); i++) { 191 | cout << c[i] + 1 << " "; 192 | } 193 | } 194 | return 0; 195 | } -------------------------------------------------------------------------------- /lab09-dfs/src/g.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class graph { 9 | 10 | private: 11 | class edge { 12 | private: 13 | size_t index; 14 | int weight; 15 | public: 16 | edge() { 17 | index = 0; 18 | weight = 0; 19 | } 20 | explicit edge(size_t i, int w = 0) { 21 | index = i; 22 | weight = w; 23 | } 24 | size_t get_index() { 25 | return index; 26 | } 27 | int get_weight() { 28 | return weight; 29 | } 30 | }; 31 | vector> matrix; 32 | set> edges; 33 | 34 | void dfs_cc(size_t i, vector &colors, vector &cc) { 35 | if (colors[i] == 0) { 36 | colors[i]++; 37 | cc.push_back(i); 38 | if (matrix[i].empty()) return; 39 | for (auto &e : matrix[i]) { 40 | dfs_cc(e.get_index(), colors, cc); 41 | } 42 | } 43 | } 44 | 45 | public: 46 | graph() { 47 | matrix = vector>(); 48 | edges = set>(); 49 | } 50 | explicit graph(size_t n) { 51 | matrix = vector>(n, vector()); 52 | edges = set>(); 53 | } 54 | size_t size() { 55 | return matrix.size(); 56 | } 57 | bool is_edge(size_t i, size_t j) { 58 | return edges.count({i, j}) > 0 || edges.count({j, i}) > 0; 59 | } 60 | void add_edge(size_t i, size_t j, size_t w = 0) { 61 | if (is_edge(i, j)) return; 62 | matrix[i].emplace_back(j, w); 63 | matrix[j].emplace_back(i, w); 64 | edges.emplace(i, j); 65 | } 66 | void add_vertex() { 67 | matrix.emplace_back(); 68 | } 69 | 70 | vector get_components(size_t &k) { 71 | vector colors(size(), 0), result(size()); 72 | k = 0; 73 | for (size_t i = 0; i < size(); i++) { 74 | vector cc; 75 | dfs_cc(i, colors, cc); 76 | for (size_t j = 0; j < cc.size(); j++) { 77 | result[cc[j]] = k; 78 | } 79 | if (!cc.empty()) k++; 80 | cc.clear(); 81 | } 82 | return result; 83 | } 84 | }; 85 | 86 | int main() { 87 | freopen("components.in", "r", stdin); 88 | freopen("components.out", "w", stdout); 89 | 90 | size_t n, m; 91 | cin >> n >> m; 92 | graph g(n); 93 | for (size_t i = 0; i < m; i++) { 94 | size_t a, b; 95 | cin >> a >> b; 96 | g.add_edge(a - 1, b - 1); 97 | } 98 | size_t k = 0; 99 | vector comp = g.get_components(k); 100 | cout << k << endl; 101 | for (size_t i = 0; i < comp.size(); i++) { 102 | cout << comp[i] + 1 << " "; 103 | } 104 | return 0; 105 | } -------------------------------------------------------------------------------- /lab09-dfs/src/h.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class graph { 9 | 10 | private: 11 | class edge { 12 | private: 13 | size_t index; 14 | int weight; 15 | public: 16 | edge() { 17 | index = 0; 18 | weight = 0; 19 | } 20 | explicit edge(size_t i, int w = 0) { 21 | index = i; 22 | weight = w; 23 | } 24 | size_t get_index() { 25 | return index; 26 | } 27 | int get_weight() { 28 | return weight; 29 | } 30 | }; 31 | vector> matrix; 32 | set> edges; 33 | 34 | void dfs_cc(size_t i, vector &colors, vector &cc) { 35 | if (colors[i] == 0) { 36 | colors[i]++; 37 | cc.push_back(i); 38 | if (matrix[i].empty()) return; 39 | for (auto &e : matrix[i]) { 40 | dfs_cc(e.get_index(), colors, cc); 41 | } 42 | } 43 | } 44 | void dfs_br(size_t i, int q, vector &colors, vector &a, vector &b, vector &result, size_t &t) { 45 | colors[i]++; 46 | a[i] = b[i] = t++; 47 | for (auto &e : matrix[i]) { 48 | if (e.get_weight() == q) continue; 49 | if (colors[e.get_index()] == 1) { 50 | a[i] = min(a[i], b[e.get_index()]); 51 | } else { 52 | dfs_br(e.get_index(), e.get_weight(), colors, a, b, result, t); 53 | a[i] = min(a[i], a[e.get_index()]); 54 | if (a[e.get_index()] > b[i]) { 55 | result.push_back(e.get_weight()); 56 | } 57 | } 58 | } 59 | } 60 | 61 | public: 62 | graph() { 63 | matrix = vector>(); 64 | edges = set>(); 65 | } 66 | explicit graph(size_t n) { 67 | matrix = vector>(n, vector()); 68 | edges = set>(); 69 | } 70 | size_t size() { 71 | return matrix.size(); 72 | } 73 | bool is_edge(size_t i, size_t j) { 74 | return edges.count({i, j}) > 0; 75 | } 76 | void add_edge(size_t i, size_t j, size_t w = 0) { 77 | matrix[i].emplace_back(j, w); 78 | matrix[j].emplace_back(i, w); 79 | edges.emplace(i, j); 80 | edges.emplace(j, i); 81 | } 82 | void add_vertex() { 83 | matrix.emplace_back(); 84 | } 85 | 86 | vector get_components(size_t &k) { 87 | vector colors(size(), 0), result(size()); 88 | k = 0; 89 | for (size_t i = 0; i < size(); i++) { 90 | vector cc; 91 | dfs_cc(i, colors, cc); 92 | for (size_t j = 0; j < cc.size(); j++) { 93 | result[cc[j]] = k; 94 | } 95 | if (!cc.empty()) k++; 96 | cc.clear(); 97 | } 98 | return result; 99 | } 100 | vector bridges() { 101 | vector colors(size(), 0), a(size(), 0), b(size(), 0); 102 | vector result; 103 | size_t t = 0; 104 | for (size_t i = 0; i < size(); i++) { 105 | if (colors[i] == 0) { 106 | dfs_br(i, -1, colors, a, b, result, t); 107 | } 108 | } 109 | sort(result.begin(), result.end()); 110 | return result; 111 | } 112 | }; 113 | 114 | int main() { 115 | freopen("bridges.in", "r", stdin); 116 | freopen("bridges.out", "w", stdout); 117 | 118 | size_t n, m; 119 | cin >> n >> m; 120 | graph g(n); 121 | for (size_t i = 0; i < m; i++) { 122 | size_t a, b; 123 | cin >> a >> b; 124 | g.add_edge(a - 1, b - 1, i); 125 | } 126 | vector br = g.bridges(); 127 | cout << br.size() << endl; 128 | for (size_t i = 0; i < br.size(); i++) { 129 | cout << br[i] + 1 << " "; 130 | } 131 | return 0; 132 | } -------------------------------------------------------------------------------- /lab09-dfs/src/i.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class graph { 9 | 10 | private: 11 | class edge { 12 | private: 13 | size_t index; 14 | int weight; 15 | public: 16 | edge() { 17 | index = 0; 18 | weight = 0; 19 | } 20 | explicit edge(size_t i, int w = 0) { 21 | index = i; 22 | weight = w; 23 | } 24 | size_t get_index() { 25 | return index; 26 | } 27 | int get_weight() { 28 | return weight; 29 | } 30 | }; 31 | vector> matrix; 32 | set> edges; 33 | 34 | void dfs_cc(size_t i, vector &colors, vector &cc) { 35 | if (colors[i] == 0) { 36 | colors[i]++; 37 | cc.push_back(i); 38 | if (matrix[i].empty()) return; 39 | for (auto &e : matrix[i]) { 40 | dfs_cc(e.get_index(), colors, cc); 41 | } 42 | } 43 | } 44 | void dfs_br(size_t i, int q, vector &colors, vector &a, vector &b, vector &result, size_t &t) { 45 | colors[i]++; 46 | a[i] = b[i] = t++; 47 | for (auto &e : matrix[i]) { 48 | if (e.get_weight() == q) continue; 49 | if (colors[e.get_index()] == 1) { 50 | a[i] = min(a[i], b[e.get_index()]); 51 | } else { 52 | dfs_br(e.get_index(), e.get_weight(), colors, a, b, result, t); 53 | a[i] = min(a[i], a[e.get_index()]); 54 | if (a[e.get_index()] > b[i]) { 55 | result.push_back(e.get_weight()); 56 | } 57 | } 58 | } 59 | } 60 | void dfs_cv(size_t i, int q, vector &colors, vector &a, vector &b, set &result, size_t &t) { 61 | colors[i]++; 62 | size_t count = 0; 63 | a[i] = b[i] = t++; 64 | for (auto &e : matrix[i]) { 65 | if (e.get_weight() == q) continue; 66 | if (colors[e.get_index()] == 1) { 67 | a[i] = min(a[i], b[e.get_index()]); 68 | } else { 69 | dfs_cv(e.get_index(), e.get_weight(), colors, a, b, result, t); 70 | a[i] = min(a[i], a[e.get_index()]); 71 | if (a[e.get_index()] >= b[i] && q != -1) { 72 | result.insert(i); 73 | } 74 | count++; 75 | } 76 | } 77 | if (count > 1 && q == -1) { 78 | result.insert(i); 79 | } 80 | } 81 | 82 | public: 83 | graph() { 84 | matrix = vector>(); 85 | edges = set>(); 86 | } 87 | explicit graph(size_t n) { 88 | matrix = vector>(n, vector()); 89 | edges = set>(); 90 | } 91 | size_t size() { 92 | return matrix.size(); 93 | } 94 | bool is_edge(size_t i, size_t j) { 95 | return edges.count({i, j}) > 0; 96 | } 97 | void add_edge(size_t i, size_t j, size_t w = 0) { 98 | matrix[i].emplace_back(j, w); 99 | matrix[j].emplace_back(i, w); 100 | edges.emplace(i, j); 101 | edges.emplace(j, i); 102 | } 103 | void add_vertex() { 104 | matrix.emplace_back(); 105 | } 106 | 107 | vector get_components(size_t &k) { 108 | vector colors(size(), 0), result(size()); 109 | k = 0; 110 | for (size_t i = 0; i < size(); i++) { 111 | vector cc; 112 | dfs_cc(i, colors, cc); 113 | for (size_t j = 0; j < cc.size(); j++) { 114 | result[cc[j]] = k; 115 | } 116 | if (!cc.empty()) k++; 117 | cc.clear(); 118 | } 119 | return result; 120 | } 121 | vector bridges() { 122 | vector colors(size(), 0), a(size(), 0), b(size(), 0); 123 | vector result; 124 | size_t t = 0; 125 | for (size_t i = 0; i < size(); i++) { 126 | if (colors[i] == 0) { 127 | dfs_br(i, -1, colors, a, b, result, t); 128 | } 129 | } 130 | sort(result.begin(), result.end()); 131 | return result; 132 | } 133 | set cutvertex() { 134 | vector colors(size(), 0), a(size(), 0), b(size(), 0); 135 | set result; 136 | size_t t = 0; 137 | for (size_t i = 0; i < size(); i++) { 138 | if (colors[i] == 0) { 139 | dfs_cv(i, -1, colors, a, b, result, t); 140 | } 141 | } 142 | return result; 143 | } 144 | }; 145 | 146 | int main() { 147 | freopen("points.in", "r", stdin); 148 | freopen("points.out", "w", stdout); 149 | 150 | size_t n, m; 151 | cin >> n >> m; 152 | graph g(n); 153 | for (size_t i = 0; i < m; i++) { 154 | size_t a, b; 155 | cin >> a >> b; 156 | g.add_edge(a - 1, b - 1, i); 157 | } 158 | set cv = g.cutvertex(); 159 | cout << cv.size() << endl; 160 | for (auto &x : cv) { 161 | cout << x + 1 << " " ; 162 | } 163 | return 0; 164 | } -------------------------------------------------------------------------------- /lab09-dfs/src/j.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class graph { 9 | 10 | private: 11 | class edge { 12 | private: 13 | size_t index; 14 | int weight; 15 | public: 16 | edge() { 17 | index = 0; 18 | weight = 0; 19 | } 20 | explicit edge(size_t i, int w = 0) { 21 | index = i; 22 | weight = w; 23 | } 24 | size_t get_index() { 25 | return index; 26 | } 27 | int get_weight() { 28 | return weight; 29 | } 30 | }; 31 | vector> matrix; 32 | set> edges; 33 | 34 | void dfs_cc(size_t i, vector &colors, vector &cc) { 35 | if (colors[i] == 0) { 36 | colors[i]++; 37 | cc.push_back(i); 38 | if (matrix[i].empty()) return; 39 | for (auto &e : matrix[i]) { 40 | dfs_cc(e.get_index(), colors, cc); 41 | } 42 | } 43 | } 44 | void dfs_br(size_t i, int q, vector &colors, vector &a, vector &b, vector &result, size_t &t) { 45 | colors[i]++; 46 | a[i] = b[i] = t++; 47 | for (auto &e : matrix[i]) { 48 | if (e.get_weight() == q) continue; 49 | if (colors[e.get_index()] == 1) { 50 | a[i] = min(a[i], b[e.get_index()]); 51 | } else { 52 | dfs_br(e.get_index(), e.get_weight(), colors, a, b, result, t); 53 | a[i] = min(a[i], a[e.get_index()]); 54 | if (a[e.get_index()] > b[i]) { 55 | result.push_back(e.get_weight()); 56 | } 57 | } 58 | } 59 | } 60 | void dfs_cv(size_t i, int q, vector &colors, vector &a, vector &b, set &result, size_t &t) { 61 | colors[i]++; 62 | size_t count = 0; 63 | a[i] = b[i] = t++; 64 | for (auto &e : matrix[i]) { 65 | if (e.get_weight() == q) continue; 66 | if (colors[e.get_index()] == 1) { 67 | a[i] = min(a[i], b[e.get_index()]); 68 | } else { 69 | dfs_cv(e.get_index(), e.get_weight(), colors, a, b, result, t); 70 | a[i] = min(a[i], a[e.get_index()]); 71 | if (a[e.get_index()] >= b[i] && q != -1) { 72 | result.insert(i); 73 | } 74 | count++; 75 | } 76 | } 77 | if (count > 1 && q == -1) { 78 | result.insert(i); 79 | } 80 | } 81 | bool dfs_bi(size_t i, int color, vector &colors) { 82 | if (colors[i] == 0) { 83 | colors[i] = color; 84 | bool f = true; 85 | for (auto &e : matrix[i]) { 86 | f &= dfs_bi(e.get_index(), color - 2 * color, colors); 87 | if (!f) break; 88 | } 89 | return f; 90 | } else { 91 | return colors[i] == color; 92 | } 93 | } 94 | 95 | public: 96 | graph() { 97 | matrix = vector>(); 98 | edges = set>(); 99 | } 100 | explicit graph(size_t n) { 101 | matrix = vector>(n, vector()); 102 | edges = set>(); 103 | } 104 | size_t size() { 105 | return matrix.size(); 106 | } 107 | bool is_edge(size_t i, size_t j) { 108 | return edges.count({i, j}) > 0; 109 | } 110 | void add_edge(size_t i, size_t j, size_t w = 0) { 111 | matrix[i].emplace_back(j, w); 112 | matrix[j].emplace_back(i, w); 113 | edges.emplace(i, j); 114 | edges.emplace(j, i); 115 | } 116 | void add_vertex() { 117 | matrix.emplace_back(); 118 | } 119 | 120 | vector get_components(size_t &k) { 121 | vector colors(size(), 0), result(size()); 122 | k = 0; 123 | for (size_t i = 0; i < size(); i++) { 124 | vector cc; 125 | dfs_cc(i, colors, cc); 126 | for (size_t j = 0; j < cc.size(); j++) { 127 | result[cc[j]] = k; 128 | } 129 | if (!cc.empty()) k++; 130 | cc.clear(); 131 | } 132 | return result; 133 | } 134 | vector bridges() { 135 | vector colors(size(), 0), a(size(), 0), b(size(), 0); 136 | vector result; 137 | size_t t = 0; 138 | for (size_t i = 0; i < size(); i++) { 139 | if (colors[i] == 0) { 140 | dfs_br(i, -1, colors, a, b, result, t); 141 | } 142 | } 143 | sort(result.begin(), result.end()); 144 | return result; 145 | } 146 | set cutvertex() { 147 | vector colors(size(), 0), a(size(), 0), b(size(), 0); 148 | set result; 149 | size_t t = 0; 150 | for (size_t i = 0; i < size(); i++) { 151 | if (colors[i] == 0) { 152 | dfs_cv(i, -1, colors, a, b, result, t); 153 | } 154 | } 155 | return result; 156 | } 157 | bool is_bipartite() { 158 | vector colors(size(), 0); 159 | bool result = true; 160 | for (size_t i = 0; i < size(); i++) { 161 | if (colors[i] == 0) { 162 | result &= dfs_bi(i, 1, colors); 163 | } 164 | } 165 | return result; 166 | } 167 | }; 168 | 169 | int main() { 170 | freopen("bipartite.in", "r", stdin); 171 | freopen("bipartite.out", "w", stdout); 172 | 173 | size_t n, m; 174 | cin >> n >> m; 175 | graph g(n); 176 | for (size_t i = 0; i < m; i++) { 177 | size_t a, b; 178 | cin >> a >> b; 179 | g.add_edge(a - 1, b - 1, i); 180 | } 181 | bool f = g.is_bipartite(); 182 | if (f) { 183 | cout << "YES"; 184 | } else { 185 | cout << "NO"; 186 | } 187 | return 0; 188 | } -------------------------------------------------------------------------------- /lab09-dfs/src/k.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class graph { 9 | 10 | private: 11 | class edge { 12 | private: 13 | size_t index; 14 | int weight; 15 | public: 16 | edge() { 17 | index = 0; 18 | weight = 0; 19 | } 20 | explicit edge(size_t i, int w = 0) { 21 | index = i; 22 | weight = w; 23 | } 24 | size_t get_index() { 25 | return index; 26 | } 27 | int get_weight() { 28 | return weight; 29 | } 30 | }; 31 | vector> matrix; 32 | set> edges; 33 | 34 | void dfs_cc(size_t i, vector &colors, vector &cc) { 35 | if (colors[i] == 0) { 36 | colors[i]++; 37 | cc.push_back(i); 38 | if (matrix[i].empty()) return; 39 | for (auto &e : matrix[i]) { 40 | dfs_cc(e.get_index(), colors, cc); 41 | } 42 | } 43 | } 44 | void dfs_br(size_t i, int q, vector &colors, vector &a, vector &b, set &result, size_t &t) { 45 | colors[i]++; 46 | a[i] = b[i] = t++; 47 | for (auto &e : matrix[i]) { 48 | if (e.get_weight() == q) continue; 49 | if (colors[e.get_index()] == 1) { 50 | a[i] = min(a[i], b[e.get_index()]); 51 | } else { 52 | dfs_br(e.get_index(), e.get_weight(), colors, a, b, result, t); 53 | a[i] = min(a[i], a[e.get_index()]); 54 | if (a[e.get_index()] > b[i]) { 55 | result.insert(e.get_weight()); 56 | } 57 | } 58 | } 59 | } 60 | void dfs_cv(size_t i, int q, vector &colors, vector &a, vector &b, set &result, size_t &t) { 61 | colors[i]++; 62 | size_t count = 0; 63 | a[i] = b[i] = t++; 64 | for (auto &e : matrix[i]) { 65 | if (e.get_weight() == q) continue; 66 | if (colors[e.get_index()] == 1) { 67 | a[i] = min(a[i], b[e.get_index()]); 68 | } else { 69 | dfs_cv(e.get_index(), e.get_weight(), colors, a, b, result, t); 70 | a[i] = min(a[i], a[e.get_index()]); 71 | if (a[e.get_index()] >= b[i] && q != -1) { 72 | result.insert(i); 73 | } 74 | count++; 75 | } 76 | } 77 | if (count > 1 && q == -1) { 78 | result.insert(i); 79 | } 80 | } 81 | bool dfs_bi(size_t i, int color, vector &colors) { 82 | if (colors[i] == 0) { 83 | colors[i] = color; 84 | bool f = true; 85 | for (auto &e : matrix[i]) { 86 | f &= dfs_bi(e.get_index(), color - 2 * color, colors); 87 | if (!f) break; 88 | } 89 | return f; 90 | } else { 91 | return colors[i] == color; 92 | } 93 | } 94 | void dfs_ecc(size_t i, vector &colors, set &br, vector &result, size_t &k, size_t t) { 95 | colors[i]++; 96 | result[i] = t - 1; 97 | for (auto &e: matrix[i]) { 98 | if (colors[e.get_index()] == 0) { 99 | if (br.count(e.get_weight()) > 0) { 100 | k++; 101 | dfs_ecc(e.get_index(), colors, br, result, k, k); 102 | } else { 103 | dfs_ecc(e.get_index(), colors, br, result, k, t); 104 | } 105 | } 106 | } 107 | } 108 | 109 | public: 110 | graph() { 111 | matrix = vector>(); 112 | edges = set>(); 113 | } 114 | explicit graph(size_t n) { 115 | matrix = vector>(n, vector()); 116 | edges = set>(); 117 | } 118 | size_t size() { 119 | return matrix.size(); 120 | } 121 | bool is_edge(size_t i, size_t j) { 122 | return edges.count({i, j}) > 0; 123 | } 124 | void add_edge(size_t i, size_t j, size_t w = 0) { 125 | matrix[i].emplace_back(j, w); 126 | matrix[j].emplace_back(i, w); 127 | edges.emplace(i, j); 128 | edges.emplace(j, i); 129 | } 130 | void add_vertex() { 131 | matrix.emplace_back(); 132 | } 133 | 134 | vector get_components(size_t &k) { 135 | vector colors(size(), 0), result(size()); 136 | k = 0; 137 | for (size_t i = 0; i < size(); i++) { 138 | vector cc; 139 | dfs_cc(i, colors, cc); 140 | for (size_t j = 0; j < cc.size(); j++) { 141 | result[cc[j]] = k; 142 | } 143 | if (!cc.empty()) k++; 144 | cc.clear(); 145 | } 146 | return result; 147 | } 148 | set bridges() { 149 | vector colors(size(), 0), a(size(), 0), b(size(), 0); 150 | set result; 151 | size_t t = 0; 152 | for (size_t i = 0; i < size(); i++) { 153 | if (colors[i] == 0) { 154 | dfs_br(i, -1, colors, a, b, result, t); 155 | } 156 | } 157 | return result; 158 | } 159 | set cutvertex() { 160 | vector colors(size(), 0), a(size(), 0), b(size(), 0); 161 | set result; 162 | size_t t = 0; 163 | for (size_t i = 0; i < size(); i++) { 164 | if (colors[i] == 0) { 165 | dfs_cv(i, -1, colors, a, b, result, t); 166 | } 167 | } 168 | return result; 169 | } 170 | bool is_bipartite() { 171 | vector colors(size(), 0); 172 | bool result = true; 173 | for (size_t i = 0; i < size(); i++) { 174 | if (colors[i] == 0) { 175 | result &= dfs_bi(i, 1, colors); 176 | } 177 | } 178 | return result; 179 | } 180 | vector get_edge_comp(size_t &k) { 181 | vector colors(size(), 0), result(size(), 0); 182 | set br = bridges(); 183 | k = 0; 184 | for (size_t i = 0; i < size(); i++) { 185 | if (colors[i] == 0) { 186 | k++; 187 | dfs_ecc(i, colors, br, result, k, k); 188 | } 189 | } 190 | return result; 191 | } 192 | }; 193 | 194 | int main() { 195 | freopen("bicone.in", "r", stdin); 196 | freopen("bicone.out", "w", stdout); 197 | 198 | size_t n, m; 199 | cin >> n >> m; 200 | graph g(n); 201 | for (size_t i = 0; i < m; i++) { 202 | size_t a, b; 203 | cin >> a >> b; 204 | g.add_edge(a - 1, b - 1, i); 205 | } 206 | size_t k = 0; 207 | vector ecc = g.get_edge_comp(k); 208 | cout << k << endl; 209 | for (size_t i = 0; i < ecc.size(); i++) { 210 | cout << ecc[i] + 1 << " "; 211 | } 212 | return 0; 213 | } -------------------------------------------------------------------------------- /lab09-dfs/tasks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cannor147/itmo-algo/96ec8f28c0af1005b9cb2870e4c68d65a7d8a941/lab09-dfs/tasks.pdf -------------------------------------------------------------------------------- /lab10-shortest-spanning/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(lab10_shortest_spanning) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_executable(a src/a.cpp) 7 | add_executable(d src/d.cpp) 8 | add_executable(e src/e.cpp) 9 | add_executable(f src/f.cpp) 10 | add_executable(g src/g.cpp) 11 | add_executable(h src/h.cpp) 12 | -------------------------------------------------------------------------------- /lab10-shortest-spanning/src/g.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | class graph { 13 | 14 | private: 15 | vector> vertexes; 16 | 17 | public: 18 | graph() { 19 | vertexes = vector>(); 20 | } 21 | size_t size() { 22 | return vertexes.size(); 23 | } 24 | double get_edge(size_t i, size_t j) { 25 | int a = vertexes[i].first, b = vertexes[i].second; 26 | int a1 = vertexes[j].first, b1 = vertexes[j].second; 27 | return sqrt((a - a1) * (a - a1) + (b - b1) * (b - b1)); 28 | } 29 | void add_vertex(int a, int b) { 30 | vertexes.emplace_back(a, b); 31 | } 32 | 33 | double get_mst_weight() { 34 | double result = 0; 35 | vector colors(size(), 0); 36 | vector minw(size(), DBL_MAX); 37 | minw[0] = 0; 38 | for (size_t i = 0; i < size(); i++) { 39 | size_t min_j = SIZE_MAX; 40 | for (size_t j = 0; j < size(); j++) { 41 | if ((colors[j] == 0) && (min_j == SIZE_MAX || minw[j] < minw[min_j])) { 42 | min_j = j; 43 | } 44 | } 45 | colors[min_j] = 1; 46 | result += minw[min_j]; 47 | for (size_t j = 0; j < size(); j++) { 48 | if (j == min_j) continue; 49 | if (get_edge(j, min_j) < minw[j]) { 50 | minw[j] = get_edge(j, min_j); 51 | } 52 | } 53 | } 54 | return result; 55 | } 56 | }; 57 | 58 | int main() { 59 | size_t n; 60 | cin >> n; 61 | graph g; 62 | for (size_t i = 0; i < n; i++) { 63 | int a, b; 64 | cin >> a >> b; 65 | g.add_vertex(a, b); 66 | } 67 | double mst = g.get_mst_weight(); 68 | cout << fixed << setprecision(15) << mst; 69 | return 0; 70 | } -------------------------------------------------------------------------------- /lab10-shortest-spanning/tasks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cannor147/itmo-algo/96ec8f28c0af1005b9cb2870e4c68d65a7d8a941/lab10-shortest-spanning/tasks.pdf -------------------------------------------------------------------------------- /lab11-matching/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(lab11_matching) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_executable(c src/c.cpp) 7 | add_executable(d src/d.cpp) 8 | -------------------------------------------------------------------------------- /lab11-matching/src/c.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | class bipartial_graph { 7 | 8 | private: 9 | vector> right, left; 10 | bool dfs_kunh(size_t i, vector &colors, vector &matching) { 11 | if (colors[i] == 0) { 12 | colors[i] = 1; 13 | for (auto j : right[i]) { 14 | if (matching[j] == SIZE_MAX || dfs_kunh(matching[j], colors, matching)) { 15 | matching[j] = i; 16 | return true; 17 | } 18 | } 19 | } 20 | return false; 21 | } 22 | void dfs_mvc(size_t i, vector &now, vector &next, bool o) { 23 | if (now[i] == 1) return; 24 | now[i] = 1; 25 | vector> &n = (o) ? left : right; 26 | for (size_t j = 0; j < n[i].size(); j++) { 27 | dfs_mvc(n[i][j], next, now, !o); 28 | } 29 | } 30 | 31 | public: 32 | bipartial_graph(size_t n, size_t m) { 33 | left.resize(n); 34 | right.resize(m); 35 | } 36 | void add_edge(size_t i, size_t j) { 37 | add_ledge(i, j); 38 | add_redge(i, j); 39 | } 40 | void add_ledge(size_t i, size_t j) { 41 | left[i].push_back(j); 42 | } 43 | void add_redge(size_t i, size_t j) { 44 | right[j].push_back(i); 45 | } 46 | size_t lsize() { 47 | return left.size(); 48 | } 49 | size_t rsize() { 50 | return right.size(); 51 | } 52 | 53 | vector> find_maximum_matching() { 54 | vector matching(lsize(), SIZE_MAX); 55 | for (size_t i = 0; i < rsize(); i++) { 56 | vector colors(rsize(), 0); 57 | dfs_kunh(i, colors, matching); 58 | } 59 | vector> result; 60 | for (size_t i = 0; i < lsize(); i++) { 61 | if (matching[i] != SIZE_MAX) { 62 | result.push_back({i, matching[i]}); 63 | } 64 | } 65 | return result; 66 | } 67 | pair, vector> find_minimum_vertex_covering(vector &free) { 68 | vector lcolors(lsize(), 0), rcolors(rsize(), 0); 69 | for (size_t i = 0; i < free.size(); i++) { 70 | dfs_mvc(free[i], lcolors, rcolors, true); 71 | } 72 | vector rresult, lresult; 73 | for (size_t i = 0; i < lsize(); i++) { 74 | if (lcolors[i] == 0) { 75 | lresult.push_back(i); 76 | } 77 | } 78 | for (size_t i = 0; i < rsize(); i++) { 79 | if (rcolors[i] == 1) { 80 | rresult.push_back(i); 81 | } 82 | } 83 | return {lresult, rresult}; 84 | } 85 | }; 86 | 87 | int main() { 88 | size_t n, m; 89 | cin >> n >> m; 90 | bipartial_graph g(n, m); 91 | vector> edges(n); 92 | for (size_t i = 0; i < n; i++) { 93 | size_t k; 94 | cin >> k; 95 | edges[i].resize(k); 96 | for (size_t j = 0; j < k; j++) { 97 | cin >> edges[i][j]; 98 | edges[i][j]--; 99 | } 100 | } 101 | vector free; 102 | for (size_t i = 0; i < n; i++) { 103 | size_t b; 104 | cin >> b; 105 | if (!b) { 106 | free.push_back(i); 107 | b = SIZE_MAX; 108 | } else { 109 | b--; 110 | } 111 | for (size_t j = 0; j < edges[i].size(); j++) { 112 | if (edges[i][j] == b) { 113 | g.add_redge(i, edges[i][j]); 114 | } else { 115 | g.add_ledge(i, edges[i][j]); 116 | } 117 | } 118 | } 119 | auto ans = g.find_minimum_vertex_covering(free); 120 | cout << ans.first.size() + ans.second.size(); 121 | cout << endl << ans.first.size() << " "; 122 | for (auto i : ans.first) { 123 | cout << i + 1 << " "; 124 | } 125 | cout << endl << ans.second.size() << " "; 126 | for (auto i : ans.second) { 127 | cout << i + 1 << " "; 128 | } 129 | return 0; 130 | } -------------------------------------------------------------------------------- /lab11-matching/src/d.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | class bipartial_graph { 7 | 8 | private: 9 | vector> right, left; 10 | bool dfs_kunh(size_t i, vector &colors, vector &matching) { 11 | if (colors[i] == 0) { 12 | colors[i] = 1; 13 | for (auto j : right[i]) { 14 | if (matching[j] == SIZE_MAX || dfs_kunh(matching[j], colors, matching)) { 15 | matching[j] = i; 16 | return true; 17 | } 18 | } 19 | } 20 | return false; 21 | } 22 | void dfs_mvc(size_t i, vector &now, vector &next, bool o) { 23 | if (now[i] == 1) return; 24 | now[i] = 1; 25 | vector> &n = (o) ? left : right; 26 | for (size_t j = 0; j < n[i].size(); j++) { 27 | dfs_mvc(n[i][j], next, now, !o); 28 | } 29 | } 30 | pair, vector> fill_mvc(vector &free) { 31 | vector lcolors(lsize(), 0), rcolors(rsize(), 0); 32 | for (size_t i = 0; i < free.size(); i++) { 33 | if (free[i] == 1) continue; 34 | dfs_mvc(i, lcolors, rcolors, true); 35 | } 36 | return {lcolors, rcolors}; 37 | } 38 | 39 | public: 40 | bipartial_graph(size_t n, size_t m) { 41 | left.resize(n); 42 | right.resize(m); 43 | } 44 | void add_edge(size_t i, size_t j) { 45 | add_ledge(i, j); 46 | add_redge(i, j); 47 | } 48 | void add_ledge(size_t i, size_t j) { 49 | left[i].push_back(j); 50 | } 51 | void add_redge(size_t i, size_t j) { 52 | right[j].push_back(i); 53 | } 54 | size_t lsize() { 55 | return left.size(); 56 | } 57 | size_t rsize() { 58 | return right.size(); 59 | } 60 | 61 | vector> find_maximum_matching() { 62 | vector matching(lsize(), SIZE_MAX); 63 | for (size_t i = 0; i < rsize(); i++) { 64 | vector colors(rsize(), 0); 65 | dfs_kunh(i, colors, matching); 66 | } 67 | vector> result; 68 | for (size_t i = 0; i < lsize(); i++) { 69 | if (matching[i] != SIZE_MAX) { 70 | result.push_back({i, matching[i]}); 71 | } 72 | } 73 | return result; 74 | } 75 | pair, vector> find_minimum_vertex_covering() { 76 | auto max_matching = find_maximum_matching(); 77 | vector free(lsize(), 0), matched(lsize()); 78 | for (size_t i = 0; i < max_matching.size(); i++) { 79 | free[max_matching[i].first] = 1; 80 | matched[max_matching[i].first] = max_matching[i].second; 81 | } 82 | bipartial_graph u(lsize(), rsize()); 83 | for (size_t i = 0; i < lsize(); i++) { 84 | for (size_t j = 0; j < left[i].size(); j++) { 85 | if (free[i] == 1 || matched[i] == left[i][j]) { 86 | u.add_redge(i, left[i][j]); 87 | } else { 88 | u.add_ledge(i, left[i][j]); 89 | } 90 | } 91 | } 92 | auto result = u.fill_mvc(free); 93 | vector rresult, lresult; 94 | for (size_t i = 0; i < lsize(); i++) { 95 | if (result.first[i] == 0) { 96 | lresult.push_back(i); 97 | } 98 | } 99 | for (size_t i = 0; i < rsize(); i++) { 100 | if (result.second[i] == 1) { 101 | rresult.push_back(i); 102 | } 103 | } 104 | return {lresult, rresult}; 105 | } 106 | pair, vector> find_maximum_indepentent_set() { 107 | auto max_matching = find_maximum_matching(); 108 | vector free(lsize(), 0), matched(lsize()); 109 | for (size_t i = 0; i < max_matching.size(); i++) { 110 | free[max_matching[i].first] = 1; 111 | matched[max_matching[i].first] = max_matching[i].second; 112 | } 113 | bipartial_graph u(lsize(), rsize()); 114 | for (size_t i = 0; i < lsize(); i++) { 115 | for (size_t j = 0; j < left[i].size(); j++) { 116 | if (free[i] == 1 && matched[i] == left[i][j]) { 117 | u.add_redge(i, left[i][j]); 118 | } else { 119 | u.add_ledge(i, left[i][j]); 120 | } 121 | } 122 | } 123 | auto result = u.fill_mvc(free); 124 | vector rresult, lresult; 125 | for (size_t i = 0; i < lsize(); i++) { 126 | if (result.first[i] == 1) { 127 | lresult.push_back(i); 128 | } 129 | } 130 | for (size_t i = 0; i < rsize(); i++) { 131 | if (result.second[i] == 0) { 132 | rresult.push_back(i); 133 | } 134 | } 135 | return {lresult, rresult}; 136 | } 137 | }; 138 | 139 | void kek() { 140 | size_t n, m; 141 | cin >> n >> m; 142 | bipartial_graph g(n, m); 143 | vector> edges(n, vector(m, 0)); 144 | for (size_t i = 0; i < n; i++) { 145 | bool f = true; 146 | while (f) { 147 | size_t w; 148 | cin >> w; 149 | if (w == 0) { 150 | f = false; 151 | } else { 152 | edges[i][w - 1]++; 153 | } 154 | } 155 | } 156 | for (size_t i = 0; i < n; i++) { 157 | for (size_t j = 0; j < m; j++) { 158 | if (edges[i][j] == 1) continue; 159 | g.add_edge(i, j); 160 | } 161 | } 162 | auto ans = g.find_maximum_indepentent_set(); 163 | cout << ans.first.size() + ans.second.size() << endl; 164 | cout << ans.first.size() << " " << ans.second.size() << endl; 165 | for (auto i : ans.first) { 166 | cout << i + 1 << " "; 167 | } 168 | cout << endl; 169 | for (auto i : ans.second) { 170 | cout << i + 1 << " "; 171 | } 172 | cout << endl << endl; 173 | } 174 | 175 | int main() { 176 | size_t k; 177 | cin >> k; 178 | for (size_t i = 0; i < k; i++) { 179 | kek(); 180 | } 181 | return 0; 182 | } -------------------------------------------------------------------------------- /lab11-matching/tasks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cannor147/itmo-algo/96ec8f28c0af1005b9cb2870e4c68d65a7d8a941/lab11-matching/tasks.pdf -------------------------------------------------------------------------------- /lab12-flow/tasks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cannor147/itmo-algo/96ec8f28c0af1005b9cb2870e4c68d65a7d8a941/lab12-flow/tasks.pdf -------------------------------------------------------------------------------- /lab13-strings/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(lab13_strings) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_executable(a src/a.cpp) 7 | add_executable(b src/b.cpp) 8 | add_executable(c src/c.cpp) 9 | add_executable(d src/d.cpp) 10 | add_executable(f src/f.cpp) 11 | add_executable(g draft/g.cpp) -------------------------------------------------------------------------------- /lab13-strings/draft/g.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | namespace my_min_max { 9 | 10 | size_t max(size_t x, size_t y) { 11 | return (x < y) ? y : x; 12 | } 13 | size_t min(size_t x, size_t y) { 14 | return (x < y) ? x : y; 15 | } 16 | } 17 | 18 | vector prefix_function(const string &s) { 19 | vector p(s.length(), 0); 20 | for (size_t i = 1; i < s.length(); i++) { 21 | p[i] = p[i - 1]; 22 | while (p[i] > 0 && s[i] != s[p[i]]) { 23 | p[i] = p[p[i] - 1]; 24 | } 25 | if (s[i] == s[p[i]]) p[i]++; 26 | } 27 | return p; 28 | } 29 | 30 | vector z_function(const string &s) { 31 | size_t last = 0, bound = 0; 32 | vector z(s.length(), 0); 33 | for (size_t i = 1; i < s.length(); i++) { 34 | if (i < bound) z[i] = my_min_max::max(0, my_min_max::min(z[i - last], bound - i)); 35 | while (i + z[i] < s.length() && s[z[i]] == s[i + z[i]]) { 36 | z[i]++; 37 | } 38 | if (i + z[i] > bound) { 39 | last = i; 40 | bound = i + z[i]; 41 | } 42 | } 43 | z[0] = s.length(); 44 | return z; 45 | } 46 | 47 | vector suffix_array(string &s) { 48 | size_t n = s.length(); 49 | vector result(n); 50 | // n 51 | for (size_t i = 0; i < n; i++) { 52 | result[i] = i; 53 | } 54 | // nlogn 55 | std::sort(result.begin(), result.end(), [&](const size_t &s1, const size_t &s2) { 56 | return s[s1] < s[s2]; 57 | }); 58 | 59 | std::vector cl(n); 60 | cl[result[0]] = 0; 61 | // n 62 | for (size_t i = 1; i < n; i++) { 63 | cl[result[i]] = cl[result[i - 1]]; 64 | if (s[result[i]] != s[result[i - 1]]) { 65 | cl[result[i]]++; 66 | } 67 | } 68 | bool f = true; 69 | 70 | // nlog^2n + nlogn 71 | for (size_t count = 1; f; count = my_min_max::min(count * 2, n)) { 72 | // 73 | std::sort(result.begin(), result.end(), [&] (const size_t &s1, const size_t &s2) { 74 | if (cl[s1] != cl[s2]) return cl[s1] < cl[s2]; 75 | return cl[(s1 + count) % n] < cl[(s2 + count) % n]; 76 | }); 77 | 78 | std::vector tmp(n); 79 | tmp[result[0]] = 0; 80 | for (size_t i = 1; i < n; i++) { 81 | tmp[result[i]] = tmp[result[i - 1]]; 82 | if (cl[result[i]] != cl[result[i - 1]]) { 83 | tmp[result[i]]++; 84 | continue; 85 | } 86 | if (cl[(result[i] + count) % n] != cl[(result[i - 1] + count) % n]) { 87 | tmp[result[i]]++; 88 | } 89 | } 90 | for (size_t i = 0; i < n; i++) { 91 | cl[i] = tmp[i]; 92 | } 93 | tmp.clear(); 94 | f = count < n; 95 | } 96 | return result; 97 | } 98 | 99 | // summary 2 * 10^7 + 10^6 100 | bool is_substring(string &p, string &t, vector &suf) { 101 | // for (auto x : suf) cout << x << endl; 102 | 103 | size_t l = 0, r = suf.size() - 1, m; 104 | while (r >= l) { 105 | m = l + (r - l) / 2; 106 | bool f = false; 107 | size_t i; 108 | for (i = 0; i < p.length() && i < t.length() - suf[m]; i++) { 109 | if (t[suf[m] + i] < p[i]) f = true; 110 | if (t[suf[m] + i] > p[i]) f = false; 111 | if (t[suf[m] + i] != p[i]) { 112 | i = 0; 113 | break; 114 | } 115 | } 116 | if (i == t.length() - suf[m]) f = true; 117 | if (i == p.length()) f = false; 118 | if (f) { 119 | l = m + 1; 120 | } else { 121 | if (l == r) break; 122 | r = m; 123 | } 124 | // cout << l << " " << m << " " << r << endl; 125 | } 126 | // cout << t.substr(suf[l], t.length() - suf[l]) << endl; 127 | if (l > suf.size() - 1 || p.length() > t.length() - suf[l]) return false; 128 | for (size_t i = 0; i < p.length(); i++) { 129 | if (t[suf[l] + i] != p[i]) return false; 130 | } 131 | return true; 132 | } 133 | 134 | int main() { 135 | size_t n; 136 | cin >> n; 137 | vector str(n); 138 | for (size_t i = 0; i < n; i++) { 139 | cin >> str[i]; 140 | } 141 | 142 | string c; 143 | cin >> c; 144 | c += "&"; 145 | auto suf = suffix_array(c); 146 | 147 | for (size_t i = 0; i < n; i++) { 148 | if (is_substring(str[i], c, suf)) { 149 | cout << "YES" << endl; 150 | } else { 151 | cout << "NO" << endl; 152 | } 153 | } 154 | return 0; 155 | } -------------------------------------------------------------------------------- /lab13-strings/src/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | string p, t; 8 | cin >> p; 9 | cin >> t; 10 | if (p.length() > t.length()) { 11 | cout << 0; 12 | return 0; 13 | } 14 | vector ans; 15 | for (size_t i = 0; i <= t.length() - p.length(); i++) { 16 | bool f = true; 17 | for (size_t j = 0; j < p.length(); j++) { 18 | if (t[i + j] != p[j]) f = false; 19 | if (!f) break; 20 | } 21 | if (f) { 22 | ans.push_back(i); 23 | } 24 | } 25 | cout << ans.size() << endl; 26 | for (size_t i = 0; i < ans.size(); i++) { 27 | cout << ans[i] + 1 << " "; 28 | } 29 | return 0; 30 | } -------------------------------------------------------------------------------- /lab13-strings/src/b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | namespace my_min_max { 8 | 9 | size_t max(size_t x, size_t y) { 10 | return (x < y) ? y : x; 11 | } 12 | size_t min(size_t x, size_t y) { 13 | return (x < y) ? x : y; 14 | } 15 | } 16 | 17 | vector z_function(const string &s) { 18 | size_t last = 0, bound = 0; 19 | vector z(s.length(), 0); 20 | for (size_t i = 1; i < s.length(); i++) { 21 | if (i < bound) z[i] = my_min_max::max(0, my_min_max::min(z[i - last], bound - i)); 22 | while (i + z[i] < s.length() && s[z[i]] == s[i + z[i]]) { 23 | z[i]++; 24 | } 25 | if (i + z[i] > bound) { 26 | last = i; 27 | bound = i + z[i]; 28 | } 29 | } 30 | z[0] = s.length(); 31 | return z; 32 | } 33 | 34 | int main() { 35 | string p, t; 36 | cin >> p >> t; 37 | if (p.length() > t.length()) { 38 | cout << 0; 39 | return 0; 40 | } 41 | string c = p + t; 42 | auto z = z_function(c); 43 | vector ans; 44 | for (size_t i = p.length(); i < z.size(); i++) { 45 | if (z[i] >= p.length()) ans.push_back(i); 46 | } 47 | cout << ans.size() << endl; 48 | for (auto x : ans) { 49 | cout << x - p.length() + 1 << " "; 50 | } 51 | return 0; 52 | } -------------------------------------------------------------------------------- /lab13-strings/src/c.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | namespace my_min_max { 8 | 9 | size_t max(size_t x, size_t y) { 10 | return (x < y) ? y : x; 11 | } 12 | size_t min(size_t x, size_t y) { 13 | return (x < y) ? x : y; 14 | } 15 | } 16 | 17 | vector prefix_function(const string &s) { 18 | vector p(s.length(), 0); 19 | for (size_t i = 1; i < s.length(); i++) { 20 | p[i] = p[i - 1]; 21 | while (p[i] > 0 && s[i] != s[p[i]]) { 22 | p[i] = p[p[i] - 1]; 23 | } 24 | if (s[i] == s[p[i]]) p[i]++; 25 | } 26 | return p; 27 | } 28 | 29 | vector z_function(const string &s) { 30 | size_t last = 0, bound = 0; 31 | vector z(s.length(), 0); 32 | for (size_t i = 1; i < s.length(); i++) { 33 | if (i < bound) z[i] = my_min_max::max(0, my_min_max::min(z[i - last], bound - i)); 34 | while (i + z[i] < s.length() && s[z[i]] == s[i + z[i]]) { 35 | z[i]++; 36 | } 37 | if (i + z[i] > bound) { 38 | last = i; 39 | bound = i + z[i]; 40 | } 41 | } 42 | z[0] = s.length(); 43 | return z; 44 | } 45 | 46 | int main() { 47 | string c; 48 | cin >> c; 49 | auto ans = prefix_function(c); 50 | for (size_t i = 0; i < ans.size(); i++) { 51 | cout << ans[i] << " "; 52 | } 53 | return 0; 54 | } -------------------------------------------------------------------------------- /lab13-strings/src/d.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | namespace my_min_max { 8 | 9 | size_t max(size_t x, size_t y) { 10 | return (x < y) ? y : x; 11 | } 12 | size_t min(size_t x, size_t y) { 13 | return (x < y) ? x : y; 14 | } 15 | } 16 | 17 | vector z_function(const string &s) { 18 | size_t last = 0, bound = 0; 19 | vector z(s.length(), 0); 20 | for (size_t i = 1; i < s.length(); i++) { 21 | if (i < bound) z[i] = my_min_max::max(0, my_min_max::min(z[i - last], bound - i)); 22 | while (i + z[i] < s.length() && s[z[i]] == s[i + z[i]]) { 23 | z[i]++; 24 | } 25 | if (i + z[i] > bound) { 26 | last = i; 27 | bound = i + z[i]; 28 | } 29 | } 30 | z[0] = s.length(); 31 | return z; 32 | } 33 | 34 | int main() { 35 | string c; 36 | cin >> c; 37 | auto ans = z_function(c); 38 | for (size_t i = 1; i < ans.size(); i++) { 39 | cout << ans[i] << " "; 40 | } 41 | return 0; 42 | } -------------------------------------------------------------------------------- /lab13-strings/src/f.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | namespace my_min_max { 8 | 9 | size_t max(size_t x, size_t y) { 10 | return (x < y) ? y : x; 11 | } 12 | size_t min(size_t x, size_t y) { 13 | return (x < y) ? x : y; 14 | } 15 | } 16 | 17 | vector prefix_function(const string &s) { 18 | vector p(s.length(), 0); 19 | for (size_t i = 1; i < s.length(); i++) { 20 | p[i] = p[i - 1]; 21 | while (p[i] > 0 && s[i] != s[p[i]]) { 22 | p[i] = p[p[i] - 1]; 23 | } 24 | if (s[i] == s[p[i]]) p[i]++; 25 | } 26 | return p; 27 | } 28 | 29 | vector z_function(const string &s) { 30 | size_t last = 0, bound = 0; 31 | vector z(s.length(), 0); 32 | for (size_t i = 1; i < s.length(); i++) { 33 | if (i < bound) z[i] = my_min_max::max(0, my_min_max::min(z[i - last], bound - i)); 34 | while (i + z[i] < s.length() && s[z[i]] == s[i + z[i]]) { 35 | z[i]++; 36 | } 37 | if (i + z[i] > bound) { 38 | last = i; 39 | bound = i + z[i]; 40 | } 41 | } 42 | z[0] = s.length(); 43 | return z; 44 | } 45 | 46 | int main() { 47 | string c; 48 | cin >> c; 49 | auto z = z_function(c); 50 | for (size_t i = 1; i < z.size(); i++) { 51 | if (z.size() % i != 0) continue; 52 | size_t v = z.size() / i; 53 | if (z[i] == (v - 1) * i) { 54 | cout << i; 55 | return 0; 56 | } 57 | } 58 | cout << z.size(); 59 | return 0; 60 | } -------------------------------------------------------------------------------- /lab13-strings/tasks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cannor147/itmo-algo/96ec8f28c0af1005b9cb2870e4c68d65a7d8a941/lab13-strings/tasks.pdf -------------------------------------------------------------------------------- /lab14-suffix/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(lab14_suffix) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_executable(a src/a.cpp) 7 | add_executable(b src/b.cpp) 8 | add_executable(c src/c.cpp) 9 | add_executable(d src/d.cpp) 10 | add_executable(e src/e.cpp) 11 | add_executable(f src/f.cpp) 12 | add_executable(g src/g.cpp) 13 | add_executable(i draft/i.cpp) 14 | add_executable(j src/j.cpp) -------------------------------------------------------------------------------- /lab14-suffix/src/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | class suffix_bor { 8 | 9 | struct bor_node { 10 | int index; 11 | std::map children; 12 | 13 | explicit bor_node(int index) : index(index) {} 14 | bor_node() : index(0) {} 15 | 16 | void add_node(int ut, char symbol) { 17 | children[symbol] = new bor_node(ut); 18 | } 19 | }; 20 | 21 | bor_node head; 22 | 23 | public: 24 | explicit suffix_bor(const std::string &word) { 25 | int number = 1; 26 | for (int i = 0; i < word.length(); ++i) { 27 | std::string suffix = word.substr(i, word.length() - i); 28 | int index = 0; 29 | bor_node *current = &head; 30 | 31 | while (index < suffix.length()) { 32 | if (current->children.count(suffix[index]) == 0) { 33 | current->add_node(number, suffix[index]); 34 | number++; 35 | } 36 | current = current->children[suffix[index]]; 37 | index++; 38 | } 39 | } 40 | } 41 | 42 | std::vector, char>> to_vector() { 43 | std::queue q; 44 | q.push(&head); 45 | 46 | std::vector, char>> result; 47 | while (!q.empty()) { 48 | bor_node *current = q.front(); 49 | q.pop(); 50 | 51 | if (current->children.empty()) continue; 52 | for (const auto &child : current->children) { 53 | result.push_back({{current->index, child.second->index}, child.first}); 54 | q.push(child.second); 55 | } 56 | } 57 | std::sort(result.begin(), result.end(), [](std::pair, char> a, std::pair, char> b) { return a.first.second < b.first.second; }); 58 | std::sort(result.begin(), result.end(), [](std::pair, char> a, std::pair, char> b) { return a.first.first < b.first.first; }); 59 | return result; 60 | } 61 | }; 62 | 63 | int main() { 64 | std::string word; 65 | std::cin >> word; 66 | suffix_bor bor = suffix_bor(word); 67 | 68 | auto ans = bor.to_vector(); 69 | int vertex = 0; 70 | for (const auto &item : ans) { 71 | if (item.first.first > vertex) { 72 | vertex = item.first.first; 73 | } 74 | if (item.first.second > vertex) { 75 | vertex = item.first.second; 76 | } 77 | } 78 | std::cout << vertex + 1 << " " << ans.size() << std::endl; 79 | for (const auto &item : ans) { 80 | std::cout << item.first.first + 1 << " " << item.first.second + 1 << " " << item.second << std::endl; 81 | } 82 | return 0; 83 | } -------------------------------------------------------------------------------- /lab14-suffix/tasks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cannor147/itmo-algo/96ec8f28c0af1005b9cb2870e4c68d65a7d8a941/lab14-suffix/tasks.pdf -------------------------------------------------------------------------------- /lab15-exp/tasks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cannor147/itmo-algo/96ec8f28c0af1005b9cb2870e4c68d65a7d8a941/lab15-exp/tasks.pdf -------------------------------------------------------------------------------- /lab16-numbers/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(lab16_numbers) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | 6 | add_executable(a src/a.cpp) 7 | add_executable(b src/b.cpp) 8 | add_executable(g draft/g.cpp) -------------------------------------------------------------------------------- /lab16-numbers/draft/g.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | long long pow(long long a, long long b, long long n) { 6 | long long result = 1; 7 | while (b > 0) { 8 | if (b % 2 == 1) { 9 | result = (result * a) % n; 10 | --b; 11 | } else { 12 | a = (a * a) % n; 13 | b /= 2; 14 | } 15 | } 16 | return result; 17 | } 18 | 19 | long long discrete_log(long long a, long long b, long long n) { 20 | if ((a % n == 0) != (b % n == 0)) { 21 | return -1; 22 | } 23 | if (a == b) { 24 | return 1; 25 | } 26 | std::map values; 27 | 28 | auto sqrt = static_cast(std::sqrt(n) + 1); 29 | for (long long i = sqrt; i >= 1; --i) { 30 | long long f1 = pow(a, i * sqrt, n); 31 | values[f1] = i; 32 | } 33 | 34 | for (long long i = 0; i < sqrt; ++i) { 35 | long long f2 = (b * pow(a, i, n)) % n; 36 | if (values.count(f2) > 0) { 37 | long long ans = sqrt * values[f2] - i; 38 | if (ans < n) { 39 | return ans; 40 | } 41 | } 42 | } 43 | 44 | return -1ll; 45 | } 46 | 47 | int main() { 48 | long long a, b, n; 49 | std::cin >> a >> b >> n; 50 | auto ans = discrete_log(a, b % n, n); 51 | std::cout << ans; 52 | } -------------------------------------------------------------------------------- /lab16-numbers/src/a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const int MAX_NUMBER = 20000000; 5 | 6 | std::vector get_primes(int n) { 7 | int sqr = 1, odd = 3; 8 | std::vector result(n + 1, true); 9 | result[0] = result[1] = false; 10 | for (int i = 2; sqr <= n; ++i) { 11 | sqr += odd; 12 | odd += 2; 13 | if (result[i]) { 14 | for (int j = sqr; j <= n; j += i) { 15 | result[j] = false; 16 | } 17 | } 18 | } 19 | 20 | return result; 21 | } 22 | 23 | int main() { 24 | std::ios_base::sync_with_stdio(false); 25 | std::cin.tie(nullptr); 26 | 27 | auto primes = get_primes(MAX_NUMBER); 28 | int n, x; 29 | std::cin >> n; 30 | for (int i = 0; i < n; ++i) { 31 | std::cin >> x; 32 | if (primes[x]) { 33 | std::cout << "YES\n"; 34 | } else { 35 | std::cout << "NO\n"; 36 | } 37 | } 38 | return 0; 39 | } -------------------------------------------------------------------------------- /lab16-numbers/src/b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const int MAX_NUMBER = 1000000; 5 | 6 | std::vector get_primes(int n) { 7 | int sqr = 1, odd = 3; 8 | std::vector result(n + 1, true); 9 | result[0] = result[1] = false; 10 | for (int i = 2; sqr <= n; ++i) { 11 | sqr += odd; 12 | odd += 2; 13 | if (result[i]) { 14 | for (int j = sqr; j <= n; j += i) { 15 | result[j] = false; 16 | } 17 | } 18 | } 19 | 20 | return result; 21 | } 22 | 23 | std::vector get_prime_multipliers(int n) { 24 | int sqr = 1, odd = 3; 25 | std::vector result(n + 1, 1); 26 | result[0] = result[1] = 0; 27 | for (int i = 2; sqr <= n; ++i) { 28 | sqr += odd; 29 | odd += 2; 30 | if (result[i] == 1) { 31 | for (int j = sqr; j <= n; j += i) { 32 | if (result[j] == 1) { 33 | result[j] = i; 34 | } 35 | } 36 | } 37 | } 38 | 39 | return result; 40 | } 41 | 42 | int main() { 43 | std::ios_base::sync_with_stdio(false); 44 | std::cin.tie(nullptr); 45 | 46 | auto prime_multipliers = get_prime_multipliers(MAX_NUMBER); 47 | int n, x; 48 | std::cin >> n; 49 | for (int i = 0; i < n; ++i) { 50 | std::cin >> x; 51 | while (prime_multipliers[x] != 1) { 52 | std::cout << prime_multipliers[x] << " "; 53 | x /= prime_multipliers[x]; 54 | } 55 | std::cout << x << "\n"; 56 | } 57 | return 0; 58 | } -------------------------------------------------------------------------------- /lab16-numbers/tasks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cannor147/itmo-algo/96ec8f28c0af1005b9cb2870e4c68d65a7d8a941/lab16-numbers/tasks.pdf --------------------------------------------------------------------------------