├── README.md ├── README_Reduced.md ├── sources ├── .gitignore ├── Matrix_class.cpp ├── bigint.cc ├── cantor_expansion.cpp ├── convex_hull_GrahamsScan.cpp ├── euclidean_algorithm_extend.cpp ├── euclidean_algorithm_extend_Linear_congruence_equation.cpp ├── euclidean_algorithm_extend_chinese_reminder_theory.cpp ├── get_prime_factor.cpp ├── hash_map.cc ├── list.cc ├── maximum_bipartite_matching.cpp ├── minimum_spanning_tree_Kruskal.cpp ├── minimum_spanning_tree_prim_V2.cpp ├── network_flow_maximun_flow_Dinic.cpp ├── point.cc ├── power_modulo.cc ├── segment_tree.cc ├── segment_tree_2.cc ├── strings.cc ├── strings.in ├── struct.cc ├── teamplate.cc └── vector.cc └── theoretical_computer_science_cheat_sheet.pdf /README_Reduced.md: -------------------------------------------------------------------------------- 1 | ACM-ICPC Cheat Sheet 2 | ========================== 3 | 4 | Orange Juice 情報 5 | 6 | ![balloon](https://assets-cdn.github.com/images/icons/emoji/unicode/1f388.png?v5) 7 | ![balloon](https://assets-cdn.github.com/images/icons/emoji/unicode/1f388.png?v5) 8 | ![balloon](https://assets-cdn.github.com/images/icons/emoji/unicode/1f388.png?v5) 9 | ![balloon](https://assets-cdn.github.com/images/icons/emoji/unicode/1f388.png?v5) 10 | ![balloon](https://assets-cdn.github.com/images/icons/emoji/unicode/1f388.png?v5) 11 | ![balloon](https://assets-cdn.github.com/images/icons/emoji/unicode/1f388.png?v5) 12 | ![balloon](https://assets-cdn.github.com/images/icons/emoji/unicode/1f388.png?v5) 13 | ![balloon](https://assets-cdn.github.com/images/icons/emoji/unicode/1f388.png?v5) 14 | ![balloon](https://assets-cdn.github.com/images/icons/emoji/unicode/1f388.png?v5) 15 | ![balloon](https://assets-cdn.github.com/images/icons/emoji/unicode/1f388.png?v5) 16 | 17 | ![fried_shrimp](https://assets-cdn.github.com/images/icons/emoji/unicode/1f364.png?v5) 18 | ![sushi](https://assets-cdn.github.com/images/icons/emoji/unicode/1f363.png?v5) 19 | ![fish_cake](https://assets-cdn.github.com/images/icons/emoji/unicode/1f365.png?v5) 20 | ![rice_ball](https://assets-cdn.github.com/images/icons/emoji/unicode/1f359.png?v5) 21 | ![rice_cracker](https://assets-cdn.github.com/images/icons/emoji/unicode/1f358.png?v5) 22 | ![stew](https://assets-cdn.github.com/images/icons/emoji/unicode/1f372.png?v5) 23 | ![oden](https://assets-cdn.github.com/images/icons/emoji/unicode/1f362.png?v5) 24 | ![hamburger](https://assets-cdn.github.com/images/icons/emoji/unicode/1f354.png?v5) 25 | ![doughnut](https://assets-cdn.github.com/images/icons/emoji/unicode/1f369.png?v5) 26 | ![cookie](https://assets-cdn.github.com/images/icons/emoji/unicode/1f36a.png?v5) 27 | 28 | 29 | 30 | **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* 31 | 32 | - [1. Basic](#1-basic) 33 | - [1.1 C++ Solution Template](#11-c-solution-template) 34 | - [1.2 Strings](#12-strings) 35 | - [1.3 STL Algorithm](#13-stl-algorithm) 36 | - [1.3.1 Permutation](#131-permutation) 37 | - [1.3.2 Binary Search & Lower Bound](#132-binary-search-&-lower-bound) 38 | - [1.3.4 Swap](#134-swap) 39 | - [1.3.5 Heap](#135-heap) 40 | - [1.3.6 Sort](#136-sort) 41 | - [1.3.7 Compare](#137-compare) 42 | - [Using lambda expression](#using-lambda-expression) 43 | - [Compare function](#compare-function) 44 | - [Define operator <()](#define-operator-) 45 | - [Define operator()()](#define-operator) 46 | - [1.4 STL Containers](#14-stl-containers) 47 | - [1.4.1 Map](#141-map) 48 | - [Commonly used method](#commonly-used-method) 49 | - [Hash Map (Unordered Map)](#hash-map-unordered-map) 50 | - [1.4.3 Vector](#143-vector) 51 | - [1.4.5 Queue](#145-queue) 52 | - [1.4.6 Double-ended Queue](#146-double-ended-queue) 53 | - [1.4.7 Stack](#147-stack) 54 | - [1.4.8 Priority Queue](#148-priority-queue) 55 | - [2. Advanced Data Structures](#2-advanced-data-structures) 56 | - [2.2 Tree](#22-tree) 57 | - [2.2.1 Pointer Jumping](#221-pointer-jumping) 58 | - [2.2.2 Heavy-Light Decomposition](#222-heavy-light-decomposition) 59 | - [2.2.3 Lowest Common Ancestor](#223-lowest-common-ancestor) 60 | - [2.2.3.1 Tarjan's Off-line Algorithm](#2231-tarjans-off-line-algorithm) 61 | - [2.2.4 Centroid Decomposition](#224-centroid-decomposition) 62 | - [2.3 Trie / Trie Graph / AC Automaton](#23-trie--trie-graph--ac-automaton) 63 | - [2.4 Suffix Tree](#24-suffix-tree) 64 | - [2.5 Suffix Array](#25-suffix-array) 65 | - [2.5.1 Build Suffix Array](#251-build-suffix-array) 66 | - [2.5.2 Pattern Matching](#252-pattern-matching) 67 | - [2.5.3 Longest Common Prefix](#253-longest-common-prefix) 68 | - [2.5.4 Longest Repeated Substring](#254-longest-repeated-substring) 69 | - [2.5.5 Longest Common Substring](#255-longest-common-substring) 70 | - [2.6 Binary Indexed Tree](#26-binary-indexed-tree) 71 | - [2.7 Segment Tree](#27-segment-tree) 72 | - [2.7.0 Range Update + Range Query](#270-range-update--range-query) 73 | - [2.8 Range Minimum Query RMQ](#28-range-minimum-query-rmq) 74 | - [2.9 Union-find Set](#29-union-find-set) 75 | - [2.10 Bloom Filter (?) (Similar)](#210-bloom-filter--similar) 76 | - [3. Methodology](#3-methodology) 77 | - [3.0 Greedy](#30-greedy) 78 | - [3.1 Recursive](#31-recursive) 79 | - [3.1.1 Hanoi](#311-hanoi) 80 | - [3.2 Dynamic Programming](#32-dynamic-programming) 81 | - [3.2.1 Longest Increasing Subsequence (LIS)](#321-longest-increasing-subsequence-lis) 82 | - [3.3 Divide and Conquer](#33-divide-and-conquer) 83 | - [3.3.1 binary search](#331-binary-search) 84 | - [3.4 Search](#34-search) 85 | - [3.4.2 双向 BFS](#342-%E5%8F%8C%E5%90%91-bfs) 86 | - [3.4.3 从终点开始搜](#343-%E4%BB%8E%E7%BB%88%E7%82%B9%E5%BC%80%E5%A7%8B%E6%90%9C) 87 | - [3.4.4 迭代加深搜索 (binary increase/decrease)](#344-%E8%BF%AD%E4%BB%A3%E5%8A%A0%E6%B7%B1%E6%90%9C%E7%B4%A2-binary-increasedecrease) 88 | - [3.5 Brute Force](#35-brute-force) 89 | - [3.5.1 子集生成](#351-%E5%AD%90%E9%9B%86%E7%94%9F%E6%88%90) 90 | - [4. String](#4-string) 91 | - [4.1 KMP](#41-kmp) 92 | - [4.2 Boyer-Moore](#42-boyer-moore) 93 | - [4.3 Longest palindromic substring (Manacher's algorithm)](#43-longest-palindromic-substring-manachers-algorithm) 94 | - [5. Graph](#5-graph) 95 | - [5.1 Graph Structure](#51-graph-structure) 96 | - [5.2 Minimium Spanning Tree](#52-minimium-spanning-tree) 97 | - [5.2.1 Prim's](#521-prims) 98 | - [5.2.2 Kruskal](#522-kruskal) 99 | - [5.3 Shortest Path](#53-shortest-path) 100 | - [5.3.1 任意两点](#531-%E4%BB%BB%E6%84%8F%E4%B8%A4%E7%82%B9) 101 | - [5.3.2 Bellman–Ford](#532-bellman%E2%80%93ford) 102 | - [5.3.3 SPFA](#533-spfa) 103 | - [5.3.4 Dijkstra](#534-dijkstra) 104 | - [5.4 Maximum Matching](#54-maximum-matching) 105 | - [5.4.1 on Bipartite Graph 二分图](#541-on-bipartite-graph-%E4%BA%8C%E5%88%86%E5%9B%BE) 106 | - [5.4.1.1 Hungarian algorithm 匈牙利算法](#5411-hungarian-algorithm-%E5%8C%88%E7%89%99%E5%88%A9%E7%AE%97%E6%B3%95) 107 | - [5.4.1.2 Hopcroft–Karp Algorithm](#5412-hopcroft%E2%80%93karp-algorithm) 108 | - [5.4.2 on General Graph](#542-on-general-graph) 109 | - [5.4.2.1 Blossom Algorithm](#5421-blossom-algorithm) 110 | - [5.5 Maximum Flow Problem 最大流](#55-maximum-flow-problem-%E6%9C%80%E5%A4%A7%E6%B5%81) 111 | - [5.5.1 Dinic](#551-dinic) 112 | - [5.5.2 Improved SAP + Gap Optimization](#552-improved-sap--gap-optimization) 113 | - [5.5.3 Minimum-Cost Maximum-Flow](#553-minimum-cost-maximum-flow) 114 | - [5.6 强连通分量 图的 割点, 桥, 双连通分支](#56-%E5%BC%BA%E8%BF%9E%E9%80%9A%E5%88%86%E9%87%8F-%E5%9B%BE%E7%9A%84-%E5%89%B2%E7%82%B9-%E6%A1%A5-%E5%8F%8C%E8%BF%9E%E9%80%9A%E5%88%86%E6%94%AF) 115 | - [5.7 Topological Sort / 拓扑排序](#57-topological-sort--%E6%8B%93%E6%89%91%E6%8E%92%E5%BA%8F) 116 | - [5.8 Euler Cycle/Path, Hamilton Cycle/Path](#58-euler-cyclepath-hamilton-cyclepath) 117 | - [5.9 find negative (weight) Cycle on a graph](#59-find-negative-weight-cycle-on-a-graph) 118 | - [6. Number + Mathematics](#6-number--mathematics) 119 | - [6.1 BigInteger + BigDecimal](#61-biginteger--bigdecimal) 120 | - [6.1.1 C++ Big Integer](#611-c-big-integer) 121 | - [6.1.2 The Java Approach](#612-the-java-approach) 122 | - [6.2 Matrix](#62-matrix) 123 | - [6.3 Number Theory](#63-number-theory) 124 | - [6.3.1 欧拉函数 ?](#631-%E6%AC%A7%E6%8B%89%E5%87%BD%E6%95%B0-) 125 | - [6.3.2 欧几里得算法 / gcd](#632-%E6%AC%A7%E5%87%A0%E9%87%8C%E5%BE%97%E7%AE%97%E6%B3%95--gcd) 126 | - [6.3.3 扩展欧几里得算法](#633-%E6%89%A9%E5%B1%95%E6%AC%A7%E5%87%A0%E9%87%8C%E5%BE%97%E7%AE%97%E6%B3%95) 127 | - [6.3.4 求解不定方程](#634-%E6%B1%82%E8%A7%A3%E4%B8%8D%E5%AE%9A%E6%96%B9%E7%A8%8B) 128 | - [6.3.5 求解模线性方程(线性同余方程)](#635-%E6%B1%82%E8%A7%A3%E6%A8%A1%E7%BA%BF%E6%80%A7%E6%96%B9%E7%A8%8B%EF%BC%88%E7%BA%BF%E6%80%A7%E5%90%8C%E4%BD%99%E6%96%B9%E7%A8%8B%EF%BC%89) 129 | - [6.3.6 求解模的逆元](#636-%E6%B1%82%E8%A7%A3%E6%A8%A1%E7%9A%84%E9%80%86%E5%85%83) 130 | - [6.3.7 中国剩余定理](#637-%E4%B8%AD%E5%9B%BD%E5%89%A9%E4%BD%99%E5%AE%9A%E7%90%86) 131 | - [6.3.8 最小公倍数](#638-%E6%9C%80%E5%B0%8F%E5%85%AC%E5%80%8D%E6%95%B0) 132 | - [6.3.9 分解质因数](#639-%E5%88%86%E8%A7%A3%E8%B4%A8%E5%9B%A0%E6%95%B0) 133 | - [6.3.10 因数个数](#6310-%E5%9B%A0%E6%95%B0%E4%B8%AA%E6%95%B0) 134 | - [6.3.11 素数判定](#6311-%E7%B4%A0%E6%95%B0%E5%88%A4%E5%AE%9A) 135 | - [6.3.11.1 Miller Rabin Primality Test](#63111-miller-rabin-primality-test) 136 | - [6.3.12 进制转换](#6312-%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2) 137 | - [6.3.13 A / C](#6313-a--c) 138 | - [6.3.14 质数表](#6314-%E8%B4%A8%E6%95%B0%E8%A1%A8) 139 | - [6.3.15 Fast Exponention](#6315-fast-exponention) 140 | - [6.3.16 Fast Fourier Transform FFT](#6316-fast-fourier-transform-fft) 141 | - [6.4 Game Theory 博弈论](#64-game-theory-%E5%8D%9A%E5%BC%88%E8%AE%BA) 142 | - [6.4.1 Impartial Combinatorial Game](#641-impartial-combinatorial-game) 143 | - [6.4.1.1 Nim Game](#6411-nim-game) 144 | - [6.4.1.1 Composite Games – Sprague-Grundy Theorem and Nim Value](#6411-composite-games-%E2%80%93-sprague-grundy-theorem-and-nim-value) 145 | - [7. Geometry](#7-geometry) 146 | - [7.1 2-Dimension Space](#71-2-dimension-space) 147 | - [7.1.1 Template of Point](#711-template-of-point) 148 | - [7.1.2 向量点乘 叉乘](#712-%E5%90%91%E9%87%8F%E7%82%B9%E4%B9%98-%E5%8F%89%E4%B9%98) 149 | - [7.1.3 dot product](#713-dot-product) 150 | - [7.1.4 cross product](#714-cross-product) 151 | - [7.1.5 直线公式](#715-%E7%9B%B4%E7%BA%BF%E5%85%AC%E5%BC%8F) 152 | - [7.1.6 Convex Hull](#716-convex-hull) 153 | - [Graham scan](#graham-scan) 154 | - [8. Tricks + Miscellaneous](#8-tricks--miscellaneous) 155 | - [8.1 Bit Manipulation](#81-bit-manipulation) 156 | - [8.1 Cantor Expansion / Reverse Cantor Expansion](#81-cantor-expansion--reverse-cantor-expansion) 157 | - [8.2 pass 2-D array](#82-pass-2-d-array) 158 | - [8.3 Binary Display](#83-binary-display) 159 | - [8.4 Fast Log](#84-fast-log) 160 | - [8.5 Squre Root](#85-squre-root) 161 | 162 | 163 | 164 | ## 1. Basic 165 | 166 | ### 1.1 C++ Solution Template 167 | 168 | ```c++ 169 | #include 170 | #include 171 | #include 172 | #include 173 | #include 174 | #include 175 | #include 176 | #include 177 | #include 178 | #include 179 | #include 180 | #include 181 | #include 182 | #include 183 | #include 184 | #include 185 | #include 186 | 187 | #ifdef DEBUG 188 | #define SHOW(x) {cout << __LINE__ << ":\t"; {x} cout << endl;} 189 | #define $(x) {cout << #x << " = " << x << ", ";} 190 | #define REACH_HERE { printf("%d:\tREACH_HERE\n", __LINE__); } 191 | #define PRINT(s, ...) { printf("%d:\t", __LINE__); printf(s, ##__VA_ARGS__); } 192 | #define PRINTLN(s, ...) { printf("%d:\t", __LINE__); printf(s, ##__VA_ARGS__); printf("\n"); } 193 | #else 194 | #define SHOW(x) {} 195 | #define $(x) {} 196 | #define REACH_HERE {} 197 | #define PRINT(s, ...) {} 198 | #define PRINTLN(s, ...) {} 199 | #endif 200 | 201 | const double E = 1e-8; 202 | const double PI = acos(-1); 203 | 204 | using namespace std; 205 | 206 | int main() { 207 | ios::sync_with_stdio(false); 208 | 209 | int a = 10, b = 10; 210 | SHOW( $(a) $(b) ) 211 | 212 | PRINTLN("Hello %d", a) 213 | 214 | } 215 | ``` 216 | 217 | ``` 218 | rm main.out 219 | g++ -O2 -std=c++11 main.cpp -DDEBUG -o main.out 220 | ./main.out < input.txt 221 | ``` 222 | 223 | ``` 224 | export PATH=$PATH:~/path_to_judge 225 | ``` 226 | 227 | ### 1.2 Strings 228 | 229 | ```C++ 230 | string a; 231 | getline(cin, a); 232 | cout << a << endl; 233 | char target[1024]; 234 | strcpy(target, cppstr.c_str()); 235 | char s[12]; 236 | gets(s); // till new line or EOF. 237 | string target = string(arr); 238 | ``` 239 | 240 | ### 1.3 STL Algorithm 241 | 242 | #### 1.3.1 Permutation 243 | 244 | ```c++ 245 | bool next_permutation (BidirectionalIterator first, BidirectionalIterator last); 246 | bool next_permutation (BidirectionalIterator first, BidirectionalIterator last, Compare comp); 247 | do { 248 | std::cout << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n'; 249 | } while ( std::next_permutation(myints,myints+3) ); 250 | ``` 251 | 252 | #### 1.3.2 Binary Search & Lower Bound 253 | 254 | ```C++ 255 | bool binary_search (ForwardIterator first, ForwardIterator last, const T& val, Compare comp); 256 | // return true if found, false if not 257 | ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last, const T& val, Compare comp); 258 | ``` 259 | 260 | #### 1.3.4 Swap 261 | 262 | ```c++ 263 | void swap (T& a, T& b); 264 | void iter_swap (ForwardIterator1 a, ForwardIterator2 b); 265 | ``` 266 | 267 | #### 1.3.5 Heap 268 | 269 | * make_heap: Rearranges the elements in the range [first,last) in such a way that they form a heap. The element with the highest value is always pointed by first. 270 | * pop_heap: Rearranges the elements in the heap range [first,last) in such a way that the part considered a heap is shortened by one: The element with the highest value is moved to (last-1). 271 | * push_heap: Given a heap in the range [first,last-1), this function extends the range considered a heap to [first,last) by placing the value in (last-1) into its corresponding location within it. 272 | * sort_heap: Sorts the elements in the heap range [first,last) into ascending order. 273 | 274 | ```c++ 275 | void make_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp); 276 | void pop_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp); 277 | void push_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp); 278 | void sort_heap (RandomAccessIterator first, RandomAccessIterator last); Compare comp); 279 | ``` 280 | 281 | 282 | #### 1.3.6 Sort 283 | 284 | 285 | ```c++ 286 | void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp); 287 | void stable_sort ( RandomAccessIterator first, RandomAccessIterator last, Compare comp ); 288 | ``` 289 | 290 | #### 1.3.7 Compare 291 | 292 | ##### Using lambda expression 293 | 294 | ``` c++ 295 | auto cmp = [](const T& a, const T& b) { return true; }; 296 | set a_set_with_customized_comparator(cmp); 297 | ``` 298 | 299 | ##### Compare function 300 | 301 | > Using by `sort`, `make_heap` and etc. 302 | 303 | ```c++ 304 | bool cmp (int i,int j) { return (i s(cmp); 306 | 307 | ``` 308 | 309 | ##### Define operator <() 310 | 311 | Member function, recommended // can use for priority_queue, sort, 312 | 313 | ```c++ 314 | struct Edge { 315 | int from, to, weight; 316 | bool operator<(Edge that) const { // or (const Edge& that) 317 | return weight > that.weight; 318 | } 319 | }; 320 | ``` 321 | 322 | ##### Define operator()() 323 | 324 | 325 | 326 | ```c++ 327 | vector occurrences; 328 | struct cmp { 329 | bool operator()(int a, int b) { 330 | return occurrences[a] < occurrences[b]; 331 | } 332 | }; 333 | set s; 334 | priority_queue, cmp> pq; 335 | ``` 336 | 337 | Used by `priority_queue `. 338 | 339 | ### 1.4 STL Containers 340 | 341 | #### 1.4.1 Map 342 | 343 | ```c++ 344 | template < class Key, // map::key_type 345 | class T, // map::mapped_type 346 | class Compare = less, // map::key_compare 347 | class Alloc = allocator > // map::allocator_type 348 | > class map; 349 | ``` 350 | 351 | ##### Commonly used method 352 | 353 | ``` 354 | begin() 355 | end() 356 | 357 | empty() 358 | size() 359 | 360 | operator[] // if not found, insert one 361 | 362 | insert(pair, // unordered_map::hasher 376 | class Pred = equal_to, // unordered_map::key_equal 377 | class Alloc = allocator< pair > // unordered_map::allocator_type 378 | > class unordered_map; 379 | 380 | ``` 381 | 382 | #### 1.4.3 Vector 383 | 384 | ```c++ 385 | std::vector second (4,100); // four ints with value 100 386 | * begin(), end() 387 | * front(), back() 388 | * clear() 389 | * size() 390 | * push_back(const value_type& val) 391 | * pop_back() 392 | ``` 393 | 394 | #### 1.4.5 Queue 395 | 396 | ```C++ 397 | queue my_queue; 398 | queue > my_queue (my_list); 399 | // use list as container, copy my_list into my_queue 400 | ``` 401 | 402 | ```C++ 403 | void queue::push(const value_type& val); 404 | void queue::pop(); 405 | bool queue::empty() const; 406 | size_type queue::size() const; 407 | const_reference& queue::front() const; 408 | ``` 409 | 410 | #### 1.4.6 Double-ended Queue 411 | 412 | ```C++ 413 | #include 414 | ``` 415 | 416 | 417 | #### 1.4.7 Stack 418 | 419 | ```C++ 420 | stack > my_stack (my_data); 421 | // use vector as container, copy my_data into my_stack 422 | 423 | bool stack::empty() const; 424 | size_type stack::size() const; 425 | const_reference& stack::top() const; 426 | void stack::push (const value_type& val); 427 | void stack::pop(); 428 | ``` 429 | 430 | #### 1.4.8 Priority Queue 431 | 432 | ```C++ 433 | #include 434 | // constructor 435 | priority_queue my_priority_queue; 436 | priority_queue, greater > two_priority_queue; // if use greater, must have vector 437 | priority_queue, Comparator_class> my_priority_queue (my_data.begin(), my_data.end()); // use Comparator_class as comparator, use vector as container, copy my_data into my_priority_queue 438 | 439 | bool priority_queue::empty() const; // return true if empty, false if not 440 | size_type priority_queue::size() const; // return size of queue 441 | const_reference priority_queue::top() const; // returns a constant reference to the top element 442 | void priority_queue::push(const value_type& val); // inserts a new element, initialize to val 443 | void priority_queue::pop(); // removes the element on top 444 | ``` 445 | 446 | Min-Max Heap 447 | ```c++ 448 | struct HEAP { 449 | int arr[127]; 450 | int size; 451 | }; 452 | void insert(HEAP *h,int n){ 453 | int sz = h->size++; 454 | while(sz>0){ 455 | if(n < h->arr[(sz-1)/2]){//若改成 > 则为大根堆 456 | h->arr[sz] = h->arr[(sz-1)/2]; 457 | sz = (sz-1)/2; 458 | }else{ 459 | h->arr[sz] = n; 460 | return; 461 | } 462 | } 463 | h->arr[0] = n; 464 | } 465 | void delete(HEAP *h){ 466 | h->size--; 467 | h->arr[0] = h->arr[h->size]; 468 | h->arr[h->size] = 0; 469 | int i = 1,cv = h->arr[0],tmp; 470 | while(i < h->size){ 471 | if(i < h->size-1 && h->arr[i] > h->arr[i+1]) 472 | i++; 473 | if(h->arr[i] < cv){ 474 | h->arr[(i-1)/2] = h->arr[i]; 475 | h->arr[i] = cv; 476 | i = i*2 + 1; 477 | }else{ 478 | return; 479 | } 480 | } 481 | } 482 | ``` 483 | 484 | ## 2. Advanced Data Structures 485 | 486 | ### 2.2 Tree 487 | 488 | #### 2.2.1 Pointer Jumping 489 | 490 | > Initialize: O(Nlog(N)) 491 | > 492 | > Query: O(Nlog(N)) 493 | 494 | ```c++ 495 | #define MAX_NODE 100030 496 | #define MAX_NODE_LOG 20 497 | 498 | #define TREE_ROOT 0 499 | vector g[MAX_NODE]; 500 | vector parent_jump[MAX_NODE]; 501 | vector path; 502 | 503 | void init_jump(int cur = TREE_ROOT) { 504 | int d = 1; 505 | while (true) { 506 | int index = path.size() - d; 507 | if (index < 0) 508 | break; 509 | parent_jump[cur].push_back(path[index]); 510 | d <<= 1; 511 | } 512 | path.push_back(cur); 513 | 514 | for (int i = 0; i < g[cur].size(); i++) { 515 | int nx = g[cur][i]; 516 | if (cur == TREE_ROOT || nx != parent_jump[cur][0]) { 517 | init_jump(nx); 518 | } 519 | } 520 | path.pop_back(); 521 | } 522 | 523 | int go_up(int cur, int dis) { 524 | int mask = 1; 525 | int index = 0; 526 | while (mask <= dis) { 527 | if (dis & mask) 528 | cur = parent_jump[cur][index]; 529 | mask <<= 1; 530 | index++; 531 | } 532 | return cur; 533 | } 534 | ``` 535 | 536 | #### 2.2.2 Heavy-Light Decomposition 537 | 538 | > Build: O(N) 539 | > 540 | > Overhead: O(log(N)) 541 | 542 | ```c++ 543 | struct Graph { 544 | map, int> node_edge; 545 | 546 | struct Edge { 547 | int from; 548 | int to; 549 | unsigned long long y; 550 | }; 551 | 552 | const static int MAXNODE = 200005; 553 | vector g[MAXNODE]; 554 | vector edge; 555 | int n; 556 | void init(int nn) { 557 | n = nn; 558 | for (int i = 0; i <= n; i++) 559 | g[i].clear(); 560 | edge.clear(); 561 | } 562 | 563 | void add_e(int x, int y, unsigned long long val_y) { 564 | Edge e1 = {x, y, val_y}; 565 | g[x].push_back(edge.size()); 566 | node_edge[make_pair(x, y)] = edge.size(); 567 | edge.push_back(e1); 568 | 569 | Edge e2 = {y, x, val_y}; 570 | g[y].push_back(edge.size()); 571 | node_edge[make_pair(y, x)] = edge.size(); 572 | edge.push_back(e2); 573 | 574 | // LOGLN("add edge %d - %d = %llu", x, y, val_y); 575 | } 576 | 577 | int parent[MAXNODE]; 578 | int size[MAXNODE]; 579 | int size_parent(int cur) { 580 | int& s = size[cur] = 1; 581 | for (int i = 0; i < g[cur].size(); i++) { 582 | int ie = g[cur][i]; 583 | const Edge& e = edge[ie]; 584 | int nx = e.to; 585 | if (nx != parent[cur]) { 586 | parent[nx] = cur; 587 | s += size_parent(nx); 588 | } 589 | } 590 | return s; 591 | } 592 | void show_size_parent() { 593 | for (int i = 0; i <= n; i++) 594 | printf("node %d: size %d, parent %d\n", i, size[i], parent[i]); 595 | } 596 | 597 | struct Chain { 598 | int head; 599 | int head_depth; 600 | int len; 601 | }; 602 | vector chain; 603 | int chain_total; 604 | int chain_no[MAXNODE]; // chain_no[node] == chain_index 605 | int chain_pos[MAXNODE]; // chain_pos[node] == x'th node in the chain // 0 based 606 | void hld(int cur, int depth) { 607 | if (chain_total == chain.size()) { 608 | Chain c = {cur, depth, 0}; 609 | chain.push_back(c); 610 | } 611 | 612 | chain_no[cur] = chain_total; 613 | chain_pos[cur] = chain[chain_total].len; 614 | chain[chain_total].len++; // 0 based, add later 615 | 616 | if (depth != 0 && g[cur].size() - 1 == 0) 617 | return ; 618 | 619 | int heavy = edge[g[cur][0]].to; 620 | for (int i = 0; i < g[cur].size(); i++) { 621 | int ie = g[cur][i]; 622 | const Edge& e = edge[ie]; 623 | int nx = e.to; 624 | if (heavy == parent[cur] || (nx != parent[cur] && size[nx] > size[heavy])) 625 | heavy = nx; 626 | } 627 | 628 | hld(heavy, depth + 1); 629 | for (int i = 0; i < g[cur].size(); i++) { 630 | int ie = g[cur][i]; 631 | const Edge& e = edge[ie]; 632 | int nx = e.to; 633 | if (nx != parent[cur] && nx != heavy) { 634 | chain_total++; 635 | hld(nx, depth + 1); 636 | } 637 | } 638 | } 639 | 640 | void heavy_light_decomposition() { 641 | int root = 1; 642 | parent[root] = -1; 643 | assert(n == size_parent(root)); 644 | 645 | chain_total = 0; 646 | chain.clear(); 647 | 648 | hld(root, 0); 649 | chain_total++; 650 | } 651 | void show_hld() { 652 | printf("chain_total = %d\n", chain_total); 653 | for (int i = 0; i <= chain_total; i++) 654 | printf("chain %d: len %d, head %d, head depth %d\n", i, chain[i].len, chain[i].head, chain[i].head_depth); 655 | for (int i = 0; i <= n; i++) 656 | printf("node %d: chain %d, pos %d\n", i, chain_no[i], chain_pos[i]); 657 | } 658 | 659 | vector st; 660 | void init_sol() { 661 | st.resize(chain_total); 662 | for (int i = 0; i < st.size(); i++) 663 | st[i].init(chain[i].len - 2); 664 | 665 | for (int i = 0; i < edge.size(); i += 2) { 666 | const Edge& e = edge[i]; 667 | int cn1 = chain_no[e.from]; 668 | int cn2 = chain_no[e.to]; 669 | 670 | if (cn1 == cn2) { 671 | int cp1 = chain_pos[e.from]; 672 | int cp2 = chain_pos[e.to]; 673 | if (cp1 > cp2) 674 | swap(cp1, cp2); 675 | st[cn1].update(cp1, cp2 - 1, e.y); 676 | } 677 | } 678 | 679 | // for (int i = 0; i < chain_total; i++) 680 | // st[i].show(); 681 | } 682 | }; 683 | 684 | int n; 685 | int m; 686 | Graph g; 687 | 688 | int main() { 689 | scanf("%d %d", &n, &m); 690 | g.init(n); 691 | for (int i = 1; i < n; i++) { 692 | int x, y; 693 | unsigned long long val_y; 694 | scanf("%d %d %llu", &x, &y, &val_y); 695 | g.add_e(x, y, val_y); 696 | } 697 | 698 | g.heavy_light_decomposition(); 699 | // g.show_hld(); 700 | g.init_sol(); 701 | } 702 | ``` 703 | 704 | #### 2.2.3 Lowest Common Ancestor 705 | 706 | ```c++ 707 | struct Graph { 708 | struct Edge { 709 | int to; 710 | int len; 711 | }; 712 | 713 | const static int MAXNODE = 1 * 1e5 + 2; 714 | 715 | vector g[MAXNODE]; 716 | vector edge; 717 | int n; 718 | 719 | int root = 0; 720 | 721 | void init(int nn, int m=0) { 722 | n = nn; 723 | for (int i = 0; i <= n; i++) 724 | g[i].clear(); 725 | edge.clear(); 726 | m *= 2; 727 | edge.reserve(m); // may speedup // add_e too slow 728 | } 729 | 730 | void add_e(int x, int y, int len) { 731 | g[x].push_back(edge.size()); 732 | edge.push_back((Edge){y, len}); 733 | 734 | g[y].push_back(edge.size()); 735 | edge.push_back((Edge){x, len}); 736 | } 737 | 738 | void show() { 739 | for (int i = 0; i <= n; i++) { 740 | printf("%d:", i); 741 | for (int ie : g[i]) 742 | printf(" %d", edge[ie].to); 743 | printf("\n"); 744 | } 745 | printf("\n"); 746 | } 747 | 748 | // 749 | // --- start of LCA --- 750 | // 751 | vector dis_to_root; 752 | vector first_visit_time; // max possible number of visits to all nodes == 2 * number of nodes - 1 753 | vector visit; 754 | int visit_counter; 755 | vector> rmq; 756 | 757 | int range_minimum_query(int l, int r) { // query [l, r] 758 | if (l > r) 759 | swap(l, r); 760 | 761 | int interval_len = r - l; // (r - l + 1) - 1 762 | 763 | int first_half = 1; 764 | while ((1 << first_half) <= interval_len) 765 | first_half++; 766 | first_half--; 767 | 768 | int second_half = r - (1 << first_half) + 1; 769 | if (first_visit_time[rmq[l][first_half]] < first_visit_time[rmq[second_half][first_half]]) 770 | return rmq[l][first_half]; 771 | return rmq[second_half][first_half]; 772 | } 773 | 774 | int get_lca(int x, int y) { 775 | return range_minimum_query(first_visit_time[x], first_visit_time[y]); 776 | } 777 | 778 | int dist(int x, int y) { 779 | int lca = get_lca(x, y); 780 | return dis_to_root[x] + dis_to_root[y] - 2 * dis_to_root[lca]; 781 | } 782 | 783 | void euler_tour(int cur) { 784 | visit[++visit_counter] = cur; // v_t[node] = time // needed in case don't have two child 785 | if (first_visit_time[cur] == 0) // if first time 786 | first_visit_time[cur] = visit_counter; // record time f_v_t[node] = time 787 | for (int ie : g[cur]) { 788 | const Edge& e = edge[ie]; 789 | int nx = e.to; 790 | int len = e.len; 791 | if (first_visit_time[nx] == 0) { 792 | dis_to_root[nx] = dis_to_root[cur] + len; 793 | euler_tour(nx); 794 | visit[++visit_counter] = cur; // every two child_visit_time have one parent_visit_time inserted between 795 | } 796 | } 797 | } 798 | 799 | void build_lca() { // O(Nlog(N)) 800 | int one_n = n + 1; 801 | int two_n = 2 * one_n; 802 | vector(one_n, 0).swap(dis_to_root); 803 | vector(one_n, 0).swap(first_visit_time); 804 | vector(two_n, 0).swap(visit); 805 | 806 | int LOG_MAXLENGTH = log2(two_n) + 2; 807 | vector>(two_n, vector(LOG_MAXLENGTH)).swap(rmq); 808 | 809 | visit_counter = 0; 810 | euler_tour(root); 811 | 812 | for (int i = 0; i < visit_counter; i++) 813 | rmq[i][0] = visit[i]; 814 | 815 | for (int j = 1; j < LOG_MAXLENGTH; j++) 816 | for (int i = 0; i < visit_counter; i++) { 817 | if (i + (1 << j) > visit_counter) 818 | break; 819 | rmq[i][j] = rmq[i][j - 1]; 820 | if (first_visit_time[rmq[i][j - 1]] > first_visit_time[rmq[i + (1 << (j - 1))][j - 1]]) 821 | rmq[i][j] = rmq[i + (1 << (j - 1))][j-1]; 822 | } 823 | } 824 | // 825 | // --- end of LCA --- 826 | // 827 | }; 828 | ``` 829 | 830 | ##### 2.2.3.1 Tarjan's Off-line Algorithm 831 | 832 | > let n = number of ndoes of the tree, m = number of query 833 | > 834 | > O(n + m) 835 | 836 | ``` 837 | function TarjanOLCA(u) 838 | MakeSet(u); 839 | u.ancestor := u; 840 | for each v in u.children do 841 | TarjanOLCA(v); 842 | Union(u,v); 843 | Find(u).ancestor := u; 844 | u.colour := black; 845 | for each v such that {u,v} in P do 846 | if v.colour == black 847 | print "Tarjan's Lowest Common Ancestor of " + u + 848 | " and " + v + " is " + Find(v).ancestor + "."; 849 | ``` 850 | 851 | > TODO refactor add comments 852 | 853 | ```c++ 854 | // 855 | // 1471. Tree 856 | // http://acm.timus.ru/problem.aspx?space=1&num=1471 857 | // Time limit: 2.0 second 858 | // Memory limit: 64 MB 859 | // 860 | // A weighted tree is given. You must find the distance between two given nodes. 861 | // 862 | // Input 863 | // The first line contains the number of nodes of the tree n (1 ≤ n ≤ 50000). 864 | // The nodes are numbered from 0 to n – 1. 865 | // Each of the next n – 1 lines contains three integers u, v, w, 866 | // which correspond to an edge with weight w (0 ≤ w ≤ 1000) connecting nodes u and v. 867 | // The next line contains the number of queries m (1 ≤ m ≤ 75000). 868 | // In each of the next m lines there are two integers. 869 | // 870 | // Output 871 | // For each range_minimum_query, output the distance between the nodes with the given numbers. 872 | // 873 | // Sample 874 | // 875 | // input 876 | // 3 877 | // 1 0 1 878 | // 2 0 1 879 | // 3 880 | // 0 1 881 | // 0 2 882 | // 1 2 883 | // 884 | // output 885 | // 1 886 | // 1 887 | // 2 888 | 889 | #include 890 | #include 891 | #include 892 | 893 | using namespace std; 894 | 895 | #define MAXHHH 50003 896 | #define MAXJJJ 75005 897 | 898 | struct Node { 899 | vector next; // edge list 900 | vector dist; // edge length 901 | vector query; // that node of a query 902 | vector lca; // lca of this and that node 903 | vector q_i; // index of query in offline query array 904 | }; 905 | 906 | Node g[MAXHHH]; 907 | int n, m; 908 | 909 | int father[MAXHHH]; 910 | int find(int x) { // find-union set 911 | if (father[x] == x) 912 | return x; 913 | return father[x] = find(father[x]); 914 | } 915 | void mergeFirstInToSecond(int x, int y) { // find-union set 916 | father[find(x)] = find(y); 917 | } 918 | 919 | pair q[MAXJJJ]; // query: node a, b 920 | pair q_ans[MAXJJJ]; // record answer's location, first = node index, second = answer index 921 | int came[MAXHHH]; 922 | void tarjan_lca_dfs(int cur) { 923 | // process cur node and all its sub-tree 924 | // process all query related to this node and nodes in sub-tree 925 | came[cur] = 1; 926 | for (unsigned int i = 0; i < g[cur].next.size(); i++) { 927 | int next = g[cur].next[i]; 928 | if (came[next] == 1) // don't go back, it is dfs 929 | continue; 930 | 931 | tarjan_lca_dfs(next); // process sub-tree 932 | mergeFirstInToSecond(cur, next); // order matters 933 | } 934 | 935 | for (unsigned int i = 0; i < g[cur].query.size(); i++) { 936 | int that = g[cur].query[i]; 937 | if (came[that] == 0) 938 | continue; 939 | 940 | // lca must be father[that] because this comes from father[that] 941 | // and father[that] haven't merge with father[father[that]] 942 | g[cur].lca[i] = find(that); 943 | q_ans[g[cur].q_i[i]] = make_pair(cur, i); // record position for later usage 944 | } 945 | } 946 | 947 | int root_dis[MAXHHH]; 948 | void dfs(int cur) { 949 | for (unsigned int i = 0; i < g[cur].next.size(); i++) { 950 | int next = g[cur].next[i]; 951 | if (root_dis[next] != -1) 952 | continue; 953 | 954 | root_dis[next] = g[cur].dist[i] + root_dis[cur]; 955 | dfs(next); 956 | } 957 | } 958 | 959 | int main(int argc, char const *argv[]) { 960 | cin >> n; 961 | for (int i = 1; i < n; i++) { 962 | int a, b, c; 963 | cin >> a >> b >> c; 964 | g[a].next.push_back(b); 965 | g[a].dist.push_back(c); 966 | g[b].next.push_back(a); 967 | g[b].dist.push_back(c); 968 | father[i] = i; 969 | } 970 | cin >> m; 971 | for (int i = 0; i < m; i++) { // offline 972 | cin >> q[i].first >> q[i].second; 973 | g[q[i].first].query.push_back(q[i].second); 974 | g[q[i].first].lca.push_back(-1); 975 | g[q[i].first].q_i.push_back(i); 976 | g[q[i].second].query.push_back(q[i].first); 977 | g[q[i].second].lca.push_back(-1); 978 | g[q[i].second].q_i.push_back(i); 979 | q_ans[i] = make_pair(-1, -1); 980 | } 981 | 982 | memset(root_dis, -1, sizeof(root_dis)); root_dis[0] = 0; 983 | dfs(0); 984 | tarjan_lca_dfs(0); 985 | 986 | for (int i = 0; i < m; i++) { 987 | int lca = g[q_ans[i].first].lca[q_ans[i].second]; 988 | int ans = root_dis[q[i].first] + root_dis[q[i].second] - 2 * root_dis[lca]; 989 | cout << ans << endl; 990 | } 991 | } 992 | ``` 993 | 994 | #### 2.2.4 Centroid Decomposition 995 | 996 | > build O(Nlog(N)) 997 | > 998 | > query O(log(N)) 999 | 1000 | ```c++ 1001 | struct Graph { 1002 | struct Edge { 1003 | int to; 1004 | }; 1005 | 1006 | const static int MAXNODE = 1 * 1e5 + 2; 1007 | 1008 | vector g[MAXNODE]; 1009 | vector edge; 1010 | int n; 1011 | 1012 | int root = 1; 1013 | 1014 | void init(int nn, int m=0) { 1015 | n = nn; 1016 | for (int i = 0; i <= n; i++) 1017 | g[i].clear(); 1018 | edge.clear(); 1019 | m *= 2; 1020 | edge.reserve(m); // may speedup // add_e too slow 1021 | } 1022 | 1023 | void add_e(int x, int y) { 1024 | g[x].push_back(edge.size()); 1025 | edge.push_back((Edge){y}); 1026 | 1027 | g[y].push_back(edge.size()); 1028 | edge.push_back((Edge){x}); 1029 | } 1030 | 1031 | void show() { 1032 | for (int i = 0; i <= n; i++) { 1033 | printf("%d:", i); 1034 | for (int ie : g[i]) 1035 | printf(" %d", edge[ie].to); 1036 | printf("\n"); 1037 | } 1038 | printf("\n"); 1039 | } 1040 | 1041 | // 1042 | // --- start of centroid decomposition --- 1043 | // 1044 | vector centroid; // index of upper level centroid node 1045 | 1046 | vector subtree_size; 1047 | vector parent; 1048 | 1049 | vector deleted; 1050 | int compute_subtree(int cur) { 1051 | int& size = subtree_size[cur]; 1052 | for (int ie : g[cur]) { 1053 | const Edge& e = edge[ie]; 1054 | int nx = e.to; 1055 | if (parent[nx] == -1) { 1056 | parent[nx] = cur; 1057 | size += compute_subtree(nx); 1058 | } 1059 | } 1060 | return size; 1061 | } 1062 | 1063 | void centroid_decomposite(int cur, int from, int tree_size) { // O(Nlog(N)) 1064 | int half_size = tree_size / 2; 1065 | 1066 | while (subtree_size[cur] <= half_size) // go up until centroid is in subtree 1067 | cur = parent[cur]; 1068 | 1069 | while (1) { 1070 | int candidate = cur; 1071 | for (int ie : g[cur]) { // go down if centroid is in subtree 1072 | const Edge& e = edge[ie]; 1073 | int nx = e.to; 1074 | if (!deleted[nx] && nx != parent[cur]) { 1075 | if (subtree_size[nx] > half_size) { 1076 | SHOW(cur, nx, subtree_size[nx], candidate) 1077 | candidate = nx; 1078 | } 1079 | } 1080 | } 1081 | if (candidate == cur) 1082 | break; 1083 | cur = candidate; 1084 | } 1085 | 1086 | deleted[cur] = true; 1087 | centroid[cur] = from; 1088 | 1089 | int temp = parent[cur]; 1090 | int cur_size = subtree_size[cur]; 1091 | while (!deleted[temp] && temp != parent[temp]) { // update all the subtree_size of parent 1092 | subtree_size[temp] -= cur_size; 1093 | temp = parent[temp]; 1094 | } 1095 | 1096 | for (int ie : g[cur]) { // decomposite parent and children 1097 | const Edge& e = edge[ie]; 1098 | int nx = e.to; 1099 | if (!deleted[nx]) { 1100 | int nx_tree_size; // size of next level centroid tree 1101 | if (nx == parent[cur]) 1102 | nx_tree_size = tree_size - cur_size; 1103 | else 1104 | nx_tree_size = subtree_size[nx]; 1105 | 1106 | if (nx_tree_size == 1) 1107 | centroid[nx] = cur; // don't need to go into it 1108 | else 1109 | centroid_decomposite(nx, cur, nx_tree_size); 1110 | } 1111 | } 1112 | } 1113 | 1114 | void centroid_decomposite() { 1115 | vector(n + 1, -1).swap(centroid); 1116 | vector(n + 1, 1).swap(subtree_size); // initialized each to be 1 (itself) 1117 | vector(n + 1, -1).swap(parent); 1118 | vector(n + 1, false).swap(deleted); 1119 | 1120 | parent[root] = root; 1121 | compute_subtree(root); 1122 | 1123 | centroid_decomposite(root, -1, n); 1124 | } 1125 | // 1126 | // --- end of centroid decomposition --- 1127 | // 1128 | }; 1129 | ``` 1130 | 1131 | Key functions 1132 | 1133 | ```C++ 1134 | int dfs_size(int cur, int from) { 1135 | int total = 1; 1136 | for (int child : tree[cur].children) { 1137 | if (child == from) continue; 1138 | total += dfs_size(child, cur); 1139 | } 1140 | tree[cur].size = total; 1141 | return total; 1142 | } 1143 | 1144 | void find_centroid(int cur, int from) { 1145 | #ifdef DEBUG 1146 | cout << "find centroid for " << cur << " from " << from << endl; 1147 | #endif 1148 | // SHOW(cur) 1149 | // finish condition 1150 | if (tree[cur].size == 1) { 1151 | tree[cur].c_parent = from; 1152 | } 1153 | // check if current node is centroid. 1154 | int max_child_size = 0, max_child; 1155 | for (int child : tree[cur].children) { 1156 | // if (child == from) continue; 1157 | if (tree[child].c_parent != -1) continue; 1158 | if (tree[child].size > max_child_size) { 1159 | max_child_size = tree[child].size; 1160 | max_child = child; 1161 | } 1162 | } 1163 | if (max_child_size > tree[cur].size / 2) { 1164 | // move root 1165 | tree[max_child].size = tree[cur].size; 1166 | tree[cur].size -= max_child_size; 1167 | find_centroid(max_child, from); 1168 | } else { 1169 | // cur is centroid 1170 | tree[cur].c_parent = from; 1171 | if (from == 0) ctree_root = cur; 1172 | for (int child : tree[cur].children) { 1173 | // if (child == from) continue; 1174 | if (tree[child].c_parent != -1) continue; 1175 | find_centroid(child, cur); 1176 | } 1177 | } 1178 | } 1179 | 1180 | void color(int cur) { 1181 | int parent = cur; 1182 | while (parent) { 1183 | tree[parent].closest = min(tree[parent].closest, distance(cur, parent)); 1184 | parent = tree[parent].c_parent; 1185 | } 1186 | } 1187 | 1188 | int query(int cur) { 1189 | int ans = MAX_N; 1190 | int parent = cur; 1191 | while (parent) { 1192 | ans = min(ans, tree[parent].closest + distance(cur, parent)); 1193 | parent = tree[parent].c_parent; 1194 | } 1195 | return ans; 1196 | } 1197 | ``` 1198 | 1199 | ### 2.3 Trie / Trie Graph / AC Automaton 1200 | 1201 | > O(NL+M) - NL: total len of words in dict, M: len of article 1202 | 1203 | ```c++ 1204 | // 1205 | // input: n, q, string x n, string x q 1206 | // output: for each query, print number of string whose prefix is the query 1207 | // 1208 | // Sample Input 1209 | // 5 1210 | // babaab 1211 | // babbbaaaa 1212 | // abba 1213 | // aaaaabaa 1214 | // babaababb 1215 | // 5 1216 | // babb 1217 | // baabaaa 1218 | // bab 1219 | // bb 1220 | // bbabbaab 1221 | // Sample Output 1222 | // 1 1223 | // 0 1224 | // 3 1225 | // 0 1226 | // 0 1227 | // 1228 | // 1229 | // 1230 | // check if any word in dict appear in article 1231 | // 1232 | // Sample Input 1233 | // 6 1234 | // aaabc 1235 | // aaac 1236 | // abcc 1237 | // ac 1238 | // bcd 1239 | // cd 1240 | // aaaaaaaaaaabaaadaaac 1241 | // 1242 | // Sample Output 1243 | // YES 1244 | // 1245 | 1246 | using namespace std; 1247 | 1248 | #define HHH 1000002 1249 | struct TrieNode 1250 | { 1251 | char val; // 'a' ~ 'z' 1252 | bool ended; // is a word ended here 1253 | int count; // number of word ended here 1254 | int childCount; // number of word contianing this prefix 1255 | 1256 | int next[26]; // index of child node, 'a' ~ 'z' 1257 | 1258 | int prev; // parent node // for trie-graph 1259 | bool suffixEnded;// suffix node is an end // for trie-graph 1260 | int suffix[26]; // suffix node // for trie-graph 1261 | 1262 | TrieNode() { 1263 | val = 0; 1264 | memset(next, -1, sizeof(next)); 1265 | ended = false; 1266 | count = 0; 1267 | childCount = 0; 1268 | 1269 | prev = -1; 1270 | suffixEnded = false; 1271 | memset(suffix, -1, sizeof(suffix)); 1272 | } 1273 | 1274 | void show() { 1275 | cerr << 1276 | "Val: " << val << 1277 | ", prev = " << prev << 1278 | ", ended = " << ended << 1279 | ", count = " << count << 1280 | ", childCount = " << childCount 1281 | << "\n\t "; 1282 | for (int i = 0; i < 4; i++) 1283 | cerr << (char)('a' + i) << ":" << next[i] << " "; 1284 | cerr 1285 | << "\n\tsuffix suffixEnded = " << suffixEnded << "\n" 1286 | << "\t "; 1287 | for (int i = 0; i < 4; i++) 1288 | cerr << (char)('a' + i) << ":" << suffix[i] << " "; 1289 | cerr << endl; 1290 | } 1291 | }; 1292 | 1293 | struct Trie 1294 | { 1295 | TrieNode node[HHH]; 1296 | int size; // the index of last node 1297 | int add(string& s) { // return index of new node 1298 | int preIndex = 0; 1299 | for (int i = 0; i < s.length(); i++) { 1300 | TrieNode& pre = node[preIndex]; 1301 | int& curIndex = pre.next[s[i] - 'a']; 1302 | if (curIndex == -1) { 1303 | size++; 1304 | curIndex = size; 1305 | } 1306 | TrieNode& cur = node[curIndex]; 1307 | cur.val = s[i]; 1308 | cur.childCount++; 1309 | 1310 | preIndex = curIndex; 1311 | } 1312 | node[preIndex].ended = true; 1313 | node[preIndex].count++; 1314 | node[0].childCount++; 1315 | return preIndex; 1316 | }; 1317 | 1318 | void buildSuffix() { 1319 | queue q; 1320 | for (int i = 0; i < 26; i++) { 1321 | int& next = node[0].next[i]; 1322 | int& suffix = node[0].suffix[i]; 1323 | 1324 | suffix = 0; 1325 | if (next == -1) 1326 | next = 0; 1327 | else { 1328 | q.push(next); 1329 | node[next].prev = 0; 1330 | } 1331 | } 1332 | 1333 | while (q.size()) { 1334 | int cur = q.front(); q.pop(); 1335 | int prev = node[cur].prev; 1336 | int prevSuffix = node[prev].suffix[node[cur].val - 'a']; 1337 | if (node[prevSuffix].ended) 1338 | node[cur].suffixEnded = true; 1339 | 1340 | for (int i = 0; i < 26; i++) { 1341 | int& next = node[cur].next[i]; 1342 | int& suffix = node[cur].suffix[i]; 1343 | 1344 | suffix = node[prevSuffix].next[i]; 1345 | if (next == -1) 1346 | next = suffix; 1347 | else { 1348 | q.push(next); 1349 | node[next].prev = cur; 1350 | } 1351 | } 1352 | } 1353 | } 1354 | 1355 | int get(string& s) { // get index of node 1356 | int preIndex = 0; 1357 | for (int i = 0; i < s.length() && preIndex != -1; i++) 1358 | preIndex = node[preIndex].next[s[i] - 'a']; 1359 | return preIndex; 1360 | }; 1361 | 1362 | bool match(string& s) { 1363 | for (int i = 0, cur = 0; i < s.length(); i++) { 1364 | cur = node[cur].next[s[i] - 'a']; 1365 | if (node[cur].ended || node[cur].suffixEnded) 1366 | return true; 1367 | } 1368 | return false; 1369 | } 1370 | 1371 | Trie() { 1372 | size = 0; 1373 | }; 1374 | 1375 | void show() { 1376 | for (int i = 0; i <= size; i++) { 1377 | show_A(i); 1378 | node[i].show(); 1379 | } 1380 | } 1381 | }; 1382 | 1383 | int n, q; 1384 | Trie t; 1385 | 1386 | int main() { 1387 | cin >> n; 1388 | 1389 | string temp; 1390 | for (int i = 0; i < n; i++) { 1391 | cin >> temp; 1392 | t.add(temp); 1393 | } 1394 | 1395 | cin >> q; 1396 | for (int i = 0; i < q; i++) { 1397 | cin >> temp; 1398 | int index = t.get(temp); 1399 | 1400 | if (index == -1) 1401 | cout << 0 << endl; // not found 1402 | else 1403 | cout << t.node[index].childCount << endl; // found 1404 | } 1405 | 1406 | 1407 | // check if any word in dict appear in article 1408 | t.buildSuffix(); 1409 | 1410 | string article; cin >> article; 1411 | if (t.match(article)) 1412 | cout << "YES" << endl; 1413 | else 1414 | cout << "NO" << endl; 1415 | } 1416 | ``` 1417 | 1418 | ```c++ 1419 | // http://blog.csdn.net/u010700335/article/details/38930175 1420 | 1421 | const int maxn = 26;//26个小写字母或者大写字母,再加上0~9就是72 1422 | //定义字典树结构体 1423 | typedef struct Trie 1424 | { 1425 | bool flag;//从根到此是否为一个单词 1426 | Trie *next[maxn];//有多少个分支 1427 | }Trie; 1428 | // 声明一个根,不含任何信息 1429 | Trie *root; 1430 | //初始化该根 1431 | void trie_init() 1432 | { 1433 | int i; 1434 | root = new Trie; 1435 | root->flag = false; 1436 | for(i=0;inext[i] = NULL; 1438 | } 1439 | // 插入一个字符串 1440 | void trie_insert(char *word) 1441 | { 1442 | //int i = 0; 1443 | //while(word[i] != '\0') 1444 | Trie *tem = root; 1445 | int i; 1446 | while(*word != '\0') 1447 | { 1448 | // cout << "root**" << tem->next[0]; 1449 | if(tem->next[*word-'a'] == NULL)// 为空才建立 1450 | { 1451 | Trie *cur = new Trie; 1452 | cur->flag = false; 1453 | for(i=0;inext[i] = NULL; 1455 | tem->next[*word-'a'] = cur; 1456 | } 1457 | tem = tem->next[*word-'a']; 1458 | //cout << *word << "**"; 1459 | word++; 1460 | } 1461 | tem->flag = true;//插入一个完整的单词 1462 | } 1463 | // 查找一个字符串 1464 | bool trie_search(char *word) 1465 | { 1466 | Trie *tem = root; 1467 | int i; 1468 | for(i=0; word[i]!='\0'; i++) 1469 | { 1470 | if(tem==NULL || tem->next[word[i]-'a']==NULL) 1471 | return false; 1472 | tem = tem->next[word[i]-'a']; 1473 | } 1474 | return tem->flag; 1475 | } 1476 | 1477 | 1478 | void trie_del(Trie *cur) 1479 | { 1480 | int i; 1481 | for(i=0;inext[i] != NULL) 1484 | trie_del(cur->next[i]); 1485 | } 1486 | delete cur; 1487 | } 1488 | 1489 | 1490 | int main() 1491 | { 1492 | int i,n; 1493 | char tmp[50]; 1494 | trie_init(); 1495 | cout << "请输入初始化字典树的字符串(字符0结束):" << endl; 1496 | while(cin >> tmp) 1497 | { 1498 | //cout << tmp << endl; 1499 | if(tmp[0] == '0' && tmp[1] =='\0') break; 1500 | trie_insert(tmp); 1501 | } 1502 | cout << "请输入要查找的字符串:" << endl; 1503 | while(cin >> tmp) 1504 | { 1505 | //cout << tmp << endl; 1506 | if(tmp[0] == '0' && tmp[1] =='\0') break; 1507 | if(trie_search(tmp)) 1508 | cout << "查找成功!再次输入查找,字符0结束查找:" << endl; 1509 | else 1510 | cout << "查找失败!再次输入查找,字符0结束查找:" << endl; 1511 | } 1512 | return 0; 1513 | } 1514 | ``` 1515 | 1516 | ### 2.4 Suffix Tree 1517 | 1518 | ### 2.5 Suffix Array 1519 | 1520 | ```c++ 1521 | int main() { 1522 | cin >> s; 1523 | build_suffix_array(); 1524 | compute_lcp(); 1525 | longest_repeated_substring(); 1526 | 1527 | longest_common_substring("GATAGACA", "CATA"); 1528 | } 1529 | ``` 1530 | 1531 | #### 2.5.1 Build Suffix Array 1532 | 1533 | > O(nlog(n)) 1534 | > 1535 | > reference: Competitve Programming 2 1536 | 1537 | ```c++ 1538 | #include 1539 | #include 1540 | #include 1541 | 1542 | using namespace std; 1543 | 1544 | #define HH 100002 1545 | 1546 | const char base_char = '.'; 1547 | string s; 1548 | int rank_array[HH]; 1549 | int rank_array_temp[HH]; 1550 | int suffix_array[HH]; 1551 | int suffix_array_temp[HH]; 1552 | int counter[HH]; 1553 | 1554 | void counting_sort(int k) { 1555 | memset(counter, 0, sizeof(counter)); 1556 | 1557 | int len = s.length(); 1558 | for (int i = 0; i < len; i++) { 1559 | // i will cover all suffix_array[i] 1560 | // so i + k will cover all suffix_array[i] + k 1561 | // so just use i + k instead of suffix_array[i] for counting 1562 | // the order is not important anyway 1563 | int old_rank = i + k < len ? rank_array[i + k] : 0; 1564 | counter[old_rank]++; 1565 | } 1566 | 1567 | int accu = 0; 1568 | int largest_possible_value = max(256, len); // initial rank is based on ascii value 1569 | for (int i = 0; i < largest_possible_value; i++) { 1570 | // counter[x]: 2, 1, 0, 0, 2, 0 1571 | // become : 0, 2, 3, 3, 3, 5 1572 | // which stands for the new rank with that old rank x 1573 | // the meaning changes here !! 1574 | int count_temp = counter[i]; 1575 | counter[i] = accu; 1576 | accu += count_temp; 1577 | } 1578 | 1579 | for (int i = 0; i < len; i++) { 1580 | // for each suffix_array[i] 1581 | // get its new rank using its old rank suffix_array[i] + k 1582 | // above if i + k >= n, we change it to 0 1583 | // the same here 1584 | int old_rank = suffix_array[i] + k < len ? rank_array[suffix_array[i] + k] : 0; 1585 | // value of counter[old_rank] is the new rank 1586 | // put suffix_array[i] to its new position == new rank 1587 | // why ++ ? suppose 1588 | // counter[x]: 0, 2, 3, 3, 3, 5 1589 | // gradually it become 1590 | // counter[x]: 1, 2, 3, 3, 3, 5 1591 | // counter[x]: 2, 2, 3, 3, 3, 5 1592 | // counter[x]: 2, 3, 3, 3, 3, 5 1593 | // ... thus assign each suffix_array[x] distinguished value 1594 | // even if there keys are the same 1595 | // but relation between different key keeps 1596 | // why assign distinguished rank ? 1597 | // of course... otherwise multiple suffix_array[i] (different suffix) go to same suffix_array[x] 1598 | // the rank of them are still kept in the rank_array[x] 1599 | // later will compress the rank 1600 | // keeping the order between those with same key 1601 | // eventually all the rank will be different 1602 | suffix_array_temp[counter[old_rank]++] = suffix_array[i]; 1603 | } 1604 | memcpy(suffix_array, suffix_array_temp, sizeof(suffix_array)); 1605 | } 1606 | void build_suffix_array() { 1607 | int len = s.length(); 1608 | for (int i = 0; i < len; i++) 1609 | rank_array[i] = s[i] - base_char; // initial rank // based on 1st char 1610 | for (int i = 0; i < len; i++) 1611 | suffix_array[i] = i; // initialize 1612 | 1613 | for (int k = 1; k < len; k <<= 1) { 1614 | // sort based on 2^i portion 1615 | // finally all will be sorted 1616 | 1617 | // [0, i + k) is first part 1618 | // [i + k, i + k + k) is second part 1619 | // sort second part then first part 1620 | // leading to a stable_sort (?) 1621 | // use [i + k, i + k + k) as key first 1622 | // then use [0, i + k) as key 1623 | counting_sort(k); 1624 | counting_sort(0); 1625 | 1626 | // after spread suffix with same rank into differnt suffix_array[x] slot (consecutive) 1627 | // compress the rank_array 1628 | // so that suffix with same second part [i + k, i + k + k) (which is the rank...) 1629 | // have same rank... 1630 | int rank = 0; 1631 | rank_array_temp[suffix_array[0]] = rank; 1632 | for (int i = 1; i < len; i++) { 1633 | if (rank_array[suffix_array[i - 1]] != rank_array[suffix_array[i]] 1634 | || 1635 | rank_array[suffix_array[i] + k] != rank_array[suffix_array[i - 1] + k]) 1636 | rank++; 1637 | rank_array_temp[suffix_array[i]] = rank; 1638 | } 1639 | memcpy(rank_array, rank_array_temp, sizeof(rank_array)); 1640 | } 1641 | 1642 | for (int i = 0; i < len; i++) 1643 | cout << "i: " << i << ", suffix " << suffix_array[i] << " : " << s.substr(suffix_array[i], s.length() - suffix_array[i]) << endl; 1644 | 1645 | cout << endl; 1646 | } 1647 | ``` 1648 | 1649 | #### 2.5.2 Pattern Matching 1650 | 1651 | > O(mlog(n)) 1652 | 1653 | ```c++ 1654 | void find_pattern(const string& pattern) { 1655 | // binary search upper bound & lower bound (?) in the suffix array 1656 | // to get a matched range 1657 | // let m = pattern.length() 1658 | // let n = s.length() 1659 | // time complexity: O(mlog(n)) 1660 | } 1661 | ``` 1662 | 1663 | #### 2.5.3 Longest Common Prefix 1664 | 1665 | > length of common prefix between suffix_array[i-1] and suffix_array[i] 1666 | > 1667 | > let n = s.length() 1668 | > 1669 | > O(n) 1670 | 1671 | ```c++ 1672 | 1673 | // 1674 | // ... 1675 | // 1676 | 1677 | int longest_common_prefix[HH]; // lcp[i] = length of common prefix between sa[i-1] and sa[i] 1678 | int phi[HH]; // phi[sa[i]] = sa[i-1] // naming ? // useless when built 1679 | int permuted_lcp[HH]; // useless when built temp for lcp 1680 | 1681 | void compute_lcp() { 1682 | // theorem: number of increase/decrese on cur_lcp is O(len) 1683 | // so time complexity: O(len) for computing lcp 1684 | int len = s.length(); 1685 | phi[suffix_array[0]] = -1; 1686 | for (int i = 1; i < len; i++) 1687 | phi[suffix_array[i]] = suffix_array[i - 1]; 1688 | for (int i = 0, cur_lcp = 0; i < len; i++) { 1689 | if (phi[i] == 0) 1690 | permuted_lcp[i] = 0; 1691 | else { 1692 | while (s[i + cur_lcp] == s[phi[i] + cur_lcp]) 1693 | cur_lcp++; 1694 | permuted_lcp[i] = cur_lcp; 1695 | cur_lcp = max(cur_lcp - 1, 0); 1696 | } 1697 | } 1698 | for (int i = 0; i < len; i++) 1699 | longest_common_prefix[i] = permuted_lcp[suffix_array[i]]; 1700 | 1701 | for (int i = 0; i < len; i++) 1702 | cout << "i: " << i << ", suffix " << suffix_array[i] << " (lcp: " << longest_common_prefix[i] << ") : " << s.substr(suffix_array[i], s.length() - suffix_array[i]) << endl; 1703 | cout << endl; 1704 | } 1705 | ``` 1706 | 1707 | #### 2.5.4 Longest Repeated Substring 1708 | 1709 | > let n = s.length() 1710 | > 1711 | > O(n) 1712 | 1713 | ```c++ 1714 | void longest_repeated_substring() { 1715 | int len = s.length(); 1716 | int max_repeated = -1; 1717 | int i_max = -1; 1718 | for (int i = 0; i < len; i++) { 1719 | if (longest_common_prefix[i] > max_repeated) { 1720 | max_repeated = longest_common_prefix[i]; 1721 | i_max = i; 1722 | } 1723 | } 1724 | cout << "longest repeated substring: " << s.substr(suffix_array[i_max], max_repeated) << endl; 1725 | } 1726 | ``` 1727 | 1728 | #### 2.5.5 Longest Common Substring 1729 | 1730 | > string a, b (also applies to multiple strings) 1731 | > 1732 | > construct Suffix Array of a.b & find Longest Common Prefix 1733 | > 1734 | > let n = max(a.length(), b.length()) 1735 | > 1736 | > O(nlog(n) + n) 1737 | 1738 | ```c++ 1739 | void longest_common_substring(const string& a, const string& b) { 1740 | s = a + base_char + b; 1741 | cout << "concatenated string: " << s << endl; 1742 | 1743 | build_suffix_array(); 1744 | compute_lcp(); 1745 | 1746 | int len = s.length(); 1747 | int max_common = -1; 1748 | int i_max = -1; 1749 | for (int i = 1; i < len; i++) { 1750 | int cur_lcp = longest_common_prefix[i]; 1751 | if (cur_lcp > max_common) { 1752 | if ((suffix_array[i] < a.length()) ^ (suffix_array[i - 1] < a.length())) { 1753 | max_common = cur_lcp; 1754 | i_max = i; 1755 | } 1756 | } 1757 | } 1758 | cout << "longest common prefix: " << s.substr(suffix_array[i_max], max_common) << endl; 1759 | } 1760 | ``` 1761 | 1762 | ### 2.6 Binary Indexed Tree 1763 | 1764 | > Binary Indexed Tree 1765 | 1766 | > O(logN) to query and update SUM(a[1]~a[i]) 1767 | 1768 | ```C++ 1769 | #define MAX_INDEX nnn 1770 | 1771 | int tree[MAX_INDEX + 1]; // 1 <= I <= MAX_INDEX 1772 | 1773 | int low_bit(int i) { 1774 | return i & -i; 1775 | } 1776 | 1777 | int query(int i) { 1778 | int ans = 0; 1779 | for (; i > 0; i -= low_bit(i)) 1780 | ans += tree[i]; 1781 | return ans; 1782 | } 1783 | 1784 | void insert(int i, int value) { 1785 | for (; i <= MAX_INDEX; i += low_bit(i)) 1786 | tree[i] += value; 1787 | } 1788 | ``` 1789 | 1790 | > 修改区间+查询点, 1791 | > 1792 | > 【1】修改操作:将A[l..r]之间的全部元素值加上c; 1793 | > 1794 | > 【2】求和操作:求此时A[x]的值。 1795 | > 1796 | > 这个模型中需要设置一个辅助数组B:B[i]表示A[1..i]到目前为止共被整体加了多少 1797 | 1798 | ```C++ 1799 | #define INTERVAL_LIMIT 100005 1800 | 1801 | int tree_add_i_n[INTERVAL_LIMIT]; 1802 | 1803 | int low_bit(int i) { 1804 | return i & -i; 1805 | } 1806 | 1807 | int query(int i, int* tree, int UP_LIMIT) { 1808 | int ans = 0; 1809 | for (; i > 0; i -= low_bit(i)) 1810 | ans += tree[i]; 1811 | return ans; 1812 | } 1813 | 1814 | void insert(int i, int value, int* tree, int UP_LIMIT) { 1815 | for (; i <= UP_LIMIT; i += low_bit(i)) 1816 | tree[i] += value; 1817 | } 1818 | 1819 | int main() { 1820 | memset(tree_add_in, 0, sizeof(tree_add_in)); 1821 | insert(3, 1, tree_add_in, INTERVAL_LIMIT); 1822 | insert(5, -1, tree_add_in, INTERVAL_LIMIT); 1823 | insert(4, 2, tree_add_in, INTERVAL_LIMIT); 1824 | insert(6, -2, tree_add_in, INTERVAL_LIMIT); 1825 | 1826 | for (int i = 1; i <= 7; i++) 1827 | SHOW_B(i, query(i, tree_add_in, INTERVAL_LIMIT)); 1828 | } 1829 | ``` 1830 | 1831 | > 修改区间+查询区间 1832 | > 1833 | > b[i]: add b[i] to a[i], a[i+1], ..., a[n] 1834 | > 1835 | > so 1836 | > 1837 | > sigma(i): a[1] + a[2] + ... + a[i] 1838 | > 1839 | > sigma(i) = ib[1] + (i-1)b[2] + ... + 2b[i-1] + b[i] 1840 | > 1841 | > sigma(i) = (i+1){b[1] + b[2] + ... + b[i]} - {b[1] + 2b[2] + ... + ib[i]} 1842 | > 1843 | > so use one more tree c[i] 1844 | > 1845 | > c[i]: 1b[1] + 2b[2] + ... + ib[i] 1846 | 1847 | ### 2.7 Segment Tree 1848 | 1849 | #### 2.7.0 Range Update + Range Query 1850 | 1851 | > with lazy propagation 1852 | > 1853 | > build O(N) 1854 | > 1855 | > query O(log(N)) 1856 | > 1857 | > update O(log(N)) 1858 | 1859 | ```c++ 1860 | struct SegmentTree { 1861 | struct Op { // store lazy operation 1862 | int h; 1863 | }; 1864 | struct Node { 1865 | int l; // [l, ] 1866 | int r; // [, r] 1867 | 1868 | int h; // value 1869 | 1870 | bool lazy; 1871 | Op op; 1872 | }; 1873 | 1874 | vector node; 1875 | void init(int l, int r) { // [l, r] 1876 | int tree_range = r - l + 1; 1877 | if (tree_range <= 0) 1878 | return ; 1879 | 1880 | int tree_size = 1; 1881 | while (tree_size <= tree_range) 1882 | tree_size <<= 1; 1883 | if (__builtin_popcount(tree_range) != 1) // count number of '1' bits 1884 | tree_size <<= 1; 1885 | 1886 | node.resize(tree_size); // (tree_range, tree_size): (001001, 100000) (001000, 010000) 1887 | 1888 | Node& root = node[1]; 1889 | root.l = l, root.r = r; 1890 | root.h = root.op.h = 0; 1891 | for (int i = 2; i < node.size(); i++) { 1892 | Node& cur = node[i]; 1893 | cur.h = 0; 1894 | 1895 | const Node& par = node[i / 2]; // parent node 1896 | if (par.l == par.r) // if parent is end node, skip 1897 | cur.l = cur.r = -1; 1898 | else { 1899 | int m = (par.l + par.r) / 2; 1900 | if (i % 2) 1901 | cur.l = m + 1, cur.r = par.r; 1902 | else 1903 | cur.l = par.l, cur.r = m; 1904 | } 1905 | } 1906 | } 1907 | 1908 | void show() { 1909 | SHOW("SegmentTree NAME") 1910 | for (int i = 1; i < node.size(); i++) { 1911 | Node& cur = node[i]; 1912 | if (cur.l == -1 && cur.r == -1) 1913 | continue; 1914 | PRINTLN("(%2d) [%2d,%2d] val: %d", i, cur.l, cur.r, cur.internal) 1915 | } 1916 | } 1917 | 1918 | int query(int xl, int xr, int i = 1) { // query [xl, xr] 1919 | Node& cur = node[i]; 1920 | if (cur.l == cur.r) // if end node 1921 | return cur.h; 1922 | 1923 | if (xl <= cur.l && cur.r <= xr) // if query cover the node 1924 | return cur.h; 1925 | 1926 | int lci = i * 2; 1927 | const Node& lc = node[lci]; 1928 | int rci = lci + 1; 1929 | const Node& rc = node[rci]; 1930 | if (cur.lazy) { // if have lazy operation, push down 1931 | update(lc.l, lc.r, cur.op.h, lci); 1932 | update(rc.l, rc.r, cur.op.h, rci); 1933 | cur.lazy = false; 1934 | } 1935 | 1936 | int ret = INT_MAX; 1937 | if (xl <= lc.r) { // if query cover left child 1938 | int temp = query(xl, xr, lci); 1939 | if (ret > temp) 1940 | ret = temp; 1941 | } 1942 | if (rc.l <= xr) { // if query cover right child 1943 | int temp = query(xl, xr, rci); 1944 | if (ret > temp) 1945 | ret = temp; 1946 | } 1947 | return ret; 1948 | } 1949 | 1950 | void update(int xl, int xr, int xh, int i = 1) { // update [xl, xr] value xh 1951 | Node& cur = node[i]; 1952 | if (cur.l == cur.r) { // if end node 1953 | if (cur.h < xh) 1954 | cur.h = xh; 1955 | return ; 1956 | } 1957 | 1958 | if (xl <= cur.l && cur.r <= xr) { // if query cover the node 1959 | if (cur.h < xh) { // update node value 1960 | cur.h = xh; 1961 | } 1962 | if (cur.lazy) { // update the lazy operation // slow if push down now 1963 | if (cur.op.h < xh) 1964 | cur.op.h = xh; 1965 | } 1966 | else { // store lazy operation 1967 | cur.op.h = xh; 1968 | cur.lazy = true; 1969 | } 1970 | return ; 1971 | } 1972 | 1973 | int lci = i * 2; 1974 | const Node& lc = node[lci]; 1975 | int rci = lci + 1; 1976 | const Node& rc = node[rci]; 1977 | if (cur.lazy) { // if have lazy operation, push down 1978 | update(lc.l, lc.r, cur.op.h, lci); 1979 | update(rc.l, rc.r, cur.op.h, rci); 1980 | cur.lazy = false; 1981 | } 1982 | 1983 | if (xl <= lc.r) // if update cover left node 1984 | update(xl, xr, xh, lci); 1985 | if (rc.l <= xr) // if update cover right node 1986 | update(xl, xr, xh, rci); 1987 | 1988 | cur.h = min(lc.h, rc.h); // reduce two children 1989 | } 1990 | }; 1991 | ``` 1992 | 1993 | ### 2.8 Range Minimum Query RMQ 1994 | 1995 | ```c++ 1996 | struct RMQ { // not tested 1997 | const static int MAXLENGTH = 2 * 1e5 + 3; 1998 | const static int LOG_MAXLENGTH = 20; 1999 | int rmq[MAXLENGTH][LOG_MAXLENGTH]; 2000 | 2001 | void init(int* arr, int len) { 2002 | for (int i = 0; i < len; i++) 2003 | rmq[i][0] = arr[i]; 2004 | for (int j = 1; j < LOG_MAXLENGTH; j++) 2005 | for (int i = 0; i < len; i++) { 2006 | if (i + (1 << j) > len) 2007 | break; 2008 | rmq[i][j] = rmq[i][j - 1]; 2009 | rmq[i][j] = min(rmq[i][j - 1], rmq[i + (1 << (j - 1))][j-1]); 2010 | } 2011 | } 2012 | 2013 | int range_minimum_query(int l, int r) { 2014 | if (l > r) 2015 | swap(l, r); 2016 | 2017 | int interval_len = r - l; // less 1 2018 | 2019 | int first_half = 1; 2020 | while ((1 << first_half) <= interval_len) 2021 | first_half++; 2022 | first_half--; 2023 | 2024 | int second_half = r - (1 << first_half) + 1; 2025 | return min(rmq[l][first_half], rmq[second_half][first_half]); 2026 | } 2027 | }; 2028 | ``` 2029 | 2030 | ### 2.9 Union-find Set 2031 | 2032 | ```C++ 2033 | struct UnionFindSet { 2034 | vector parent; 2035 | void init(int nn) { 2036 | parent.resize(nn + 1); 2037 | for (int i = 0; i < parent.size(); i++) 2038 | parent[i] = i; 2039 | } 2040 | 2041 | void merge(int x, int y) { 2042 | parent[find(x)] = find(y); 2043 | } 2044 | int find(int x) { 2045 | return x == parent[x] ? x : parent[x] = find(parent[x]); 2046 | } 2047 | bool together(int x, int y) { 2048 | return find(x) == find(y); 2049 | } 2050 | }; 2051 | ``` 2052 | 2053 | ### 2.10 Bloom Filter (?) (Similar) 2054 | 2055 | > Can calculate hash of number sequence quickly. 2056 | > 2057 | > If too slow, set REPEAT smaller. Or try again:) 2058 | 2059 | 2060 | ```c++ 2061 | #include 2062 | 2063 | struct BloomFilterSimilar { 2064 | static const int MAXN = 100002; 2065 | static const int REPEAT = 10; 2066 | 2067 | unsigned long long hash_constant[REPEAT][MAXN]; 2068 | set hash[REPEAT]; 2069 | 2070 | void init_hash(int max_n=MAXN) { 2071 | random_device rd; 2072 | mt19937 gen(rd()); 2073 | uniform_int_distribution dis(1, ULLONG_MAX); 2074 | for (int i = 0; i < REPEAT; i++) { 2075 | for (int j = 0; j < max_n; j++) 2076 | hash_constant[i][j] = dis(gen); 2077 | } 2078 | } 2079 | 2080 | vector get_hash(int val) { 2081 | vector h(REPEAT); 2082 | for (int i = 0; i < REPEAT; i++) 2083 | h[i] = hash_constant[i][val]; 2084 | return move(h); 2085 | } 2086 | 2087 | // bool exist(int val) { 2088 | // return exist(get_hash(val)); 2089 | // } 2090 | bool exist(const vector& h) { 2091 | for (int i = 0; i < REPEAT; i++) 2092 | if (hash[i].find(h[i]) == end(hash[i])) 2093 | return false; 2094 | return true; // possible False Positive 2095 | } 2096 | 2097 | // void insert(int val) { 2098 | // insert(get_hash(val)); 2099 | // } 2100 | void insert(const vector& h) { 2101 | for (int i = 0; i < REPEAT; i++) 2102 | hash[i].insert(h[i]); 2103 | } 2104 | }; 2105 | ``` 2106 | 2107 | ## 3. Methodology 2108 | 2109 | ### 3.0 Greedy 2110 | 2111 | > It's Art. 2112 | 2113 | ### 3.1 Recursive 2114 | 2115 | #### 3.1.1 Hanoi 2116 | 2117 | ```C++ 2118 | void hanoi(int n, char x, char y, char z) { // 将 x 上编号 1 至 n 的圆盘移到 z, y 作辅助塔 2119 | if (n == 1) 2120 | printf("%d from %c to %c\n", n, x, z); // 将编号为 n 的圆盘从 x 移到 z 2121 | else { 2122 | hanoi(n-1, x, z, y); // 将 x 上编号 1 至 n-1 的圆盘移到 y, z 作辅助塔 2123 | printf("%d from %c to %c\n", n, x, z); // 将编号为 n 的圆盘从 x 移到 z 2124 | hanoi(n-1, y, x, z); // 将 y 上编号 1 至 n-1 的圆盘移到 z, x 作辅助塔 2125 | } 2126 | } 2127 | ``` 2128 | 2129 | ### 3.2 Dynamic Programming 2130 | 2131 | #### 3.2.1 Longest Increasing Subsequence (LIS) 2132 | 2133 | > O(nlog(n)) 2134 | 2135 | ```c++ 2136 | vector sequence; 2137 | vector lis(sequence.size() + 1, INT_MAX); // [i]: min value in sequence that have LIS = i 2138 | for (int i = 0; i < sequence.size(); i++) { 2139 | int r = sequence[i]; 2140 | auto ptr = lower_bound(begin(lis), end(lis), r); 2141 | *ptr = min(*ptr, r); 2142 | } 2143 | ``` 2144 | 2145 | ### 3.3 Divide and Conquer 2146 | 2147 | #### 3.3.1 binary search 2148 | 2149 | ### 3.4 Search 2150 | 2151 | #### 3.4.2 双向 BFS 2152 | 2153 | #### 3.4.3 从终点开始搜 2154 | 2155 | #### 3.4.4 迭代加深搜索 (binary increase/decrease) 2156 | 2157 | > placeholder 2158 | 2159 | ### 3.5 Brute Force 2160 | 2161 | #### 3.5.1 子集生成 2162 | 2163 | ## 4. String 2164 | 2165 | ### 4.1 KMP 2166 | 2167 | > Match pattern in a string 2168 | > 2169 | > O(n) = O(len(pattern) + len(string)) 2170 | 2171 | ```C++ 2172 | #define HHH 10003 2173 | 2174 | int ne[HHH]; // next[], if par[i] not matched, jump to i = ne[i] 2175 | int kmp(string& par, string& ori) { 2176 | ne[0] = -1; 2177 | for (int p = ne[0], i = 1; i < par.length(); i++) { 2178 | while (p >= 0 && par[p+1] != par[i]) 2179 | p = ne[p]; 2180 | if (par[p+1] == par[i]) 2181 | p++; 2182 | ne[i] = p; 2183 | } 2184 | 2185 | int match = 0; 2186 | for (int p = -1, q = 0; q < ori.length(); q++) { 2187 | while (p >= 0 && par[p+1] != ori[q]) 2188 | p = ne[p]; 2189 | if (par[p+1] == ori[q]) 2190 | p++; 2191 | if (p + 1 == par.length()) { // match! 2192 | p = ne[p]; 2193 | match++; 2194 | } 2195 | } 2196 | 2197 | return match; // return number of occurance 2198 | } 2199 | 2200 | int main () { 2201 | int n; cin >> n; 2202 | string par, ori; 2203 | while (cin >> par >> ori) 2204 | cout << kmp(par, ori) << endl; 2205 | return 0; 2206 | } 2207 | ``` 2208 | 2209 | ### 4.2 Boyer-Moore 2210 | 2211 | ### 4.3 Longest palindromic substring (Manacher's algorithm) 2212 | 2213 | > O(n) 2214 | 2215 | ```c++ 2216 | int dp[HHH]; 2217 | int lengthLongestPalindromSubstring(string& s) { 2218 | memset(dp, 0, sizeof(dp)); 2219 | int ans = 0; 2220 | int pivot = 1; 2221 | int len = s.length() * 2; // _s0_s1_s2 = 2 * length 2222 | for (int i = 1; i < len; i++) { 2223 | int pBorder = pivot + dp[pivot]; 2224 | int iBorder = i; 2225 | if (iBorder < pBorder && 2 * pivot - i > 0) { 2226 | dp[i] = dp[2*pivot-i]; 2227 | iBorder = min(pBorder, i + dp[i]); 2228 | } 2229 | 2230 | if (iBorder >= pBorder) { 2231 | int j = iBorder + (iBorder % 2 ? 2 : 1); 2232 | for (; j < len && 2*i-j > 0 && s[j/2] == s[(2*i-j)/2]; j += 2) 2233 | ; 2234 | iBorder = j - 2; 2235 | dp[i] = iBorder - i; 2236 | pivot = i; 2237 | } 2238 | ans = max(ans, dp[i] + 1); 2239 | } 2240 | 2241 | return ans; 2242 | } 2243 | 2244 | int main () { 2245 | int n; cin >> n; 2246 | string s; 2247 | while (cin >> s) 2248 | cout << lengthLongestPalindromSubstring(s) << endl; 2249 | return 0; 2250 | } 2251 | ``` 2252 | 2253 | ## 5. Graph 2254 | 2255 | ### 5.1 Graph Structure 2256 | 2257 | ```c++ 2258 | struct Graph { 2259 | struct Edge { 2260 | int from; 2261 | int to; 2262 | int len; 2263 | }; 2264 | 2265 | const static int MAXNODE = 3 * 1e5 + 2; 2266 | vector g[MAXNODE]; 2267 | vector edge; 2268 | int n; 2269 | void init(int nn) { 2270 | n = nn; 2271 | for (int i = 0; i <= n; i++) 2272 | g[i].clear(); 2273 | edge.clear(); 2274 | } 2275 | 2276 | void add_e(int x, int y, int len) { 2277 | g[x].push_back(edge.size()); 2278 | edge.push_back((Edge){x, y, len}); 2279 | g[y].push_back(edge.size()); 2280 | edge.push_back((Edge){y, x, len}); 2281 | } 2282 | 2283 | void show() { 2284 | for (int i = 0; i <= n; i++) { 2285 | printf("%d:", i); 2286 | for (int ie : g[i]) 2287 | printf(" %d", edge[ie].to); 2288 | printf("\n"); 2289 | } 2290 | printf("\n"); 2291 | } 2292 | }; 2293 | ``` 2294 | 2295 | ```c++ 2296 | struct Network { 2297 | struct Edge { 2298 | int to; 2299 | int pre_edge; 2300 | int cap; 2301 | int flow; 2302 | }; 2303 | 2304 | vector last; 2305 | 2306 | int nv; // total number of vertex, index range: [0, nv) 2307 | vector edge; 2308 | void init(int _nv) { 2309 | nv = _nv; 2310 | vector().swap(edge); 2311 | vector(nv + 1, -1).swap(last); 2312 | } 2313 | 2314 | void add_e(int x, int y, int cap, int r_cap = 0) { 2315 | Edge e{y, last[x], cap, 0}; 2316 | last[x] = edge.size(); 2317 | edge.push_back(move(e)); 2318 | 2319 | Edge r_e{x, last[y], r_cap, 0}; 2320 | last[y] = edge.size(); 2321 | edge.push_back(move(r_e)); 2322 | } 2323 | void show_edge() { 2324 | for (int i = 0; i < nv; i++) { 2325 | printf("%d:", i); 2326 | for (int ie = last[i]; ie != -1; ) { 2327 | const Edge& e = edge[ie]; 2328 | ie = e.pre_edge; 2329 | printf(" (%d)%d/%d", e.to, e.flow, e.cap); 2330 | } 2331 | printf("\n"); 2332 | } 2333 | printf("\n"); 2334 | } 2335 | } 2336 | ``` 2337 | 2338 | ### 5.2 Minimium Spanning Tree 2339 | 2340 | #### 5.2.1 Prim's 2341 | 2342 | > O((V + E)log(V)) 2343 | 2344 | ```C++ 2345 | struct Graph { 2346 | struct Edge { 2347 | int from; 2348 | int to; 2349 | int len; 2350 | }; 2351 | 2352 | const static int MAXNODE = 3 * 1e5 + 2; 2353 | vector g[MAXNODE]; 2354 | vector edge; 2355 | int n; 2356 | void init(int nn) { 2357 | n = nn; 2358 | for (int i = 0; i <= n; i++) 2359 | g[i].clear(); 2360 | edge.clear(); 2361 | } 2362 | 2363 | void add_e(int x, int y, int len) { 2364 | g[x].push_back(edge.size()); 2365 | edge.push_back((Edge){x, y, len}); 2366 | g[y].push_back(edge.size()); 2367 | edge.push_back((Edge){y, x, len}); 2368 | } 2369 | 2370 | void show() { 2371 | for (int i = 0; i <= n; i++) { 2372 | printf("%d:", i); 2373 | for (int ie : g[i]) 2374 | printf(" %d", edge[ie].to); 2375 | printf("\n"); 2376 | } 2377 | printf("\n"); 2378 | } 2379 | 2380 | // 2381 | // ---- start of Minimum Spanning Tree --- 2382 | // 2383 | vector added; 2384 | vector mindis; // little optimization 2385 | void mst() { 2386 | vector(n + 1, false).swap(added); 2387 | vector(n + 1, INT_MAX).swap(mindis); 2388 | 2389 | auto cmp = [](const Edge& a, const Edge& b) { 2390 | return a.len > b.len; 2391 | }; 2392 | priority_queue, decltype(cmp)> near(cmp); 2393 | for (int i = 0; i < g[1].size(); i++) { 2394 | const Edge& e = edge[g[1][i]]; 2395 | near.push(e); 2396 | mindis[e.to] = e.len; // little optimization 2397 | } 2398 | added[1] = true; 2399 | 2400 | while (near.size()) { 2401 | Edge cur = near.top(); near.pop(); 2402 | added[cur.to] = true; 2403 | // add Edge cur 2404 | for (int ie : g[cur.to]) { 2405 | const Edge& nxe = edge[ie]; 2406 | int nx = nxe.to; 2407 | if (!added[nx] 2408 | && mindis[nx] > nxe.len) { // little optimization 2409 | mindis[nx] = nxe.len; // little optimization 2410 | near.push(nxe); 2411 | } 2412 | } 2413 | while (near.size() && added[near.top().to]) 2414 | near.pop(); 2415 | } 2416 | // 2417 | } 2418 | // 2419 | // ---- end of Minimum Spanning Tree --- 2420 | // 2421 | }; 2422 | ``` 2423 | 2424 | #### 5.2.2 Kruskal 2425 | 2426 | > Elog(E) + Elog(V) 2427 | 2428 | ```C++ 2429 | struct Graph { 2430 | struct Edge { 2431 | int from; 2432 | int to; 2433 | int len; 2434 | }; 2435 | 2436 | const static int MAXNODE = 3 * 1e5 + 2; 2437 | vector g[MAXNODE]; 2438 | vector edge; 2439 | int n; 2440 | void init(int nn) { 2441 | n = nn; 2442 | for (int i = 0; i <= n; i++) 2443 | g[i].clear(); 2444 | edge.clear(); 2445 | } 2446 | 2447 | void add_e(int x, int y, int len) { 2448 | g[x].push_back(edge.size()); 2449 | edge.push_back((Edge){x, y, len}); 2450 | g[y].push_back(edge.size()); 2451 | edge.push_back((Edge){y, x, len}); 2452 | } 2453 | 2454 | void show() { 2455 | for (int i = 0; i <= n; i++) { 2456 | printf("%d:", i); 2457 | for (int ie : g[i]) 2458 | printf(" %d", edge[ie].to); 2459 | printf("\n"); 2460 | } 2461 | printf("\n"); 2462 | } 2463 | 2464 | // 2465 | // ---- start of Minimum Spanning Tree --- 2466 | // 2467 | UnionFindSet ufs; 2468 | void mst() { 2469 | ufs.init(n); 2470 | vector eee = edge; 2471 | sort(begin(eee), end(eee), [](const Edge& a, const Edge& b) { 2472 | return a.len < b.len; 2473 | }); 2474 | 2475 | int need = n - 1; 2476 | for (const auto& e : eee) { 2477 | if (!ufs.together(e.from, e.to)) { 2478 | // add Edge e 2479 | ufs.merge(e.from, e.to); 2480 | need--; 2481 | if (!need) 2482 | break; 2483 | } 2484 | } 2485 | } 2486 | // 2487 | // ---- end of Minimum Spanning Tree --- 2488 | // 2489 | }; 2490 | ``` 2491 | 2492 | 2493 | ### 5.3 Shortest Path 2494 | 2495 | #### 5.3.1 任意两点 2496 | 2497 | ``` 2498 | for (k) 2499 | for (i) 2500 | for (j) 2501 | d(i, j) = min(d(i, j), d(i, k) + d(j, k)) 2502 | ``` 2503 | 2504 | #### 5.3.2 Bellman–Ford 2505 | 2506 | > Bellman–Ford algorithm is O(VE). 2507 | > Can be applied to situations when there is a maximun number of vertices in shortest path. 2508 | 2509 | ``` 2510 | for (n times of relax) 2511 | for (each node) 2512 | relax each node 2513 | ``` 2514 | 2515 | #### 5.3.3 SPFA 2516 | 2517 | #### 5.3.4 Dijkstra 2518 | 2519 | > Dijkstra is good for graphs non-negative edges. 2520 | 2521 | > O(Vlog(E)) (?) 2522 | 2523 | ```c++ 2524 | void dijkstra(int s) { 2525 | map> m; 2526 | dist[s] = 0; 2527 | m[0].push(s); 2528 | while (m.size()) { 2529 | if (!m.begin()->second.size()) { 2530 | m.erase(m.begin()); 2531 | continue; 2532 | } 2533 | int cur = m.begin()->second.front(); 2534 | m.begin()->second.pop(); 2535 | if (done[cur]) continue; 2536 | done[cur] = true; 2537 | SHOW(cur, dist[cur]) 2538 | for (int next : children[cur]) { 2539 | if (!done[next] && dist[next] > dist[cur] + edge[cur][next]) { 2540 | dist[next] = dist[cur] + edge[cur][next]; 2541 | prev[next] = cur; 2542 | m[dist[next]].push(next); 2543 | } 2544 | } 2545 | } 2546 | cout << endl; 2547 | } 2548 | ``` 2549 | 2550 | If you want to write compare operator(). 2551 | 2552 | ```c++ 2553 | struct cmp { 2554 | bool operator()(pair a, pair b) { 2555 | return a.first > b.first; 2556 | } 2557 | }; 2558 | 2559 | void dijkstra(int s) { 2560 | priority_queue, vector>, cmp> q; 2561 | q.push(make_pair(0, s)); 2562 | dist[s] = 0; 2563 | while (q.size()) { 2564 | int cur = q.top().second; 2565 | q.pop(); 2566 | if (done[cur]) continue; 2567 | done[cur] = true; 2568 | SHOW(cur, dist[cur]) 2569 | for (int next : children[cur]) { 2570 | if (!done[next] && dist[next] > dist[cur] + edge[cur][next]) { 2571 | dist[next] = dist[cur] + edge[cur][next]; 2572 | q.push(make_pair(dist[next], next)); 2573 | prev[next] = cur; 2574 | } 2575 | } 2576 | } 2577 | } 2578 | ``` 2579 | 2580 | ### 5.4 Maximum Matching 2581 | 2582 | #### 5.4.1 on Bipartite Graph 二分图 2583 | 2584 | > 1. A graph is bipartite if and only if it does not contain an odd cycle. 2585 | > 2. A graph is bipartite if and only if it is 2-colorable, (i.e. its chromatic number is less than or equal to 2). 2586 | > 3. The spectrum of a graph is symmetric if and only if it's a bipartite graph. 2587 | 2588 | ##### 5.4.1.1 Hungarian algorithm 匈牙利算法 2589 | 2590 | > O(E * V) 2591 | 2592 | ```c++ 2593 | struct Network { 2594 | struct Edge { 2595 | int to; 2596 | int pre_edge; 2597 | int cap; 2598 | int flow; 2599 | }; 2600 | 2601 | #define MAXNODE 405 2602 | int last[MAXNODE]; 2603 | 2604 | int nv; // total number of vertex, index range: [0, nv) 2605 | vector edge; 2606 | void init(int _nv) { 2607 | nv = _nv; 2608 | edge.clear(); 2609 | fill(last, last + nv, -1); 2610 | } 2611 | 2612 | void add_e(int x, int y, int cap, int r_cap = 0) { 2613 | Edge e = {y, last[x], cap, 0}; 2614 | // Edge e{y, last[x], cap, 0}; 2615 | last[x] = edge.size(); 2616 | // edge.push_back(move(e)); 2617 | edge.push_back(e); 2618 | 2619 | Edge r_e = {x, last[y], r_cap, 0}; 2620 | // Edge r_e{x, last[y], r_cap, 0}; 2621 | last[y] = edge.size(); 2622 | // edge.push_back(move(r_e)); 2623 | edge.push_back(r_e); 2624 | } 2625 | void show_edge() { 2626 | for (int i = 0; i < nv; i++) { 2627 | printf("v [%d]:", i); 2628 | for (int ie = last[i]; ie != -1; ) { 2629 | const Edge& e = edge[ie]; 2630 | ie = e.pre_edge; 2631 | printf(" [%d]%d/%d", e.to, e.flow, e.cap); 2632 | } 2633 | printf("\n"); 2634 | } 2635 | printf("\n"); 2636 | } 2637 | 2638 | // 2639 | // bipartite match 2640 | // O(V * E) 2641 | int peer[MAXNODE]; 2642 | bool went[MAXNODE]; 2643 | int bipartite_match() { 2644 | fill(peer, peer + nv, -1); 2645 | int ans = 0; 2646 | for (int i = 0; i < nv; i++) { 2647 | if (last[i] == -1 || peer[i] != -1) 2648 | continue; 2649 | fill(went, went + nv, false); 2650 | if (match(i)) 2651 | ans++; 2652 | } 2653 | return ans; 2654 | } 2655 | bool match(int cur) { 2656 | for (int ie = last[cur]; ie != -1; ) { 2657 | const Edge& e = edge[ie]; 2658 | ie = e.pre_edge; 2659 | int to = e.to; 2660 | if (went[to]) 2661 | continue; 2662 | went[to] = true; 2663 | if (peer[to] == -1 || match(peer[to])) { 2664 | peer[to] = cur; 2665 | peer[cur] = to; 2666 | return true; 2667 | } 2668 | } 2669 | return false; 2670 | } 2671 | void show_peer() { 2672 | for (int i = 0; i < nv; i++) 2673 | printf("%d peer-> %d\n", i, peer[i]); 2674 | } 2675 | // end of 2676 | // bipartite match 2677 | // 2678 | }; 2679 | ``` 2680 | 2681 | ##### 5.4.1.2 Hopcroft–Karp Algorithm 2682 | 2683 | > O(sqrt(V)*E) 2684 | 2685 | ```c++ 2686 | #define MAXN 1010 2687 | #define MAXINT 0x7fffffff 2688 | 2689 | int n, m, top, x, y; 2690 | int ans; 2691 | 2692 | int disx[MAXN], disy[MAXN], matx[MAXN], maty[MAXN];//x,y,分别为二分图的两个点集,mat为每个点在对侧集合的匹配点,如果当前没有匹配点则为-1 2693 | 2694 | struct edge { 2695 | int to; 2696 | edge *next; 2697 | }e[MAXN*MAXN], *prev[MAXN]; 2698 | 2699 | void insert(int u,int v) { 2700 | e[++top].to = v; 2701 | e[top].next = prev[u]; 2702 | prev[u] = &e[top]; 2703 | } 2704 | 2705 | bool bfs() { // 寻找最短增广路 2706 | bool ret = 0; 2707 | queue q; 2708 | memset(disx, 0, sizeof(disx)); 2709 | memset(disy, 0, sizeof(disy)); 2710 | for (int i = 1; i <= n; i++) 2711 | if (matx[i] == -1) 2712 | q.push(i); // 找到未盖点,入队 2713 | while (!q.empty()) { // 在二分图另一个点集的非盖点中寻找增广路 2714 | int x = q.front(); q.pop(); 2715 | for (edge *i = prev[x]; i; i = i->next) 2716 | if (!disy[i->to]) { 2717 | disy[i->to] = disx[x] + 1; 2718 | if (maty[i->to]==-1) 2719 | ret = 1; // 找到增广路 2720 | else 2721 | disx[maty[i->to]] = disy[i->to] + 1, q.push(maty[i->to]); 2722 | } 2723 | } 2724 | return ret; 2725 | } 2726 | 2727 | bool dfs(int x) { // 沿增广路增广 2728 | for (edge *i = prev[x]; i; i = i->next) { 2729 | if (disy[i->to] == disx[x] + 1) { 2730 | disy[i->to] = 0; 2731 | if (maty[i->to] == -1 || dfs(maty[i->to])) { 2732 | matx[x] = i->to; 2733 | maty[i->to] = x; 2734 | return 1; 2735 | } 2736 | } 2737 | } 2738 | return 0; 2739 | } 2740 | 2741 | int main() { 2742 | scanf("%d%d",&n,&m); 2743 | memset(matx, -1, sizeof(matx)); 2744 | memset(maty, -1, sizeof(maty)); 2745 | /*for (int i=1;i<=n;i++) 2746 | { 2747 | scanf("%d%d",&x,&y);x++;y++; 2748 | insert(i,x);insert(i,y); 2749 | }建图请自动忽略*/ 2750 | while (bfs()) { 2751 | for (int i = 1; i <= m; i++) 2752 | if (matx[i] == -1 && dfs(i)) 2753 | ans++; 2754 | } 2755 | cout << ans << endl; 2756 | } 2757 | ``` 2758 | 2759 | #### 5.4.2 on General Graph 2760 | 2761 | ##### 5.4.2.1 Blossom Algorithm 2762 | 2763 | ```c++ 2764 | const int NMax = 230; 2765 | 2766 | int Next[NMax]; 2767 | int spouse[NMax]; 2768 | int belong[NMax]; 2769 | 2770 | int findb(int a) { 2771 | return belong[a] == a ? a : belong[a] = findb(belong[a]); 2772 | } 2773 | 2774 | void together(int a,int b) { 2775 | a = findb(a), b = findb(b); 2776 | if (a != b) 2777 | belong[a] = b; 2778 | } 2779 | 2780 | vector E[NMax]; 2781 | int N; 2782 | int Q[NMax],bot; 2783 | int mark[NMax]; 2784 | int visited[NMax]; 2785 | 2786 | int findLCA(int x,int y) { 2787 | static int t = 0; 2788 | t++; 2789 | while (1) { 2790 | if (x!=-1) { 2791 | x = findb(x); 2792 | if (visited[x] == t) 2793 | return x; 2794 | visited[x] = t; 2795 | if (spouse[x] != -1) 2796 | x = Next[spouse[x]]; 2797 | else x = -1; 2798 | } 2799 | swap(x,y); 2800 | } 2801 | } 2802 | 2803 | void goup(int a,int p) { 2804 | while (a != p) { 2805 | int b = spouse[a], c = Next[b]; 2806 | if (findb(c) != p) 2807 | Next[c] = b; 2808 | if (mark[b] == 2) 2809 | mark[Q[bot++] = b] = 1; 2810 | if (mark[c] == 2) 2811 | mark[Q[bot++] = c] = 1; 2812 | together(a,b); 2813 | together(b,c); 2814 | a = c; 2815 | } 2816 | } 2817 | 2818 | void findaugment(int s) { 2819 | for (int i = 0; i < N; i++) 2820 | Next[i] = -1, belong[i] = i, mark[i] = 0, visited[i] = -1; 2821 | Q[0] = s; 2822 | bot = 1; 2823 | mark[s] = 1; 2824 | for (int head = 0; spouse[s] == -1 && head < bot; head++) { 2825 | int x = Q[head]; 2826 | for (int i = 0; i < (int)E[x].size(); i++) { 2827 | int y = E[x][i]; 2828 | if (spouse[x] != y && findb(x) != findb(y) && mark[y] != 2) { 2829 | if (mark[y] == 1) { 2830 | int p = findLCA(x,y); 2831 | if (findb(x) != p) 2832 | Next[x] = y; 2833 | if (findb(y) != p) 2834 | Next[y] = x; 2835 | goup(x,p); 2836 | goup(y,p); 2837 | } 2838 | else if (spouse[y] == -1) { 2839 | Next[y] = x; 2840 | for (int j = y; j != -1; ) { 2841 | int k = Next[j]; 2842 | int l = spouse[k]; 2843 | spouse[j] = k; 2844 | spouse[k] = j; 2845 | j = l; 2846 | } 2847 | break; 2848 | } 2849 | else{ 2850 | Next[y] = x; 2851 | mark[Q[bot++] = spouse[y]] = 1; 2852 | mark[y] = 2; 2853 | } 2854 | } 2855 | } 2856 | } 2857 | } 2858 | 2859 | int Map[NMax][NMax]; 2860 | 2861 | int main() { 2862 | memset(Map, 0, sizeof(Map)); 2863 | 2864 | scanf("%d",&N); 2865 | int x, y; 2866 | while (scanf("%d%d",&x,&y) != EOF) { 2867 | x--; 2868 | y--; 2869 | if (x != y && !Map[x][y]) { 2870 | Map[x][y] = Map[y][x] = 1; 2871 | E[x].push_back(y); 2872 | E[y].push_back(x); 2873 | } 2874 | } 2875 | memset(spouse, -1, sizeof(spouse)); 2876 | for (int i = 0; i < N; i++) 2877 | if (spouse[i] == -1) 2878 | findaugment(i); 2879 | int ret = 0; 2880 | for (int i = 0; i < N; i++) 2881 | if (spouse[i] != -1) 2882 | ret++; 2883 | printf("%d\n", ret); 2884 | for (int i = 0; i < N; i++) 2885 | if (spouse[i] != -1 && spouse[i] > i) 2886 | printf("pair: %d %d\n", i + 1, spouse[i] + 1); 2887 | } 2888 | ``` 2889 | 2890 | ### 5.5 Maximum Flow Problem 最大流 2891 | 2892 | #### 5.5.1 Dinic 2893 | ```c++ 2894 | // a convenient class 2895 | 2896 | struct Network { 2897 | struct Edge { 2898 | int to; 2899 | int pre_edge; 2900 | int cap; 2901 | int flow; 2902 | }; 2903 | 2904 | #define MAXNODE 405 2905 | int last[MAXNODE]; 2906 | 2907 | int nv; // total number of vertex, index range: [0, nv) 2908 | vector edge; 2909 | void init(int _nv) { 2910 | nv = _nv; 2911 | edge.clear(); 2912 | fill(last, last + nv, -1); 2913 | } 2914 | 2915 | void add_e(int x, int y, int cap, int r_cap = 0) { 2916 | Edge e = {y, last[x], cap, 0}; 2917 | // Edge e{y, last[x], cap, 0}; 2918 | last[x] = edge.size(); 2919 | // edge.push_back(move(e)); 2920 | edge.push_back(e); 2921 | 2922 | Edge r_e = {x, last[y], r_cap, 0}; 2923 | // Edge r_e{x, last[y], r_cap, 0}; 2924 | last[y] = edge.size(); 2925 | // edge.push_back(move(r_e)); 2926 | edge.push_back(r_e); 2927 | } 2928 | void show_edge() { 2929 | for (int i = 0; i < nv; i++) { 2930 | printf("v [%d]:", i); 2931 | for (int ie = last[i]; ie != -1; ) { 2932 | const Edge& e = edge[ie]; 2933 | ie = e.pre_edge; 2934 | printf(" [%d]%d/%d", e.to, e.flow, e.cap); 2935 | } 2936 | printf("\n"); 2937 | } 2938 | printf("\n"); 2939 | } 2940 | 2941 | // 2942 | // maximum flow 2943 | // dinic O(V * V * E) 2944 | int lv[MAXNODE]; 2945 | bool mark_level(int start, int end) { 2946 | fill(lv, lv + MAXNODE, -1); 2947 | queue q; 2948 | lv[start] = 0; 2949 | q.push(start); 2950 | while (!q.empty()) { 2951 | int cur = q.front(); q.pop(); 2952 | for (int ie = last[cur]; ie != -1; ) { 2953 | const Edge& e = edge[ie]; 2954 | ie = e.pre_edge; 2955 | if (e.cap != e.flow && lv[e.to] == -1) { 2956 | lv[e.to] = lv[cur] + 1; 2957 | q.push(e.to); 2958 | } 2959 | } 2960 | } 2961 | return lv[end] != -1; 2962 | } 2963 | void show_lv() { 2964 | for (int i = 0; i < nv; i++) { 2965 | printf("lv[%d] = %d\n", i, lv[i]); 2966 | } 2967 | } 2968 | int augment(int cur, int end, int min_flow) { 2969 | if (cur == end) 2970 | return min_flow; 2971 | 2972 | int augmented_flow = 0; 2973 | for (int ie = last[cur]; ie != -1; ) { 2974 | Edge& e = edge[ie]; 2975 | Edge& re = edge[ie ^ 1]; 2976 | ie = e.pre_edge; 2977 | if (lv[e.to] == lv[cur] + 1 && 2978 | e.cap > e.flow && 2979 | (augmented_flow = augment(e.to, end, min(e.cap - e.flow, min_flow))) 2980 | ) { 2981 | e.flow += augmented_flow; 2982 | re.flow -= augmented_flow; 2983 | return augmented_flow; 2984 | } 2985 | } 2986 | return 0; 2987 | } 2988 | int dinic(int start, int end) { 2989 | int total_flow = 0; 2990 | int flow = 0; 2991 | while (mark_level(start, end)) // update level 2992 | while (flow = augment(start, end, INT_MAX)) // eat up all augmented flow 2993 | total_flow += flow; 2994 | return total_flow; 2995 | } 2996 | // end of 2997 | // maximum flow - dinic 2998 | // 2999 | }; 3000 | ``` 3001 | 3002 | #### 5.5.2 Improved SAP + Gap Optimization 3003 | 3004 | ```c++ 3005 | struct Network { 3006 | struct Edge { 3007 | int to; 3008 | int pre_edge; 3009 | int cap; 3010 | int flow; 3011 | }; 3012 | 3013 | #define MAXNODE 405 3014 | int last[MAXNODE]; 3015 | 3016 | int nv; // total number of vertex, index range: [0, nv) 3017 | vector edge; 3018 | void init(int _nv) { 3019 | nv = _nv; 3020 | edge.clear(); 3021 | fill(last, last + nv, -1); 3022 | } 3023 | 3024 | void add_e(int x, int y, int cap, int r_cap = 0) { 3025 | Edge e = {y, last[x], cap, 0}; 3026 | // Edge e{y, last[x], cap, 0}; 3027 | last[x] = edge.size(); 3028 | // edge.push_back(move(e)); 3029 | edge.push_back(e); 3030 | 3031 | Edge r_e = {x, last[y], r_cap, 0}; 3032 | // Edge r_e{x, last[y], r_cap, 0}; 3033 | last[y] = edge.size(); 3034 | // edge.push_back(move(r_e)); 3035 | edge.push_back(r_e); 3036 | } 3037 | void show_edge() { 3038 | for (int i = 0; i < nv; i++) { 3039 | printf("v [%d]:", i); 3040 | for (int ie = last[i]; ie != -1; ) { 3041 | const Edge& e = edge[ie]; 3042 | ie = e.pre_edge; 3043 | printf(" [%d]%d/%d", e.to, e.flow, e.cap); 3044 | } 3045 | printf("\n"); 3046 | } 3047 | printf("\n"); 3048 | } 3049 | 3050 | // 3051 | // maximum flow 3052 | // isap + gap O(V * V * E) 3053 | // a bit faster than dinic 3054 | int lv[MAXNODE]; 3055 | int lv_count[MAXNODE]; 3056 | int from_edge[MAXNODE]; 3057 | void mark_r_level(int end) { 3058 | fill(lv, lv + nv, nv); 3059 | fill(lv_count, lv_count + nv, 0); 3060 | queue q; 3061 | 3062 | lv[end] = 0; 3063 | lv_count[lv[end]]++; 3064 | q.push(end); 3065 | while (!q.empty()) { 3066 | int cur = q.front(); q.pop(); 3067 | for (int ie = last[cur]; ie != -1; ) { 3068 | const Edge& e = edge[ie]; 3069 | ie = e.pre_edge; 3070 | int to = e.to; 3071 | if (lv[to] != nv) 3072 | continue; 3073 | 3074 | lv[to] = lv[cur] + 1; 3075 | lv_count[lv[to]]++; 3076 | q.push(to); 3077 | } 3078 | } 3079 | } 3080 | int isap_gap(int start, int end) { 3081 | mark_r_level(end); // reverse bfs to get level of node 3082 | 3083 | int total_flow = 0; 3084 | int cur = start; 3085 | from_edge[start] = -1; 3086 | while (lv[start] < nv) { 3087 | if (cur == end) { 3088 | int flow = INT_MAX; 3089 | for (int x = cur; x != start; ) { // backtrack to get min cap along the path 3090 | int ie = from_edge[x]; 3091 | const Edge& e = edge[ie]; 3092 | flow = min(flow, e.cap - e.flow); 3093 | x = edge[ie ^ 1].to; 3094 | } 3095 | 3096 | for ( ; cur != start; ) { // update the cap along the path 3097 | int ie = from_edge[cur]; 3098 | Edge& e = edge[ie]; 3099 | Edge& re = edge[ie ^ 1]; 3100 | e.flow += flow; 3101 | re.flow -= flow; 3102 | cur = re.to; 3103 | } 3104 | total_flow += flow; 3105 | } 3106 | 3107 | bool found = false; 3108 | for (int ie = last[cur]; ie != -1; ) { // find the next vertex 3109 | const Edge& e = edge[ie]; 3110 | if (e.cap != e.flow && lv[cur] == lv[e.to] + 1) { 3111 | cur = e.to; 3112 | from_edge[cur] = ie; // record the edge from which we comes 3113 | found = true; 3114 | break; 3115 | } 3116 | ie = e.pre_edge; 3117 | } 3118 | 3119 | if (found) 3120 | continue; 3121 | 3122 | lv_count[lv[cur]]--; 3123 | if (lv_count[lv[cur]] == 0) 3124 | break; 3125 | int min_lv = nv; 3126 | for (int ie = last[cur]; ie != -1; ) { // find the min level around cur vertex 3127 | const Edge& e = edge[ie]; 3128 | ie = e.pre_edge; 3129 | 3130 | if (e.cap != e.flow) 3131 | min_lv = min(min_lv, lv[e.to]); 3132 | } 3133 | 3134 | lv[cur] = min_lv + 1; // raise level of cur vertex by 1 3135 | lv_count[lv[cur]]++; 3136 | if (cur != start) 3137 | cur = edge[from_edge[cur] ^ 1].to; // revert one step 3138 | } 3139 | return total_flow; 3140 | } 3141 | // end of 3142 | // maximum flow - isap + gap 3143 | // 3144 | }; 3145 | ``` 3146 | 3147 | #### 5.5.3 Minimum-Cost Maximum-Flow 3148 | 3149 | ```C++ 3150 | // have not tested 3151 | int n_node; 3152 | int n_edge; 3153 | 3154 | int cost[405][405]; // cost[i][j] = -cost[j][i] 3155 | int residual[405][405]; 3156 | 3157 | bool bellman_ford(int& flow_sum, int&cost_sum) { // 0: start, n_node - 1: end 3158 | int min_cost[405]; for (int i = 0; i < n_node; i++) min_cost[i] = INT_MAX; min_cost[0] = 0; 3159 | int pre_node[405]; pre_node[0] = 0; 3160 | int max_flow[405]; 3161 | int in_queue[405]; memset(in_queue, 0, sizeof(in_queue)); 3162 | 3163 | queue q; 3164 | q.push(0); 3165 | while (q.size()) { 3166 | int cur = q.front(); q.pop(); 3167 | in_queue[cur] = 0; 3168 | 3169 | for (int i = 0; i < n_node; i++) { 3170 | if (residual[cur][i] > 0 && min_cost[i] > min_cost[cur] + cost[cur][i]) { 3171 | min_cost[i] = min_cost[cur] + cost[cur][i]; 3172 | pre_node[i] = cur; 3173 | max_flow[i] = min(max_flow[cur], residual[cur][i]); 3174 | 3175 | if (in_queue[i] == 0) { 3176 | in_queue[i] = 1; 3177 | q.push(i); 3178 | } 3179 | } 3180 | } 3181 | } 3182 | if (min_cost[n_node - 1] == INT_MAX) 3183 | return false; 3184 | flow_sum += max_flow[n_node - 1]; 3185 | cost_sum += max_flow[n_node - 1] * min_cost[n_node - 1]; 3186 | for (int cur = n_node - 1; cur != 0; cur = pre_node[cur]) { 3187 | residual[pre_node[cur]][cur] -= max_flow[n_node - 1]; 3188 | residual[cur][pre_node[cur]] += max_flow[n_node - 1]; 3189 | } 3190 | return true; 3191 | } 3192 | 3193 | void min_cost_max_flow() { 3194 | int flow_sum = 0; 3195 | int cost_sum = 0; 3196 | while (bellman_ford(flow_sum, cost_sum)); 3197 | cout << flow_sum << " " << cost_sum << endl; 3198 | } 3199 | ``` 3200 | 3201 | 3202 | ### 5.6 强连通分量 图的 割点, 桥, 双连通分支 3203 | 3204 | ``https://www.byvoid.com/blog/biconnect`` 3205 | 3206 | > [点连通度与边连通度] 3207 | > 3208 | > 在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合。一个图的点连通度的定义为,最小割点集合中的顶点数。 3209 | > 3210 | > 类似的,如果有一个边集合,删除这个边集合以后,原图变成多个连通块,就称这个点集为割边集合。一个图的边连通度的定义为,最小割边集合中的边数。 3211 | > 3212 | > [双连通图、割点与桥] 3213 | > 3214 | > 如果一个无向连通图的点连通度大于1,则称该图是点双连通的(point biconnected),简称双连通或重连通。一个图有割点,当且仅当这个图的点连通度为1,则割点集合的唯一元素被称为割点(cut point),又叫关节点(articulation point)。 3215 | > 3216 | > 如果一个无向连通图的边连通度大于1,则称该图是边双连通的(edge biconnected),简称双连通或重连通。一个图有桥,当且仅当这个图的边连通度为1,则割边集合的唯一元素被称为桥(bridge),又叫关节边(articulation edge)。 3217 | > 3218 | > 可以看出,点双连通与边双连通都可以简称为双连通,它们之间是有着某种联系的,下文中提到的双连通,均既可指点双连通,又可指边双连通。 3219 | > 3220 | > [双连通分支] 3221 | > 3222 | > 在图G的所有子图G'中,如果G'是双连通的,则称G'为双连通子图。如果一个双连通子图G'它不是任何一个双连通子图的真子集,则G'为极大双连通子图。双连通分支(biconnected component),或重连通分支,就是图的极大双连通子图。特殊的,点双连通分支又叫做块。 3223 | > 3224 | > [求割点与桥] 3225 | > 3226 | > 该算法是R.Tarjan发明的。对图深度优先搜索,定义DFS(u)为u在搜索树(以下简称为树)中被遍历到的次序号。定义Low(u)为u或u的子树中能通过非父子边追溯到的最早的节点,即DFS序号最小的节点。根据定义,则有: 3227 | > 3228 | > Low(u)=Min { DFS(u) DFS(v) (u,v)为后向边(返祖边) 等价于 DFS(v) 3230 | > 一个顶点u是割点,当且仅当满足(1)或(2) (1) u为树根,且u有多于一个子树。 (2) u不为树根,且满足存在(u,v)为树枝边(或称父子边,即u为v在搜索树中的父亲),使得DFS(u)<=Low(v)。 3231 | > 3232 | > 一条无向边(u,v)是桥,当且仅当(u,v)为树枝边,且满足DFS(u) 3234 | > [求双连通分支] 3235 | > 3236 | > 下面要分开讨论点双连通分支与边双连通分支的求法。 3237 | > 3238 | > 对于点双连通分支,实际上在求割点的过程中就能顺便把每个点双连通分支求出。建立一个栈,存储当前双连通分支,在搜索图时,每找到一条树枝边或后向边(非横叉边),就把这条边加入栈中。如果遇到某时满足DFS(u)<=Low(v),说明u是一个割点,同时把边从栈顶一个个取出,直到遇到了边(u,v),取出的这些边与其关联的点,组成一个点双连通分支。割点可以属于多个点双连通分支,其余点和每条边只属于且属于一个点双连通分支。 3239 | > 3240 | > 对于边双连通分支,求法更为简单。只需在求出所有的桥以后,把桥边删除,原图变成了多个连通块,则每个连通块就是一个边双连通分支。桥不属于任何一个边双连通分支,其余的边和每个顶点都属于且只属于一个边双连通分支。 3241 | > 3242 | > [构造双连通图] 3243 | > 3244 | > 一个有桥的连通图,如何把它通过加边变成边双连通图?方法为首先求出所有的桥,然后删除这些桥边,剩下的每个连通块都是一个双连通子图。把每个双连通子图收缩为一个顶点,再把桥边加回来,最后的这个图一定是一棵树,边连通度为1。 3245 | > 3246 | > 统计出树中度为1的节点的个数,即为叶节点的个数,记为leaf。则至少在树上添加(leaf+1)/2条边,就能使树达到边二连通,所以至少添加的边数就是(leaf+1)/2。具体方法为,首先把两个最近公共祖先最远的两个叶节点之间连接一条边,这样可以把这两个点到祖先的路径上所有点收缩到一起,因为一个形成的环一定是双连通的。然后再找两个最近公共祖先最远的两个叶节点,这样一对一对找完,恰好是(leaf+1)/2次,把所有点收缩到了一起。 3247 | 3248 | find articulation point (cut vertex) / bridge (cutedge) in directed / undirected graph 3249 | 3250 | find and merge biconnected component in undirected graph 3251 | 3252 | find and merge strongly connected component in directed graph 3253 | 3254 | 3255 | > time complexity `O(E+V)` 3256 | 3257 | ``` c++ 3258 | #define NN 20002 3259 | #define MM 100002 3260 | 3261 | int n; 3262 | int m; 3263 | 3264 | int visit_order[NN]; 3265 | int smallest_order_can_reach[NN]; 3266 | int parent[NN]; 3267 | int in_stack[NN]; 3268 | int temp_component[NN]; 3269 | 3270 | vector g[NN]; 3271 | 3272 | void merge(const vector& component) { 3273 | vector out_vertex; 3274 | int new_vertex = component.back(); 3275 | for (int v : component) 3276 | temp_component[v] = 1; 3277 | for (int v : component) { 3278 | for (int o : g[v]) { 3279 | if (!temp_component[o]) 3280 | out_vertex.push_back(o); 3281 | } 3282 | g[v].clear(); 3283 | g[v].push_back(new_vertex); 3284 | } 3285 | for (int v : component) 3286 | temp_component[v] = 0; 3287 | 3288 | // use last vertex in the component as new vertex 3289 | g[new_vertex] = out_vertex; 3290 | } 3291 | 3292 | void dfs(int cur) { 3293 | static int order = 0; 3294 | static stack s; 3295 | 3296 | visit_order[cur] = smallest_order_can_reach[cur] = ++order; 3297 | s.push(cur); 3298 | in_stack[cur] = 1; 3299 | 3300 | int subtree = 0; 3301 | for (int next : g[cur]) { 3302 | if (visit_order[next] == 0) { 3303 | subtree++; 3304 | parent[next] = cur; 3305 | dfs(next); 3306 | smallest_order_can_reach[cur] = min(smallest_order_can_reach[cur], smallest_order_can_reach[next]); 3307 | 3308 | // if cur is root, and subtree > 1 3309 | // it is an articulation point 3310 | if (visit_order[cur] == 1 && subtree > 1) 3311 | ; 3312 | 3313 | // if cur is not root, and next cannot reach smaller vertex 3314 | // it is an articulation point 3315 | if (visit_order[cur] != 1 && visit_order[cur] <= smallest_order_can_reach[next]) 3316 | ; 3317 | 3318 | // if cannot use this edge to reach a smaller vertex 3319 | // it is a bridge 3320 | if (visit_order[cur] < smallest_order_can_reach[next]) 3321 | ; 3322 | } 3323 | 3324 | // for undirected graph 3325 | // update the smallness of vertex that can reach 3326 | // else if (next != parent[cur]) 3327 | // smallest_order_can_reach[cur] = min(smallest_order_can_reach[cur], visit_order[next]); 3328 | 3329 | // for directed graph 3330 | else if (in_stack[next]) 3331 | smallest_order_can_reach[cur] = min(smallest_order_can_reach[cur], visit_order[next]); 3332 | } 3333 | 3334 | if (visit_order[cur] == smallest_order_can_reach[cur]) { 3335 | // because visit_order[cur] == smallest_order_can_reach[cur] 3336 | // and visit_order[cur] > visit_order[parent[cur]] 3337 | // so visit_order[parent[cur]] < smallest_order_can_reach[cur] 3338 | // so cur-parent[cur] is a bridge 3339 | // cur is root of the biconnected component 3340 | // so pop all util cur 3341 | 3342 | vector component; 3343 | int min_vertex = s.top(); 3344 | while (1) { 3345 | int vertex = s.top(); s.pop(); 3346 | in_stack[vertex] = 0; 3347 | min_vertex = min(min_vertex, vertex); 3348 | component.push_back(vertex); 3349 | if (vertex == cur) 3350 | break; 3351 | } 3352 | // cur is the last vertex in the component 3353 | merge(component); 3354 | } 3355 | } 3356 | 3357 | int main() { 3358 | cin >> n >> m; 3359 | for (int i = 0; i < m; i++) { 3360 | int a, b; 3361 | cin >> a >> b; 3362 | g[a].push_back(b); 3363 | } 3364 | 3365 | dfs(1); 3366 | } 3367 | ``` 3368 | 3369 | ### 5.7 Topological Sort / 拓扑排序 3370 | 3371 | > Topological Sorting on Directed Acyclic Graph (DAG) 3372 | > 3373 | > time complexity `O(N)` 3374 | 3375 | ```c++ 3376 | struct Graph { 3377 | struct Edge { 3378 | int to; 3379 | }; 3380 | 3381 | const static int MAXNODE = 3 * 1e5 + 2; 3382 | vector g[MAXNODE]; 3383 | vector edge; 3384 | int n; 3385 | void init(int nn) { 3386 | n = nn; 3387 | for (int i = 0; i <= n; i++) 3388 | g[i].clear(); 3389 | edge.clear(); 3390 | } 3391 | 3392 | void add_e(int x, int y) { 3393 | Edge e = {y}; 3394 | g[x].push_back(edge.size()); 3395 | edge.push_back(e); 3396 | } 3397 | 3398 | void show() { 3399 | for (int i = 0; i <= n; i++) { 3400 | printf("%d:", i); 3401 | for (int ie : g[i]) 3402 | printf(" %d", edge[ie].to); 3403 | printf("\n"); 3404 | } 3405 | printf("\n"); 3406 | } 3407 | 3408 | // 3409 | // Node index ~ [0, N) 3410 | // matters for topological sort 3411 | // 3412 | int in_order[MAXNODE]; 3413 | void init_in_order() { 3414 | fill_n(in_order, n + 1, 0); 3415 | for (int i = 0; i < n; i++) 3416 | for (int ie : g[i]) 3417 | in_order[edge[ie].to]++; 3418 | } 3419 | bool topological_sort(vector& result) { 3420 | init_in_order(); 3421 | queue q; 3422 | for (int i = 0; i < n; i++) 3423 | if (in_order[i] == 0) 3424 | q.push(i); 3425 | while (q.size()) { 3426 | int cur = q.front(); q.pop(); 3427 | result.push_back(cur); 3428 | for (int ie : g[cur]) { 3429 | const Edge& e = edge[ie]; 3430 | in_order[e.to]--; 3431 | if (in_order[e.to] == 0) 3432 | q.push(e.to); 3433 | } 3434 | } 3435 | return result.size() == n; 3436 | } 3437 | void show_order() { 3438 | for (int i = 0; i < n; i++) 3439 | printf("in_order[%d] = %d\n", i, in_order[i]); 3440 | } 3441 | }; 3442 | ``` 3443 | 3444 | ### 5.8 Euler Cycle/Path, Hamilton Cycle/Path 3445 | 3446 | > place holder 3447 | 3448 | ### 5.9 find negative (weight) Cycle on a graph 3449 | 3450 | > place holder 3451 | 3452 | 3453 | ## 6. Number + Mathematics 3454 | 3455 | ### 6.1 BigInteger + BigDecimal 3456 | 3457 | #### 6.1.1 C++ Big Integer 3458 | 3459 | ```c++ 3460 | const int BASE_LENGTH = 2; 3461 | const int BASE = (int) pow(10, BASE_LENGTH); 3462 | const int MAX_LENGTH = 500; 3463 | 3464 | string int_to_string(int i, int width, bool zero) { 3465 | string res = ""; 3466 | while (width--) { 3467 | if (!zero && i == 0) return res; 3468 | res = (char)(i%10 + '0') + res; 3469 | i /= 10; 3470 | } 3471 | return res; 3472 | } 3473 | 3474 | struct bigint { 3475 | int len, s[MAX_LENGTH]; 3476 | 3477 | bigint() { 3478 | memset(s, 0, sizeof(s)); 3479 | len = 1; 3480 | } 3481 | 3482 | bigint(unsigned long long num) { 3483 | len = 0; 3484 | while (num >= BASE) { 3485 | s[len] = num % BASE; 3486 | num /= BASE; 3487 | len ++; 3488 | } 3489 | s[len++] = num; 3490 | } 3491 | 3492 | bigint(const char* num) { 3493 | int l = strlen(num); 3494 | len = l/BASE_LENGTH; 3495 | if (l % BASE_LENGTH) len++; 3496 | int index = 0; 3497 | for (int i = l - 1; i >= 0; i -= BASE_LENGTH) { 3498 | int tmp = 0; 3499 | int k = i - BASE_LENGTH + 1; 3500 | if (k < 0) k = 0; 3501 | for (int j = k; j <= i; j++) { 3502 | tmp = tmp*10 + num[j] - '0'; 3503 | } 3504 | s[index++] = tmp; 3505 | } 3506 | } 3507 | 3508 | void clean() { 3509 | while(len > 1 && !s[len-1]) len--; 3510 | } 3511 | 3512 | string str() const { 3513 | string ret = ""; 3514 | if (len == 1 && !s[0]) return "0"; 3515 | for(int i = 0; i < len; i++) { 3516 | if (i == 0) { 3517 | ret += int_to_string(s[len - i - 1], BASE_LENGTH, false); 3518 | } else { 3519 | ret += int_to_string(s[len - i - 1], BASE_LENGTH, true); 3520 | } 3521 | } 3522 | return ret; 3523 | } 3524 | 3525 | unsigned long long ll() const { 3526 | unsigned long long ret = 0; 3527 | for(int i = len-1; i >= 0; i--) { 3528 | ret *= BASE; 3529 | ret += s[i]; 3530 | } 3531 | return ret; 3532 | } 3533 | 3534 | bigint operator + (const bigint& b) const { 3535 | bigint c = b; 3536 | while (c.len < len) c.s[c.len++] = 0; 3537 | c.s[c.len++] = 0; 3538 | bool r = 0; 3539 | for (int i = 0; i < len || r; i++) { 3540 | c.s[i] += (i= BASE; 3542 | if (r) c.s[i] -= BASE; 3543 | } 3544 | c.clean(); 3545 | return c; 3546 | } 3547 | 3548 | bigint operator - (const bigint& b) const { 3549 | if (operator < (b)) throw "cannot do subtract"; 3550 | bigint c = *this; 3551 | bool r = 0; 3552 | for (int i = 0; i < b.len || r; i++) { 3553 | c.s[i] -= b.s[i]; 3554 | r = c.s[i] < 0; 3555 | if (r) c.s[i] += BASE; 3556 | } 3557 | c.clean(); 3558 | return c; 3559 | } 3560 | 3561 | bigint operator * (const bigint& b) const { 3562 | bigint c; 3563 | c.len = len + b.len; 3564 | for(int i = 0; i < len; i++) 3565 | for(int j = 0; j < b.len; j++) 3566 | c.s[i+j] += s[i] * b.s[j]; 3567 | for(int i = 0; i < c.len-1; i++){ 3568 | c.s[i+1] += c.s[i] / BASE; 3569 | c.s[i] %= BASE; 3570 | } 3571 | c.clean(); 3572 | return c; 3573 | } 3574 | 3575 | bigint operator / (const int b) const { 3576 | bigint ret; 3577 | int down = 0; 3578 | for (int i = len - 1; i >= 0; i--) { 3579 | ret.s[i] = (s[i] + down * BASE) / b; 3580 | down = s[i] + down * BASE - ret.s[i] * b; 3581 | } 3582 | ret.len = len; 3583 | ret.clean(); 3584 | return ret; 3585 | } 3586 | 3587 | bool operator < (const bigint& b) const { 3588 | if (len < b.len) return true; 3589 | else if (len > b.len) return false; 3590 | for (int i = 0; i < len; i++) 3591 | if (s[i] < b.s[i]) return true; 3592 | else if (s[i] > b.s[i]) return false; 3593 | return false; 3594 | } 3595 | 3596 | bool operator == (const bigint& b) const { 3597 | return !(*this (const bigint& b) const { 3601 | return b < *this; 3602 | } 3603 | }; 3604 | ``` 3605 | 3606 | Examples 3607 | 3608 | ```c++ 3609 | ASSERT((a+b).str()=="10001") 3610 | ASSERT((a+b)==bigint(10001)) 3611 | ASSERT((b/2)==4999) 3612 | ASSERT(c == 12345) 3613 | ASSERT(c < 123456) 3614 | ASSERT(c > 123) 3615 | ASSERT(!(c > 123456)) 3616 | ASSERT(!(c < 123)) 3617 | ASSERT(!(c == 12346)) 3618 | ASSERT(!(c == 12344)) 3619 | ASSERT(c.str() == "12345") 3620 | ASSERT((b-1)==9998) 3621 | ASSERT(a.ll() == 2) 3622 | ASSERT(b.ll() == 9999) 3623 | ``` 3624 | 3625 | 3626 | #### 6.1.2 The Java Approach 3627 | 3628 | BigInteger & BigDecimal 3629 | 3630 | ### 6.2 Matrix 3631 | 3632 | ```C++ 3633 | operator+ 3634 | operator* 3635 | ``` 3636 | 3637 | > Square matrix 3638 | 3639 | ```C++ 3640 | 3641 | struct Matrix { 3642 | // int height; 3643 | // int width; 3644 | 3645 | long long value[32][32]; 3646 | 3647 | Matrix operator* (const Matrix& that); 3648 | Matrix operator+ (const Matrix& that); 3649 | Matrix mirror(); 3650 | void show() { 3651 | cout << endl; 3652 | for (int i = 0; i < n; i++) { 3653 | for (int j = 0; j < n; j++) 3654 | cout << this->value[i][j] << " "; 3655 | cout << endl; 3656 | } 3657 | } 3658 | }; 3659 | 3660 | void mod_it(Matrix& temp) { 3661 | for (int i = 0; i < n; i++) 3662 | for (int j = 0; j < n; j++) 3663 | temp.value[i][j] %= m; 3664 | } 3665 | 3666 | Matrix Matrix::operator* (const Matrix& that) { 3667 | Matrix temp; 3668 | for (int i = 0; i < n; i++) { 3669 | for (int j = 0; j < n; j++) { 3670 | temp.value[i][j] = 0; 3671 | for (int k = 0; k < n; k++) 3672 | temp.value[i][j] += this->value[i][k] * that.value[k][j]; 3673 | } 3674 | } 3675 | mod_it(temp); 3676 | return temp; 3677 | } 3678 | 3679 | Matrix Matrix::operator+ (const Matrix& that) { 3680 | Matrix temp; 3681 | for (int i = 0; i < n; i++) 3682 | for (int j = 0; j < n; j++) 3683 | temp.value[i][j] = this->value[i][j] + that.value[i][j]; 3684 | mod_it(temp); 3685 | return temp; 3686 | } 3687 | 3688 | Matrix Matrix::mirror() { 3689 | Matrix temp; 3690 | for (int i = 0; i < n; i++) 3691 | for (int j = 0; j < n; j++) 3692 | temp.value[i][j] = this->value[i][j]; 3693 | return temp; 3694 | } 3695 | ``` 3696 | 3697 | ### 6.3 Number Theory 3698 | 3699 | #### 6.3.1 欧拉函数 ? 3700 | 3701 | #### 6.3.2 欧几里得算法 / gcd 3702 | 3703 | ```c++ 3704 | int gcd(int a, int b) { 3705 | return b == 0 ? a : gcd(b, a % b); 3706 | } 3707 | 3708 | int lcm(int a, int b) { 3709 | return a / gcd(a, b) * b; 3710 | } 3711 | ``` 3712 | 3713 | #### 6.3.3 扩展欧几里得算法 3714 | 3715 | ``http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html`` 3716 | 3717 | > 对于不完全为 0 的非负整数 a, b, 必然存在整数对 (x, y), 使得 gcd(a, b) = ax + by 3718 | 3719 | > suppose: a > b, we want to get (x1, y1) 3720 | 3721 | > (i) if b == 0, then gcd(a, b) = a = ax + 0, then x1 = 1, y1 = 0 3722 | 3723 | > (ii) if b != 0: 3724 | 3725 | > (1): a * x1 + b * y1 = gcd(a, b) 3726 | 3727 | > (2): b * x2 + (a % b) * y2 = gcd(b, a % b) 3728 | 3729 | > (1) == (2) 3730 | 3731 | > so: a * x1 + b * y1 = b * x2 + (a % b) * y2 3732 | 3733 | > so: a * x1 + b * y1 = b * x2 + (a - (int)(a / b) * b) * y2 3734 | 3735 | > so: a * x1 + b * y1 = a * y2 + b * (x2 - (int)(a / b) * y2) 3736 | 3737 | > so: x1 = y2, y1 = x2 - (int)(a / b) * y2, can get (x1, y1) from (x2, y2) 3738 | 3739 | > next: 3740 | 3741 | > (1): b * x2 + (a % b) * y2 = gcd(b, a % b) 3742 | 3743 | > (2): (a % b) * x3 + b % (a % b) * y3 = gcd(a % b, b % (a % b)) 3744 | 3745 | > so: can get (x2, y2) from (x3, y3) 3746 | 3747 | > next: ... until in gcd(a, b), b == 0, then xi = 1, yi = 0, go back ... 3748 | 3749 | ```C++ 3750 | long long ansx, ansy, ansd; 3751 | 3752 | void euclidean(long long a, long long b) { 3753 | if (b == 0) { 3754 | ansx = 1; 3755 | ansy = 0; 3756 | ansd = a; 3757 | } else { 3758 | euclidean(b, a % b); 3759 | long long temp = ansx; 3760 | ansx = ansy; 3761 | ansy = temp - a / b * ansy; 3762 | } 3763 | } 3764 | 3765 | int main(int argc, char const *argv[]) { 3766 | long long a, b, c; 3767 | cin >> a >> b >> c; 3768 | 3769 | ansx = 0; 3770 | ansy = 0; 3771 | ansd = 0; 3772 | euclidean(a, b); 3773 | 3774 | // now (ansx, ansy) is the answer (x, y) for a * x1 + b * y1 = gcd(a, b) 3775 | // ansd is the a when b == 0, which is just gcd(a, b) 3776 | } 3777 | ``` 3778 | 3779 | #### 6.3.4 求解不定方程 3780 | 3781 | > for: p * a + q * b = c 3782 | 3783 | > if c % gcd(a, b) == 0, then 有整数解 (p, q), else NO 3784 | 3785 | 3786 | > if we get (p0, q0) for p0 * a + q0 * b = gcd(a, b) 3787 | 3788 | > then: for p * a + q * b = gcd(a, b) (k is any integer) 3789 | 3790 | > p = p0 + b / gcd(a, b) * k 3791 | 3792 | > q = q0 - a / gcd(a, b) * k 3793 | 3794 | 3795 | > then: for p * a + q * b = c = c / gcd(a, b) * gcd(a, b) (k is any integer) 3796 | 3797 | > p = (p0 + b / gcd(a, b) * k) * c / gcd(a, b) 3798 | 3799 | > q = (q0 - a / gcd(a, b) * k) * c / gcd(a, b) 3800 | 3801 | ```C++ 3802 | // after get ansx, ansy, ansd 3803 | // test if c % ansd == 0 3804 | // ansx = (ansx + b / gcd(a, b) * k) * c / gcd(a, b) 3805 | // ansy = (ansy - a / gcd(a, b) * k) * c / gcd(a, b) 3806 | // smallest: ansx % (b / gcd(a, b) + b / gcd(a, b)) % (b / gcd(a, b)) 3807 | ``` 3808 | 3809 | #### 6.3.5 求解模线性方程(线性同余方程) 3810 | 3811 | > (a * x) % n = b % n, x = ? 3812 | 3813 | > same as: a * x + n * y= b 3814 | 3815 | > so: one answer for a * x + n * y= b is: x * b / gcd(a, n) 3816 | 3817 | > so: one answer for (a * x) % n = b % n is: x0 = (x * b / gcd(a, n)) % n 3818 | 3819 | > other answer xi = (x0 + i * (n / gcd(a, n))) % n, i = 0...gcd(a, n)-1 3820 | 3821 | > smallest answer is x0 % (n / gcd(a, n) + gcd(a, n)) % gcd(a, n) 3822 | 3823 | 3824 | 3825 | #### 6.3.6 求解模的逆元 3826 | 3827 | > (a * x) % n = 1, x = ? 3828 | 3829 | > if gcd(a, n) != 1, then NO answer 3830 | 3831 | > else: 3832 | 3833 | > same as: a * x + n * y = 1 3834 | 3835 | > can get only one answer x 3836 | 3837 | ```C++ 3838 | // after get ansx, ansy, ansd 3839 | // if ansd != 1, then NO answer 3840 | // smallest ansx = (ansx % (n / gcd(a, n)) + (n / gcd(a, n))) % (n / gcd(a, n)) 3841 | ``` 3842 | 3843 | #### 6.3.7 中国剩余定理 3844 | 3845 | #### 6.3.8 最小公倍数 3846 | 3847 | ```C++ 3848 | a / gcd(a, b) * b 3849 | ``` 3850 | 3851 | #### 6.3.9 分解质因数 3852 | 3853 | ```C++ 3854 | long long x; 3855 | cin >> x; 3856 | for (long long factor = 2; x != 1; factor++) { 3857 | if (x % factor == 0) 3858 | cout << factor << " is a prime factor" << endl; 3859 | while (x % factor == 0) 3860 | x = x / factor; 3861 | } 3862 | ``` 3863 | 3864 | #### 6.3.10 因数个数 3865 | 3866 | ```C++ 3867 | n = p1 ^ x1 * p2 ^ x2 * ... * pn ^ xn 3868 | total = (x1 + 1) * (x2 + 1) * ... * (xn + 1) 3869 | ``` 3870 | 3871 | #### 6.3.11 素数判定 3872 | 3873 | > 大于 3 的质数可以被表示为 6n - 1 或 6n + 1 3874 | 3875 | ```C++ 3876 | bool is_prime(int n) { 3877 | if (n == 1 || n % 2 == 0) 3878 | return false; 3879 | int t = sqrt(n); 3880 | for (int i = 3; i <= t; i += 2) 3881 | if (n % i == 0) 3882 | return false; 3883 | return true; 3884 | } 3885 | ``` 3886 | 3887 | ##### 6.3.11.1 Miller Rabin Primality Test 3888 | 3889 | > O(k(logN)^3) 3890 | 3891 | ```c++ 3892 | class MillerRabin { // O(k(logX)^3) 3893 | long long mulmod(long long a, long long b, long long c) { 3894 | if (a < b) 3895 | swap(a, b); 3896 | long long res = 0, x = a; 3897 | while (b > 0) { 3898 | if (b & 1) { 3899 | res = res + x; 3900 | if (res >= c) 3901 | res -= c; 3902 | } 3903 | x = x * 2; 3904 | if (x >= c) 3905 | x -= c; 3906 | b >>= 1; 3907 | } 3908 | return res % c; 3909 | } 3910 | 3911 | long long bigmod(long long a, long long p, long long mod) { 3912 | long long x = a, res = 1; 3913 | while (p) { 3914 | if (p & 1) 3915 | res = mulmod(res, x, mod); 3916 | x = mulmod(x, x, mod); 3917 | p >>= 1; 3918 | } 3919 | return res; 3920 | } 3921 | 3922 | bool witness(long long a, long long d, long long s, long long n) { 3923 | long long r = bigmod(a, d, n); 3924 | if (r == 1 || r == n - 1) 3925 | return false; 3926 | for (int i = 0; i < s - 1; i++) { 3927 | r = mulmod(r, r, n); 3928 | if (r == 1) 3929 | return true; 3930 | if (r == n - 1) 3931 | return false; 3932 | } 3933 | return true; 3934 | } 3935 | 3936 | public: 3937 | const vector aaa{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}; // enough for N < 2^64 3938 | 3939 | bool test(long long n) { 3940 | if (n <= 1) 3941 | return false; 3942 | 3943 | long long p = n - 1; 3944 | long long s = 0; 3945 | while (!(p & 1)) { 3946 | p /= 2; 3947 | s++; 3948 | } 3949 | 3950 | for (int i = 0; i < aaa.size() && aaa[i] < n; i++) 3951 | if (witness(aaa[i], p, s, n)) 3952 | return false; 3953 | return true; 3954 | } 3955 | }; 3956 | ``` 3957 | 3958 | #### 6.3.12 进制转换 3959 | 3960 | ```C++ 3961 | void convert_dec_to_base(int n, const int base) { 3962 | if (n == 0) 3963 | cout << 0 << endl; 3964 | while (n != 0) { 3965 | int e = n % base; 3966 | cout << e << " "; // printing in reverse order 3967 | n /= base; 3968 | } cout << endl; 3969 | } 3970 | 3971 | int convert_base_to_dec(const int s[], const int len, const int base) { 3972 | int result = 0; 3973 | for (int i = 0; i < len; i++) 3974 | result = result * base + s[i]; 3975 | return result; 3976 | } 3977 | ``` 3978 | 3979 | #### 6.3.13 A / C 3980 | > C(n, k) = C(n-1, k) + C(n-1, k-1) 3981 | > C(n, k) = C(n, n-k) 3982 | 3983 | ```c++ 3984 | #define MAXN 1002 3985 | #define MOD 1000000007 3986 | long long choose[MAXN][MAXN]; 3987 | 3988 | void init_choose_n_k() { 3989 | for (int i = 1; i < MAXN; i++) { 3990 | choose[i][i] = choose[i][0] = 1; 3991 | for (int j = 1; j < i; j++) 3992 | choose[i][j] = (choose[i-1][j-1] + choose[i-1][j]) % MOD; 3993 | } 3994 | } 3995 | ``` 3996 | 3997 | #### 6.3.14 质数表 3998 | 3999 | ```C++ 4000 | int is_prime[UP_LIMIT + 1]; 4001 | for (int i = 1; i <= UP_LIMIT; i++) // init to 1 4002 | is_prime[i] = 1; 4003 | for (int i = 4; i <= UP_LIMIT; i += 2) // even number is not 4004 | is_prime[i] = 0; 4005 | for (int k = 3; k*k <= UP_LIMIT; k++) // start from 9, end at sqrt 4006 | if (is_prime[k]) 4007 | for(int i = k*k; i <= UP_LIMIT; i += 2*k) // every two is not 4008 | is_prime[i] = 0; 4009 | ``` 4010 | 4011 | #### 6.3.15 Fast Exponention 4012 | 4013 | > To calculate n ^ p % M 4014 | 4015 | ```C++ 4016 | int power_modulo(int n, int p, int M) { 4017 | int result = 1; 4018 | while (p > 0) { 4019 | if (p % 2 == 1) 4020 | result = (result*n) % M; 4021 | p /= 2; 4022 | n = (n*n) % M; 4023 | } 4024 | return result; 4025 | } 4026 | ``` 4027 | 4028 | #### 6.3.16 Fast Fourier Transform FFT 4029 | 4030 | > [Reference 1](www.gatevin.moe/acm/fft算法学习笔记/) 4031 | > 4032 | > [Reference 2](https://github.com/marioyc/ACM-ICPC-Library/blob/master/math/fft.cpp) 4033 | > 4034 | > Example: calculate two number C = A * B 4035 | 4036 | ```c++ 4037 | #include 4038 | #include 4039 | #include 4040 | 4041 | #ifndef M_PI 4042 | const double M_PI = acos(-1); 4043 | #endif 4044 | 4045 | using namespace std; 4046 | 4047 | typedef complex Complex; 4048 | 4049 | void FFT(vector &A, int s) { 4050 | int n = A.size(); 4051 | int p = __builtin_ctz(n); 4052 | 4053 | vector a = A; 4054 | 4055 | for (int i = 0; i < n; ++i) { 4056 | int rev = 0; 4057 | for (int j = 0; j < p; ++j) { 4058 | rev <<= 1; 4059 | rev |= ((i >> j) & 1); 4060 | } 4061 | A[i] = a[rev]; 4062 | } 4063 | 4064 | Complex w, wn; 4065 | 4066 | for (int i = 1; i <= p; ++i) { 4067 | int M = (1<>1); 4068 | wn = Complex(cos(s*2.0*M_PI/(double)M), sin(s*2.0*M_PI/(double)M)); 4069 | 4070 | for (int j = 0; j < n; j += M) { 4071 | w = Complex(1.0, 0.0); 4072 | for (int l = j; l < K + j; ++l) { 4073 | Complex t = w; 4074 | t *= A[l + K]; 4075 | Complex u = A[l]; 4076 | A[l] += t; 4077 | u -= t; 4078 | A[l + K] = u; 4079 | w *= wn; 4080 | } 4081 | } 4082 | } 4083 | 4084 | if (s == -1) { 4085 | for (int i = 0; i < n; ++i) 4086 | A[i] /= (double)n; 4087 | } 4088 | } 4089 | 4090 | vector FFT_Multiply(vector &P, vector &Q) { 4091 | int n = P.size() + Q.size(); 4092 | 4093 | #define lowbit(x) (((x) ^ (x-1)) & (x)) 4094 | while (n != lowbit(n)) n += lowbit(n); 4095 | #undef lowbit 4096 | 4097 | P.resize(n, 0); 4098 | Q.resize(n, 0); 4099 | 4100 | FFT(P, 1); 4101 | FFT(Q, 1); 4102 | 4103 | vector R; 4104 | for (int i = 0; i < n; i++) R.push_back(P[i] * Q[i]); 4105 | 4106 | FFT(R, -1); 4107 | 4108 | return R; 4109 | } 4110 | 4111 | int main() { // multiply two number 4112 | string sa; // [a1 * 10^(?)] + [a2 * 10^(?)] + ... + [an * 10^(?)] 4113 | string sb; // [b1 * 10^(?)] + [b2 * 10^(?)] + ... + [bm * 10^(?)] 4114 | while (cin >> sa >> sb) { 4115 | vector a; 4116 | vector b; 4117 | 4118 | for (int i = 0; i < sa.length(); i++) 4119 | a.push_back(Complex(sa[sa.length() - i - 1] - '0', 0)); // add [a_ * (x)^(?)] 4120 | for (int i = 0; i < sb.length(); i++) 4121 | b.push_back(Complex(sb[sb.length() - i - 1] - '0', 0)); // add [b_ * (x)^(?)] 4122 | 4123 | // [c1 * 10^(?)] + [c2 * 10^(?)] + ... + [cn * 10^(?)] 4124 | // = 4125 | // [a1 * 10^(?)] + [a2 * 10^(?)] + ... + [an * 10^(?)] 4126 | // * 4127 | // [b1 * 10^(?)] + [b2 * 10^(?)] + ... + [bm * 10^(?)] 4128 | vector c = FFT_Multiply(a, b); 4129 | 4130 | vector ans(c.size()); 4131 | for (int i = 0; i < c.size(); i++) 4132 | ans[i] = c[i].real() + 0.5; // extract [c_ * (x)^(?)] // equivalent to [c_ * (x=10)^(?)] 4133 | for (int i = 0; i < ans.size() - 1; i++) { // process carry 4134 | ans[i + 1] += ans[i] / 10; 4135 | ans[i] %= 10; 4136 | } 4137 | 4138 | bool flag = false; 4139 | for (int i = ans.size() - 1; i >= 0; i--) { // print from most significant digit 4140 | if (ans[i]) 4141 | cout << ans[i], flag = true; 4142 | else if (flag || i == 0) 4143 | cout << 0; 4144 | } 4145 | cout << endl; 4146 | } 4147 | } 4148 | ``` 4149 | 4150 | ### 6.4 Game Theory 博弈论 4151 | 4152 | #### 6.4.1 Impartial Combinatorial Game 4153 | 4154 | > In combinatorial game theory, an impartial game is a game in which the allowable moves depend only on the position and not on which of the two players is currently moving, and where the payoffs are symmetric. In other words, the only difference between player 1 and player 2 is that player 1 goes first. 4155 | 4156 | > Impartial games can be analyzed using the Sprague–Grundy theorem. 4157 | 4158 | > Impartial games include Nim, Sprouts, Kayles, Quarto, Cram, Chomp, and poset games. Go and chess are not impartial, as each player can only place or move pieces of their own color. Games like ZÈRTZ and Chameleon are also not impartial, since although they are played with shared pieces, the payoffs are not necessarily symmetric for any given position. 4159 | 4160 | > A game that is not impartial is called a partisan game. 4161 | > 4162 | > [source: wiki](https://en.wikipedia.org/wiki/Impartial_game) 4163 | > 4164 | > [tutorial: topcoder](https://www.topcoder.com/community/data-science/data-science-tutorials/algorithm-games/) 4165 | 4166 | ##### 6.4.1.1 Nim Game 4167 | 4168 | > One good choice: brute force to find some pattern. 4169 | > 4170 | > We will not be able to play many of the games without decomposing them to smaller parts (sub-games), pre-computing some values for them, and then obtaining the result by combining these values. 4171 | > 4172 | > Positions have the following properties: 4173 | > 4174 | > - All terminal positions are losing. 4175 | > - If a player is able to move to a losing position then he is in a winning position. 4176 | > - If a player is able to move only to the winning positions then he is in a losing position. 4177 | > 4178 | > Rules of the Game of Nim: There are n piles of coins. When it is a player’s turn he chooses one pile and takes at least one coin from it. If someone is unable to move he loses (so the one who removes the last coin is the winner). 4179 | > 4180 | > Let n1, n2, ..., nk, be the sizes of the piles. It is a losing position for the player whose turn it is if and only if n1 xor n2 xor ... xor nk = 0. 4181 | 4182 | ##### 6.4.1.1 Composite Games – Sprague-Grundy Theorem and Nim Value 4183 | 4184 | > - Break composite game into subgames 4185 | > - Assign grundy number to every subgame according to which size of the pile in the Game of Nim it is equivalent to. 4186 | > - Now we have some subgames (piles), each subgame has its grundy number (size of pile) 4187 | > - xor all subgames 4188 | 4189 | > - Losing position of subgame has grundy number = 0. 4190 | > - A position has grundy number = smallest number among its next positions don't have. 4191 | 4192 | > If the table of grundy number is too large, we can precompute and find the pattern. 4193 | 4194 | ```c++ 4195 | // hihocoer 1173 4196 | const int MAXSTATE = 2e4 + 2; 4197 | 4198 | bool appear[MAXSTATE]; 4199 | int sg[MAXSTATE]; // Sprague-Grundy // Nim Value 4200 | void init_sg() { 4201 | sg[state] = 0; 4202 | for (int state = 1; state < MAXSTATE; state++) { // sg(x) = mex{sg(y) | y是x的后继局面} // mex{a[i]}表示a中未出现的最小非负整数 4203 | fill_n(appear, MAXSTATE, false); 4204 | for (int nx = 0; nx < state; nx++) 4205 | appear[sg[nx]] = true; 4206 | int pile_a = 1; 4207 | int pile_b = state - pile_a; 4208 | while (pile_a <= pile_b) { 4209 | appear[sg[pile_a] ^ sg[pile_b]] = true; 4210 | pile_a++; 4211 | pile_b--; 4212 | } 4213 | while (appear[sg[state]]) 4214 | sg[state]++; 4215 | } 4216 | } 4217 | 4218 | int main() { 4219 | 4220 | init_sg(); 4221 | 4222 | // --- start of finding pattern --- 4223 | // 4224 | // --- end of finding pattern --- 4225 | 4226 | int n; 4227 | cin >> n; 4228 | int result = 0; 4229 | for (int i = 0; i < n; i++) { 4230 | int a; 4231 | cin >> a; 4232 | 4233 | // by grundy number 4234 | // result ^= sg[a]; 4235 | 4236 | // by pattern 4237 | // if (a % 4 == 0) 4238 | // a--; 4239 | // else if (a % 4 == 3) 4240 | // a++; 4241 | // result ^= a; 4242 | } 4243 | if (result) 4244 | cout << "Alice" << endl; 4245 | else 4246 | cout << "Bob" << endl; 4247 | } 4248 | ``` 4249 | 4250 | ## 7. Geometry 4251 | 4252 | ### 7.1 2-Dimension Space 4253 | 4254 | #### 7.1.1 Template of Point 4255 | 4256 | ```C++ 4257 | struct point { 4258 | int x, y; 4259 | 4260 | double length() { 4261 | return sqrt(x*x + y*y); 4262 | } 4263 | 4264 | point operator + (const point &rhs) const { 4265 | return (point){x + rhs.x, y + rhs.y}; 4266 | } 4267 | 4268 | point operator - (const point &rhs) const { 4269 | return (point){x - rhs.x, y - rhs.y}; 4270 | } 4271 | 4272 | long operator* (const point& b) { 4273 | return x*b.y - y*b.x; 4274 | } 4275 | 4276 | long cross_product(const point& b) { 4277 | return x * b.x + y * b.y; 4278 | } 4279 | 4280 | bool at_right_of(const point& a, const point& b) const { 4281 | // a: relative point, b: base 4282 | point vec_self = {x - b.x, y - b.y}; 4283 | point vec_that = {a.x - b.x, a.y - b.y}; 4284 | long product = vec_self * vec_that; 4285 | if (product>0) return true; 4286 | if (product==0 && vec_self.length()>vec_that.length()) return true; 4287 | return false; 4288 | } 4289 | 4290 | double to_point(const point& b) const { 4291 | return sqrt(pow(x-b.x,2) + pow(y-b.y,2)); 4292 | } 4293 | 4294 | double to_segment(const point& a, const point& b) const { 4295 | double len_ab = a.to_point(b); 4296 | if (abs(len_ab)1 || r<0) return min(to_point(a), to_point(b)); 4299 | // projection of p is on extension of AB 4300 | r = ((a.y - y)*(b.y - y) - (a.x - x)*(b.y - a.y))/pow(len_ab,2); 4301 | return fabs(r*len_ab); 4302 | } 4303 | 4304 | double to_segment(const point& a, const point& b) const { 4305 | point vec_ab = {b.x - a.x, b.y - a.y}; 4306 | point vec_ia = {x - a.x, y - a.y}; 4307 | point vec_ib = {x - b.x, y - b.y}; 4308 | if (vec_ia.cross_product(vec_ab) < 0 || vec_ib.cross_product(vec_ab) > 0) 4309 | return min(to_point(a), to_point(b)); 4310 | return abs(vec_ab * vec_ia) / vec_ab.length(); 4311 | } // same meaning with v1, need test 4312 | 4313 | double to_line(const point& a, const point& b) const { 4314 | point vec_ab = {b.x - a.x, b.y - a.y}; 4315 | point vec_ia = {x - a.x, y - a.y}; 4316 | return abs(vec_ab * vec_ia) / vec_ab.length(); 4317 | } // same meaning with v1, need test 4318 | 4319 | point rotate(const point &rhs, double angle) const { 4320 | point t = (*this) - rhs; 4321 | double c = cos(angle), s = sin(angle); 4322 | return (point){rhs.x + t.x * c - t.y * s, rhs.y + t.x * s + t.y * c}; 4323 | } 4324 | }; 4325 | ``` 4326 | 4327 | #### 7.1.2 向量点乘 叉乘 4328 | 4329 | > a = (x1, y1) 4330 | > 4331 | > b = (x2, y2) 4332 | > 4333 | > i ... |i| = 1, vertical to a-b surface 4334 | 4335 | #### 7.1.3 dot product 4336 | > a dot b = x1 * x2 + y1 * y2 = |a| * |b| * cos(angle) 4337 | > 4338 | > if = 0: 90 degree 4339 | > 4340 | > a dot b / |b| = a project to b 4341 | 4342 | #### 7.1.4 cross product 4343 | > a x b = x1 * y2 - x2 * y1 = |a| * |b| * sin(angle) * i 4344 | > 4345 | > if < 0: b is at left of a 4346 | > 4347 | > if = 0: a, b in a line 4348 | > 4349 | > if 0: b is at right of a 4350 | > 4351 | > a x b = area of 平行四边形 4352 | > 4353 | > a x b x c = area of 平行六面体, c = (x3, y3) 4354 | 4355 | #### 7.1.5 直线公式 4356 | 4357 | > (x, y) = (x1, y1) + k * ((x2, y2) - (x1, y1)) 4358 | 4359 | #### 7.1.6 Convex Hull 4360 | 4361 | ##### Graham scan 4362 | 4363 | > O(VlogV) 4364 | 4365 | ```C++ 4366 | struct Point { 4367 | long x; 4368 | long y; 4369 | 4370 | bool at_right_of(Point& that, Point& base) { 4371 | Point vec_self = {this->x - base.x, this->y - base.y}; 4372 | Point vec_that = {that.x - base.x, that.y - base.y}; 4373 | 4374 | long product = vec_self * vec_that; 4375 | if (product > 0) 4376 | return true; // "this" is at right of "that" 4377 | if (product == 0 && vec_self.length() > vec_that.length()) 4378 | return true; // "this" is at right of "that" 4379 | return false; // "this" is NOT at right of "that" 4380 | }; 4381 | long operator* (Point& that) { 4382 | return this->x * that.y - this->y * that.x; 4383 | }; 4384 | double distance_to(Point& that) { 4385 | long x_diff = this->x - that.x; 4386 | long y_diff = this->y - that.y; 4387 | return sqrt(x_diff * x_diff + y_diff * y_diff); 4388 | }; 4389 | double length() { 4390 | return sqrt(this->x * this->x + this->y * this->y); 4391 | } 4392 | }; 4393 | 4394 | Point p[1005]; 4395 | int my_stack[1005]; 4396 | int n, l, my_stack_top = -1; 4397 | 4398 | bool compare(Point p1, Point p2) { 4399 | return p1.at_right_of(p2, p[0]); 4400 | } 4401 | 4402 | void push(int index) { 4403 | my_stack[++my_stack_top] = index; 4404 | } 4405 | int pop() { 4406 | int temp = my_stack[my_stack_top--]; 4407 | return temp; 4408 | } 4409 | 4410 | void graham_scan() { 4411 | push(0); 4412 | push(1); 4413 | 4414 | int pre; 4415 | int prepre; 4416 | for (int i = 2; i < n; i++) { 4417 | pre = my_stack_top; 4418 | prepre = my_stack_top - 1; 4419 | while (p[i].at_right_of(p[my_stack[pre]], p[my_stack[prepre]])) { 4420 | pop(); 4421 | if (my_stack_top == 0) 4422 | break; 4423 | pre = my_stack_top; 4424 | prepre = my_stack_top - 1; 4425 | } 4426 | push(i); 4427 | } 4428 | 4429 | int last = my_stack_top; 4430 | if (p[0].at_right_of(p[my_stack[last]], p[my_stack[pre]])) 4431 | pop(); 4432 | } 4433 | 4434 | int main(int argc, char const *argv[]) { 4435 | cin >> n >> l; 4436 | 4437 | int minimun = 0; 4438 | for (int i = 0; i < n; ++i) { 4439 | int temp_x, temp_y; 4440 | cin >> temp_x >> temp_y; 4441 | p[i] = {temp_x, temp_y}; 4442 | 4443 | if ((p[i].y < p[minimun].y) || (p[i].y == p[minimun].y && p[i].x < p[minimun].x)) 4444 | minimun = i; 4445 | } 4446 | 4447 | Point temp = {p[minimun].x, p[minimun].y}; // swap lowest and most left point to p[0] 4448 | p[minimun] = p[0]; 4449 | p[0] = temp; 4450 | 4451 | sort(p + 1, p + n, compare); // use p[0] as base, sort according to polar angle 4452 | graham_scan(); 4453 | // now all points in the stack is on Convex Hull // size of stack = 1 + stack_top 4454 | 4455 | for (int i = 0; i <= my_stack_top; i++) 4456 | cout << "point " << my_stack[i] << " is on Convex Hull" << endl; 4457 | } 4458 | ``` 4459 | 4460 | 4461 | 4462 | ## 8. Tricks + Miscellaneous 4463 | 4464 | ### 8.1 Bit Manipulation 4465 | 4466 | ```c++ 4467 | #define GET_BIT(n, i) (((n) & (1LL << ((i)-1))) >> ((i)-1)) // i start from 1 4468 | #define SET_BIT(n, i) ((n) | (1LL << ((i)-1))) 4469 | #define CLR_BIT(n, i) ((n) & ~(1LL << ((i)-1))) 4470 | ``` 4471 | 4472 | ### 8.1 Cantor Expansion / Reverse Cantor Expansion 4473 | 4474 | > for hashing, or ... 4475 | 4476 | ```C++ 4477 | long long factorial(int n) { 4478 | if (n == 0) 4479 | return 1; 4480 | 4481 | long long ans = n; 4482 | for (int i = 1; i < n; i++) 4483 | ans = ans * i; 4484 | return ans; 4485 | } 4486 | 4487 | long long cantor_expansion(int permutation[], int n) { 4488 | // input: (m-th permutation of n numbers, n) 4489 | // return: m 4490 | int used[n + 1]; 4491 | memset(used, n, sizeof(used)); 4492 | 4493 | long long ans = 0; 4494 | for (int i = 0; i < n; i++) { 4495 | int temp = 0; 4496 | used[permutation[i]] = 1; 4497 | for (int j = 1; j < permutation[i]; j++) 4498 | if (used[j] != 1) 4499 | temp += 1; 4500 | ans += factorial(n - 1 - i) * temp; 4501 | } 4502 | 4503 | return ans + 1; 4504 | } 4505 | 4506 | void reverse_cantor_expansion(int n, long long m) { 4507 | // m-th permutation of n numbers 4508 | int ans[n + 1], used[n + 1]; 4509 | memset(ans, -1, sizeof (ans)); 4510 | memset(used, 0, sizeof (used)); 4511 | 4512 | m = m - 1; 4513 | for (int i = n - 1; i >= 0; i--) { 4514 | long long fac = factorial(i); 4515 | int temp = m / fac + 1; 4516 | m = m - (temp - 1) * fac; 4517 | for (int j = 1; j <= temp; j++) 4518 | if (used[j] == 1) 4519 | temp++; 4520 | 4521 | ans[n - i] = temp; 4522 | used[temp] = 1; 4523 | } 4524 | 4525 | for (int i = 1; i < n + 1; i++) 4526 | cout << ans[i] << " "; 4527 | cout << "\n"; 4528 | } 4529 | ``` 4530 | 4531 | ### 8.2 pass 2-D array 4532 | 4533 | ```c++ 4534 | // The parameter is a 2D array 4535 | int array[10][10]; 4536 | void passFunc(int a[][10]) { 4537 | // ... 4538 | } 4539 | passFunc(array); 4540 | 4541 | // The parameter is an array containing pointers 4542 | int *array[10]; 4543 | for(int i = 0; i < 10; i++) 4544 | array[i] = new int[10]; 4545 | void passFunc(int *a[10]) { 4546 | // ... 4547 | } 4548 | passFunc(array); 4549 | 4550 | // The parameter is a pointer to a pointer 4551 | int **array; 4552 | array = new int *[10]; 4553 | for(int i = 0; i <10; i++) 4554 | array[i] = new int[10]; 4555 | void passFunc(int **a) { 4556 | // ... 4557 | } 4558 | passFunc(array); 4559 | ``` 4560 | 4561 | ### 8.3 Binary Display 4562 | 4563 | ```c++ 4564 | #include 4565 | void show_binary(unsigned long long x) { 4566 | printf("%s\n", bitset<64>(x).to_string().c_str()); 4567 | } 4568 | ``` 4569 | 4570 | ### 8.4 Fast Log 4571 | 4572 | > Built-in ``log(double)`` is not accurate for integer. 4573 | > 4574 | > Should ``(int)(log(double)+0.000....001)`` 4575 | 4576 | ```c++ 4577 | int fastlog(unsigned long long x, unsigned long long base) { 4578 | // ERROR VALUE IF X == BASE == ULLONG_MAX 4579 | 4580 | const unsigned long long HALF = 1ULL << 32; 4581 | unsigned long long cache[7]; 4582 | #define INIT(i) { cache[i] = base; if (base < HALF) base *= base; else base = ULLONG_MAX; } 4583 | INIT(0); INIT(1); INIT(2); INIT(3); INIT(4); INIT(5); INIT(6); 4584 | #undef INIT 4585 | 4586 | int ret = -(x == 0); 4587 | #define S(i, k) if (x >= cache[i]) ret += k, x /= cache[i]; else return ret; 4588 | S(6, 64); S(5, 32); S(4, 16); S(3, 8); S(2, 4); S(1, 2); S(0, 1); 4589 | #undef S 4590 | } 4591 | ``` 4592 | 4593 | ### 8.5 Squre Root 4594 | 4595 | ```c++ 4596 | long long sq(long long a) { 4597 | long long l = 1; 4598 | long long r = a + 1; 4599 | while (l + 1 < r) { 4600 | long long m = (l + r) / 2; 4601 | if (a / m < m) 4602 | r = m; 4603 | else 4604 | l = m; 4605 | } 4606 | return l; 4607 | } 4608 | ``` -------------------------------------------------------------------------------- /sources/.gitignore: -------------------------------------------------------------------------------- 1 | *.out 2 | -------------------------------------------------------------------------------- /sources/Matrix_class.cpp: -------------------------------------------------------------------------------- 1 | // Matrix 2 | // ... 3 | // http://www.matrix67.com/blog/archives/276 4 | // ... 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define GET_BIT(n, i) (((n) & (1 << ((i)-1))) >> ((i)-1)) 19 | #define SET_BIT(n, i) ((n) | (1 << ((i)-1))) 20 | #define CLR_BIT(n, i) ((n) & ~(1 << ((i)-1))) 21 | #define SHOW_A(x) {cout << #x << " = " << x << endl;} 22 | #define SHOW_B(x, y) {cout << #x << " = " << x << ", " << #y << " = " << y << endl;} 23 | #define SHOW_C(x, y, z) {cout << #x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl;} 24 | #define REACH_HERE {cout << "REACH_HERE!" << endl;} 25 | 26 | 27 | const double E = 1e-8; 28 | const double PI = acos(-1); 29 | 30 | using namespace std; 31 | 32 | int n; 33 | int k; 34 | int m; 35 | 36 | struct Matrix { 37 | // int height; 38 | // int width; 39 | 40 | long long value[32][32]; 41 | 42 | Matrix operator* (const Matrix& that); 43 | Matrix operator+ (const Matrix& that); 44 | Matrix mirror(); 45 | void show() { 46 | cout << endl; 47 | for (int i = 0; i < n; i++) { 48 | for (int j = 0; j < n; j++) 49 | cout << this->value[i][j] << " "; 50 | cout << endl; 51 | } 52 | } 53 | }; 54 | 55 | void mod_it(Matrix& temp) { 56 | for (int i = 0; i < n; i++) 57 | for (int j = 0; j < n; j++) 58 | temp.value[i][j] %= m; 59 | } 60 | 61 | Matrix Matrix::operator* (const Matrix& that) { 62 | Matrix temp; 63 | for (int i = 0; i < n; i++) { 64 | for (int j = 0; j < n; j++) { 65 | temp.value[i][j] = 0; 66 | for (int k = 0; k < n; k++) 67 | temp.value[i][j] += this->value[i][k] * that.value[k][j]; 68 | } 69 | } 70 | mod_it(temp); 71 | return temp; 72 | } 73 | 74 | Matrix Matrix::operator+ (const Matrix& that) { 75 | Matrix temp; 76 | for (int i = 0; i < n; i++) 77 | for (int j = 0; j < n; j++) 78 | temp.value[i][j] = this->value[i][j] + that.value[i][j]; 79 | mod_it(temp); 80 | return temp; 81 | } 82 | 83 | Matrix Matrix::mirror() { 84 | Matrix temp; 85 | for (int i = 0; i < n; i++) 86 | for (int j = 0; j < n; j++) 87 | temp.value[i][j] = this->value[i][j]; 88 | return temp; 89 | } 90 | 91 | Matrix a; 92 | Matrix one; 93 | 94 | Matrix get_single(int the_k) { 95 | if (the_k == 0) 96 | REACH_HERE; 97 | if (the_k == 1) 98 | return a.mirror(); 99 | 100 | if (the_k % 2 == 0) { 101 | Matrix temp = get_single(the_k / 2); 102 | return temp * temp; 103 | } 104 | else 105 | return get_single(the_k - 1) * get_single(1); 106 | } 107 | 108 | Matrix get(int the_k) { 109 | if (the_k == 0) 110 | REACH_HERE; 111 | if (the_k == 1) 112 | return a.mirror(); 113 | 114 | if (the_k % 2 == 0) { 115 | Matrix sum = get(the_k / 2); 116 | Matrix second = get_single(the_k / 2); 117 | return sum + (sum * second); 118 | } 119 | else 120 | return get(the_k - 1) + get_single(the_k); 121 | } 122 | 123 | int main() { 124 | ios::sync_with_stdio(false); 125 | 126 | cin >> n >> k >> m; 127 | for (int i = 0; i < n; i++) 128 | for (int j = 0; j < n; j++) 129 | cin >> a.value[i][j]; 130 | 131 | for (int i = 0; i < n; i++) 132 | for (int j = 0; j < n; j++) 133 | one.value[i][j] = i == j ? 1 : 0; 134 | 135 | Matrix ans = get(k); 136 | for (int i = 0; i < n; i++) { 137 | for (int j = 0; j < n; j++) 138 | cout << ans.value[i][j] << " "; 139 | cout << endl; 140 | } 141 | 142 | return 0; 143 | } 144 | 145 | 146 | // D - Matrix Power Series 147 | // Time Limit:3000MS Memory Limit:131072KB 64bit IO Format:%I64d & %I64u 148 | // Submit 149 | 150 | // Status 151 | // Description 152 | // Given a n × n matrix A and a positive integer k, find the sum S = A + A^2 + A^3 + … + A^k. 153 | 154 | // Input 155 | // The input contains exactly one test case. The first line of input contains three positive integers n (n ≤ 30), k (k ≤ 109) and m (m < 104). Then follow n lines each containing n nonnegative integers below 32,768, giving A’s elements in row-major order. 156 | 157 | // Output 158 | // Output the elements of S modulo m in the same way as A is given. 159 | 160 | // Sample Input 161 | // 2 2 4 162 | // 0 1 163 | // 1 1 164 | // Sample Output 165 | // 1 2 166 | // 2 3 167 | -------------------------------------------------------------------------------- /sources/bigint.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | /* 14 | * n: number 15 | * i: LSB starting from 1 16 | */ 17 | #define SET_BIT(n, i) ((n) | (1 << ((i)-1))) 18 | #define CLR_BIT(n, i) ((n) & ~(1 << ((i)-1))) 19 | #define GET_BIT(n, i) (((n) & (1 << ((i)-1))) >> ((i)-1)) 20 | #define SHOW(x) {cout << #x << " = " << x << endl;} 21 | #define ASSERT(x) { assert(x); cout << #x << endl; } 22 | const double E = 1e-8; 23 | const double PI = acos(-1); 24 | 25 | using namespace std; 26 | 27 | /* 28 | * Big Int begin 29 | */ 30 | 31 | const int BASE_LENGTH = 2; 32 | const int BASE = (int) pow(10, BASE_LENGTH); 33 | const int MAX_LENGTH = 500; 34 | 35 | string int_to_string(int i, int width, bool zero) { 36 | string res = ""; 37 | while (width--) { 38 | if (!zero && i == 0) return res; 39 | res = (char)(i%10 + '0') + res; 40 | i /= 10; 41 | } 42 | return res; 43 | } 44 | 45 | struct bigint { 46 | int len, s[MAX_LENGTH]; 47 | 48 | bigint() { 49 | memset(s, 0, sizeof(s)); 50 | len = 1; 51 | } 52 | 53 | bigint(unsigned long long num) { 54 | len = 0; 55 | while (num >= BASE) { 56 | s[len] = num % BASE; 57 | num /= BASE; 58 | len ++; 59 | } 60 | s[len++] = num; 61 | } 62 | 63 | bigint(const char* num) { 64 | int l = strlen(num); 65 | len = l/BASE_LENGTH; 66 | if (l % BASE_LENGTH) len++; 67 | int index = 0; 68 | for (int i = l - 1; i >= 0; i -= BASE_LENGTH) { 69 | int tmp = 0; 70 | int k = i - BASE_LENGTH + 1; 71 | if (k < 0) k = 0; 72 | for (int j = k; j <= i; j++) { 73 | tmp = tmp*10 + num[j] - '0'; 74 | } 75 | s[index++] = tmp; 76 | } 77 | } 78 | 79 | void clean() { 80 | while(len > 1 && !s[len-1]) len--; 81 | } 82 | 83 | string str() const { 84 | string ret = ""; 85 | if (len == 1 && !s[0]) return "0"; 86 | for(int i = 0; i < len; i++) { 87 | if (i == 0) { 88 | ret += int_to_string(s[len - i - 1], BASE_LENGTH, false); 89 | } else { 90 | ret += int_to_string(s[len - i - 1], BASE_LENGTH, true); 91 | } 92 | } 93 | return ret; 94 | } 95 | 96 | unsigned long long ll() const { 97 | unsigned long long ret = 0; 98 | for(int i = len-1; i >= 0; i--) { 99 | ret *= BASE; 100 | ret += s[i]; 101 | } 102 | return ret; 103 | } 104 | 105 | bigint operator + (const bigint& b) const { 106 | bigint c = b; 107 | while (c.len < len) c.s[c.len++] = 0; 108 | c.s[c.len++] = 0; 109 | bool r = 0; 110 | for (int i = 0; i < len || r; i++) { 111 | c.s[i] += (i= BASE; 113 | if (r) c.s[i] -= BASE; 114 | } 115 | c.clean(); 116 | return c; 117 | } 118 | 119 | bigint operator - (const bigint& b) const { 120 | if (operator < (b)) throw "cannot do subtract"; 121 | bigint c = *this; 122 | bool r = 0; 123 | for (int i = 0; i < b.len || r; i++) { 124 | c.s[i] -= b.s[i]; 125 | r = c.s[i] < 0; 126 | if (r) c.s[i] += BASE; 127 | } 128 | c.clean(); 129 | return c; 130 | } 131 | 132 | bigint operator * (const bigint& b) const { 133 | bigint c; 134 | c.len = len + b.len; 135 | for(int i = 0; i < len; i++) 136 | for(int j = 0; j < b.len; j++) 137 | c.s[i+j] += s[i] * b.s[j]; 138 | for(int i = 0; i < c.len-1; i++){ 139 | c.s[i+1] += c.s[i] / BASE; 140 | c.s[i] %= BASE; 141 | } 142 | c.clean(); 143 | return c; 144 | } 145 | 146 | bigint operator / (const int b) const { 147 | bigint ret; 148 | int down = 0; 149 | for (int i = len - 1; i >= 0; i--) { 150 | ret.s[i] = (s[i] + down * BASE) / b; 151 | down = s[i] + down * BASE - ret.s[i] * b; 152 | } 153 | ret.len = len; 154 | ret.clean(); 155 | return ret; 156 | } 157 | 158 | bool operator < (const bigint& b) const { 159 | if (len < b.len) return true; 160 | else if (len > b.len) return false; 161 | for (int i = 0; i < len; i++) 162 | if (s[i] < b.s[i]) return true; 163 | else if (s[i] > b.s[i]) return false; 164 | return false; 165 | } 166 | 167 | bool operator == (const bigint& b) const { 168 | return !(*this (const bigint& b) const { 172 | return b < *this; 173 | } 174 | }; 175 | 176 | /* 177 | * Big Int end. 178 | */ 179 | 180 | 181 | int test = 0, pass = 0; 182 | 183 | void assert(bool result) { 184 | test++; pass+=result; 185 | cout << (result ? "PASS: " : "FAIL: "); 186 | } 187 | 188 | 189 | int main() { 190 | bigint a = 2; 191 | bigint b = 9999; 192 | bigint c = "12345"; 193 | ASSERT((a+b).str()=="10001") 194 | ASSERT((a+b)==bigint(10001)) 195 | ASSERT((b/2)==4999) 196 | ASSERT(c == 12345) 197 | ASSERT(c < 123456) 198 | ASSERT(c > 123) 199 | ASSERT(!(c > 123456)) 200 | ASSERT(!(c < 123)) 201 | ASSERT(!(c == 12346)) 202 | ASSERT(!(c == 12344)) 203 | ASSERT(c.str() == "12345") 204 | ASSERT((b-1)==9998) 205 | ASSERT(a.ll() == 2) 206 | ASSERT(b.ll() == 9999) 207 | cout << "Total test: " << test << endl; 208 | cout << "Passed: " << pass << " (" << 100.0*pass/test << "%%)" << endl; 209 | } -------------------------------------------------------------------------------- /sources/cantor_expansion.cpp: -------------------------------------------------------------------------------- 1 | // Cantor expansion 2 | // reverse Cantor expansion 3 | 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | long long factorial(int n) { 10 | if (n == 0) 11 | return 1; 12 | 13 | long long ans = n; 14 | for (int i = 1; i < n; i++) 15 | ans = ans * i; 16 | return ans; 17 | } 18 | 19 | long long cantor_expansion(int permutation[], int n) { 20 | int used[n + 1]; 21 | memset(used, n, sizeof(used)); 22 | 23 | long long ans = 0; 24 | for (int i = 0; i < n; i++) { 25 | int temp = 0; 26 | used[permutation[i]] = 1; 27 | for (int j = 1; j < permutation[i]; j++) 28 | if (used[j] != 1) 29 | temp += 1; 30 | ans += factorial(n - 1 - i) * temp; 31 | } 32 | 33 | return ans + 1; 34 | } 35 | 36 | void reverse_cantor_expansion(int n, long long m) { 37 | int ans[n + 1], used[n + 1]; 38 | memset(ans, -1, sizeof (ans)); 39 | memset(used, 0, sizeof (used)); 40 | 41 | m = m - 1; 42 | for (int i = n - 1; i >= 0; i--) { 43 | long long fac = factorial(i); 44 | int temp = m / fac + 1; 45 | m = m - (temp - 1) * fac; 46 | for (int j = 1; j <= temp; j++) 47 | if (used[j] == 1) 48 | temp++; 49 | 50 | ans[n - i] = temp; 51 | used[temp] = 1; 52 | } 53 | 54 | for (int i = 1; i < n + 1; i++) 55 | cout << ans[i] << " "; 56 | cout << "\n"; 57 | } 58 | 59 | int main(int argc, char const *argv[]) { 60 | int n; 61 | long long m; 62 | cin >> n >> m; 63 | 64 | reverse_cantor_expansion(n, m); 65 | } 66 | 67 | 68 | 69 | // 描述 70 | // 输入两个自然数m,n 1<=n<=20,1<=m<=n! 71 | // 输出n个数的第m种全排列。 72 | // 如 : 73 | // 输入 3 1 74 | // 输出 1 2 3 75 | // 格式 76 | // 输入格式 77 | 78 | // 在一行中输入n m 79 | // 输出格式 80 | 81 | // 一个数列,既n个数的第m种排列 82 | // 每两个数之间空1格 83 | // 样例1 84 | // 样例输入1[复制] 85 | 86 | // 3 2 87 | // 样例输出1[复制] 88 | 89 | // 1 3 2 -------------------------------------------------------------------------------- /sources/convex_hull_GrahamsScan.cpp: -------------------------------------------------------------------------------- 1 | // Convex Hull problem 2 | // Graham's Scan 3 | 4 | #include 5 | #include 6 | #include 7 | #define TESTING false 8 | using namespace std; 9 | 10 | class Point { 11 | public: 12 | long __x__; 13 | long __y__; 14 | 15 | Point(); 16 | Point(long, long); 17 | ~Point(); 18 | 19 | bool at_right_of(Point& that, Point& base); 20 | long operator* (Point& that); 21 | double distance_to(Point& that); 22 | double length(); 23 | void show(); 24 | }; 25 | 26 | Point::Point(long x, long y): __x__(x), __y__(y) {}; 27 | Point::Point() {}; 28 | Point::~Point() {}; 29 | void Point::show() { 30 | cout << "(" << this->__x__ << ", " << this->__y__ << ")"; 31 | } 32 | bool Point::at_right_of(Point& that, Point& base) { 33 | Point vec_self(this->__x__ - base.__x__, this->__y__ - base.__y__); 34 | Point vec_that(that.__x__ - base.__x__, that.__y__ - base.__y__); 35 | 36 | long product = vec_self * vec_that; 37 | if (product > 0) { 38 | if (TESTING) { 39 | this->show(); 40 | cout << " at right of "; 41 | that.show(); 42 | cout << endl; 43 | } 44 | 45 | return true; 46 | } 47 | if (product == 0 && vec_self.length() > vec_that.length()) { 48 | if (TESTING) { 49 | this->show(); 50 | cout << " at right of "; 51 | that.show(); 52 | cout << endl; 53 | } 54 | return true; 55 | } 56 | 57 | if (TESTING) { 58 | this->show(); 59 | cout << " not at right of "; 60 | that.show(); 61 | cout << endl; 62 | } 63 | return false; 64 | }; 65 | double Point::length() { 66 | return sqrt(pow((double)this->__x__, 2) + pow((double)this->__y__, 2)); 67 | } 68 | long Point::operator* (Point& that) { 69 | return this->__x__ * that.__y__ - this->__y__ * that.__x__; 70 | }; 71 | double Point::distance_to(Point& that) { 72 | double temp = pow((double)this->__x__ - that.__x__, 2) + pow((double)this->__y__ - that.__y__, 2); 73 | return sqrt(temp); 74 | }; 75 | 76 | Point* p; 77 | int* stack; 78 | int n, l, stack_top = -1; 79 | 80 | bool compare(Point p1, Point p2) { 81 | Point vec_self(p1.__x__ - p[0].__x__, p1.__y__ - p[0].__y__); 82 | Point vec_that(p2.__x__ - p[0].__x__, p2.__y__ - p[0].__y__); 83 | 84 | long product = vec_self * vec_that; 85 | if (product > 0) 86 | return true; 87 | if (product == 0 && vec_self.length() > vec_that.length()) 88 | return true; 89 | return false; 90 | } 91 | 92 | void show() { 93 | cout << endl; 94 | for (int i = 0; i < n; i++) { 95 | p[i].show(); 96 | cout << endl; 97 | } 98 | cout << endl; 99 | } 100 | void show_stack() { 101 | cout << "stack: " << stack_top + 1 << endl; 102 | for (int i = stack_top; i >= 0; i--) { 103 | p[stack[i]].show(); 104 | cout << endl; 105 | } 106 | cout << "__________" << endl; 107 | } 108 | 109 | void push(int index) { 110 | stack[++stack_top] = index; 111 | 112 | if (TESTING) { 113 | cout << "\n-- push -- "; 114 | p[stack[stack_top]].show(); 115 | cout << endl; 116 | show_stack(); 117 | } 118 | } 119 | int pop() { 120 | int temp = stack[stack_top--]; 121 | if (TESTING) { 122 | cout << "\n-- pop -- "; 123 | p[temp].show(); 124 | cout << endl; 125 | show_stack(); 126 | } 127 | return temp; 128 | } 129 | 130 | void scan() { 131 | push(0); 132 | push(1); 133 | 134 | int pre; 135 | int prepre; 136 | for (int i = 2; i < n; i++) { 137 | pre = stack_top; 138 | prepre = stack_top - 1; 139 | while (p[i].at_right_of(p[stack[pre]], p[stack[prepre]])) { 140 | pop(); 141 | if (stack_top == 0) 142 | break; 143 | pre = stack_top; 144 | prepre = stack_top - 1; 145 | } 146 | push(i); 147 | } 148 | 149 | int last = stack_top; 150 | if (p[0].at_right_of(p[stack[last]], p[stack[pre]])) 151 | pop(); 152 | } 153 | 154 | int main(int argc, char const *argv[]) { 155 | cin >> n >> l; 156 | p = new Point[n]; 157 | stack = new int[n]; 158 | 159 | int minimun = 0; 160 | for (int i = 0; i < n; ++i) { 161 | int x, y; 162 | cin >> x >> y; 163 | Point temp(x, y); 164 | p[i] = temp; 165 | 166 | if ((p[i].__y__ < p[minimun].__y__) || (p[i].__y__ == p[minimun].__y__ && p[i].__x__ < p[minimun].__x__)) 167 | minimun = i; 168 | } 169 | 170 | Point temp(p[minimun].__x__, p[minimun].__y__); 171 | p[minimun] = p[0]; 172 | p[0] = temp; 173 | 174 | if (TESTING) { 175 | show(); 176 | } 177 | 178 | sort(p + 1, p + n, compare); 179 | 180 | if (TESTING) { 181 | show(); 182 | } 183 | scan(); 184 | 185 | if (TESTING) { 186 | cout << "\n--- final ---" << endl; 187 | show_stack(); 188 | } 189 | 190 | double ans = 0; 191 | for (int i = 0; i < stack_top; i++) { 192 | ans += p[stack[i]].distance_to(p[stack[i + 1]]); 193 | } 194 | ans += p[stack[0]].distance_to(p[stack[stack_top]]); 195 | 196 | cout << (long)(ans + 2 * 3.1415926 * l + 0.5) << endl; 197 | } 198 | 199 | 200 | // Wall 201 | // Time Limit: 1000MS Memory Limit: 10000K 202 | // Total Submissions: 29880 Accepted: 10035 203 | // Description 204 | 205 | // Once upon a time there was a greedy King who ordered his chief Architect to build a wall around the King's castle. The King was so greedy, that he would not listen to his Architect's proposals to build a beautiful brick wall with a perfect shape and nice tall towers. Instead, he ordered to build the wall around the whole castle using the least amount of stone and labor, but demanded that the wall should not come closer to the castle than a certain distance. If the King finds that the Architect has used more resources to build the wall than it was absolutely necessary to satisfy those requirements, then the Architect will loose his head. Moreover, he demanded Architect to introduce at once a plan of the wall listing the exact amount of resources that are needed to build the wall. 206 | 207 | 208 | // Your task is to help poor Architect to save his head, by writing a program that will find the minimum possible length of the wall that he could build around the castle to satisfy King's requirements. 209 | 210 | // The task is somewhat simplified by the fact, that the King's castle has a polygonal shape and is situated on a flat ground. The Architect has already established a Cartesian coordinate system and has precisely measured the coordinates of all castle's vertices in feet. 211 | // Input 212 | 213 | // The first line of the input file contains two integer numbers N and L separated by a space. N (3 <= N <= 1000) is the number of vertices in the King's castle, and L (1 <= L <= 1000) is the minimal number of feet that King allows for the wall to come close to the castle. 214 | 215 | // Next N lines describe coordinates of castle's vertices in a clockwise order. Each line contains two integer numbers Xi and Yi separated by a space (-10000 <= Xi, Yi <= 10000) that represent the coordinates of ith vertex. All vertices are different and the sides of the castle do not intersect anywhere except for vertices. 216 | // Output 217 | 218 | // Write to the output file the single number that represents the minimal possible length of the wall in feet that could be built around the castle to satisfy King's requirements. You must present the integer number of feet to the King, because the floating numbers are not invented yet. However, you must round the result in such a way, that it is accurate to 8 inches (1 foot is equal to 12 inches), since the King will not tolerate larger error in the estimates. 219 | // Sample Input 220 | 221 | // 9 100 222 | // 200 400 223 | // 300 400 224 | // 300 300 225 | // 400 300 226 | // 400 400 227 | // 500 400 228 | // 500 200 229 | // 350 200 230 | // 200 200 231 | // Sample Output 232 | 233 | // 1628 -------------------------------------------------------------------------------- /sources/euclidean_algorithm_extend.cpp: -------------------------------------------------------------------------------- 1 | // extend-euclidean algorithm 2 | // 1. gcd(a, b) 3 | // 2. ax mod n = b mod n ......-> ax + ny = gcd(a, n) * (b / gcd(a, n)) 4 | // 3. ax mod n = 1 ......-> ax + ny = gcd(a, n) * (1 / gcd(a, n)) 5 | 6 | #include 7 | using namespace std; 8 | 9 | long long ansx, ansy, d; 10 | 11 | void euclidean(long long a, long long b) { 12 | if (b == 0) { 13 | ansx = 1; 14 | ansy = 0; 15 | d = a; 16 | } else { 17 | euclidean(b, a % b); 18 | long long temp = ansx; 19 | ansx = ansy; 20 | ansy = temp - a / b * ansy; 21 | } 22 | } 23 | 24 | int main(int argc, char const *argv[]) { 25 | long long x, y, m, n, L; 26 | cin >> x >> y >> m >> n >> L; 27 | long long yx = y - x; 28 | long long mn = m - n; 29 | 30 | if (mn < 0) { 31 | mn = -mn; 32 | yx = -yx; 33 | } 34 | 35 | ansx = 0; 36 | ansy = 0; 37 | d = 0; 38 | euclidean(mn, L); 39 | 40 | if (m == n || yx % d != 0) { 41 | cout << "Impossible"; 42 | } 43 | else { 44 | ansx = ansx * (yx / d); 45 | long long s = L / d; 46 | ansx = (ansx % s + s) % s; 47 | cout << ansx; 48 | } 49 | } 50 | 51 | // 青蛙的约会 52 | // Time Limit: 1000MS Memory Limit: 10000K 53 | // Total Submissions: 88315 Accepted: 15676 54 | // Description 55 | 56 | // 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面。它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止。可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置。不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的。但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的。为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面。 57 | // 我们把这两只青蛙分别叫做青蛙A和青蛙B,并且规定纬度线上东经0度处为原点,由东往西为正方向,单位长度1米,这样我们就得到了一条首尾相接的数轴。设青蛙A的出发点坐标是x,青蛙B的出发点坐标是y。青蛙A一次能跳m米,青蛙B一次能跳n米,两只青蛙跳一次所花费的时间相同。纬度线总长L米。现在要你求出它们跳了几次以后才会碰面。 58 | // Input 59 | 60 | // 输入只包括一行5个整数x,y,m,n,L,其中x≠y < 2000000000,0 < m、n < 2000000000,0 < L < 2100000000。 61 | // Output 62 | 63 | // 输出碰面所需要的跳跃次数,如果永远不可能碰面则输出一行"Impossible" 64 | // Sample Input 65 | 66 | // 1 2 3 4 5 67 | // Sample Output 68 | 69 | // 4 -------------------------------------------------------------------------------- /sources/euclidean_algorithm_extend_Linear_congruence_equation.cpp: -------------------------------------------------------------------------------- 1 | // extend-euclidean algorithm 2 | // 1. gcd(a, b) 3 | // 2. ax mod n = b mod n ......-> ax + ny = gcd(a, n) * (b / gcd(a, n)) 4 | // 3. ax mod n = 1 ......-> ax + ny = gcd(a, n) * (1 / gcd(a, n)) 5 | 6 | #include 7 | using namespace std; 8 | 9 | long long ansx, ansy, ansd; 10 | 11 | void euclidean(long long a, long long b) { 12 | if (b == 0) { 13 | ansx = 1; 14 | ansy = 0; 15 | ansd = a; 16 | } else { 17 | euclidean(b, a % b); 18 | long long temp = ansx; 19 | ansx = ansy; 20 | ansy = temp - a / b * ansy; 21 | } 22 | } 23 | 24 | int main(int argc, char const *argv[]) { 25 | long long a, b; 26 | cin >> a >> b; 27 | 28 | ansx = 0; 29 | ansy = 0; 30 | ansd = 0; 31 | euclidean(a, b); 32 | 33 | if (ansd != 1) { 34 | cout << "bad!"; 35 | } 36 | else { 37 | ansx = (ansx % b + b) % b; 38 | cout << ansx; 39 | } 40 | } 41 | 42 | // 描述 43 | // 求关于x的同余方程ax ≡ 1 (mod b)的最小正整数解。 44 | // 格式 45 | // 输入格式 46 | 47 | // 输入只有一行,包含两个正整数a, b,用一个空格隔开。 48 | // 输出格式 49 | 50 | // 输出只有一行,包含一个正整数x0,即最小正整数解。输入数据保证一定有解。 51 | // 样例1 52 | // 样例输入1[复制] 53 | 54 | // 3 10 55 | // 样例输出1[复制] 56 | 57 | // 7 -------------------------------------------------------------------------------- /sources/euclidean_algorithm_extend_chinese_reminder_theory.cpp: -------------------------------------------------------------------------------- 1 | // Chinese Reminder Theory 2 | // solution to x mod A = a; x mode B = b; ... 3 | 4 | #include 5 | using namespace std; 6 | 7 | int ansx, ansy, ansd; 8 | 9 | void extend_euclidean(int a, int b) { 10 | if (b == 0) { 11 | ansx = 1; 12 | ansy = 0; 13 | ansd = a; 14 | } else { 15 | extend_euclidean(b, a % b); 16 | int temp = ansx; 17 | ansx = ansy; 18 | ansy = temp - a / b * ansy; 19 | } 20 | } 21 | 22 | int main(int argc, char const *argv[]) { 23 | const int P = 23; 24 | const int E = 28; 25 | const int I = 33; 26 | const int PEI = P * E * I; 27 | extend_euclidean(P, E); 28 | const int lcmPE = P * E / ansd; 29 | extend_euclidean(P, I); 30 | const int lcmPI = P * I / ansd; 31 | extend_euclidean(E, I); 32 | const int lcmEI = E * I / ansd; 33 | 34 | int noc = 1; 35 | while (true) { 36 | int p, e, i, now, xp, xe, xi; 37 | cin >> p >> e >> i >> now; 38 | if (p == -1) 39 | break; 40 | 41 | extend_euclidean(lcmPE, I); 42 | xi = (ansx % I + I) % I * lcmPE; 43 | extend_euclidean(lcmPI, E); 44 | xe = (ansx % E + E) % E * lcmPI; 45 | extend_euclidean(lcmEI, P); 46 | xp = (ansx % P + P) % P * lcmEI; 47 | 48 | int x = ((xi * i + xe * e + xp * p) % PEI + PEI) % PEI; 49 | int ans = (x - now + PEI) % PEI; 50 | if (ans == 0) 51 | ans = PEI; 52 | cout << "Case " << noc++ << ": the next triple peak occurs in " << ans << " days.\n"; 53 | } 54 | } 55 | 56 | 57 | 58 | // Biorhythms 59 | // Time Limit: 1000MS Memory Limit: 10000K 60 | // Total Submissions: 111704 Accepted: 34800 61 | // Description 62 | 63 | // Some people believe that there are three cycles in a person's life that start the day he or she is born. These three cycles are the physical, emotional, and intellectual cycles, and they have periods of lengths 23, 28, and 33 days, respectively. There is one peak in each period of a cycle. At the peak of a cycle, a person performs at his or her best in the corresponding field (physical, emotional or mental). For example, if it is the mental curve, thought processes will be sharper and concentration will be easier. 64 | // Since the three cycles have different periods, the peaks of the three cycles generally occur at different times. We would like to determine when a triple peak occurs (the peaks of all three cycles occur in the same day) for any person. For each cycle, you will be given the number of days from the beginning of the current year at which one of its peaks (not necessarily the first) occurs. You will also be given a date expressed as the number of days from the beginning of the current year. You task is to determine the number of days from the given date to the next triple peak. The given date is not counted. For example, if the given date is 10 and the next triple peak occurs on day 12, the answer is 2, not 3. If a triple peak occurs on the given date, you should give the number of days to the next occurrence of a triple peak. 65 | // Input 66 | 67 | // You will be given a number of cases. The input for each case consists of one line of four integers p, e, i, and d. The values p, e, and i are the number of days from the beginning of the current year at which the physical, emotional, and intellectual cycles peak, respectively. The value d is the given date and may be smaller than any of p, e, or i. All values are non-negative and at most 365, and you may assume that a triple peak will occur within 21252 days of the given date. The end of input is indicated by a line in which p = e = i = d = -1. 68 | // Output 69 | 70 | // For each test case, print the case number followed by a message indicating the number of days to the next triple peak, in the form: 71 | 72 | // Case 1: the next triple peak occurs in 1234 days. 73 | 74 | // Use the plural form ``days'' even if the answer is 1. 75 | // Sample Input 76 | 77 | // 0 0 0 0 78 | // 0 0 0 100 79 | // 5 20 34 325 80 | // 4 5 6 7 81 | // 283 102 23 320 82 | // 203 301 203 40 83 | // -1 -1 -1 -1 84 | // Sample Output 85 | 86 | // Case 1: the next triple peak occurs in 21252 days. 87 | // Case 2: the next triple peak occurs in 21152 days. 88 | // Case 3: the next triple peak occurs in 19575 days. 89 | // Case 4: the next triple peak occurs in 16994 days. 90 | // Case 5: the next triple peak occurs in 8910 days. 91 | // Case 6: the next triple peak occurs in 10789 days. -------------------------------------------------------------------------------- /sources/get_prime_factor.cpp: -------------------------------------------------------------------------------- 1 | // get prime factor 2 | // :::: for prime number, if n >= 5, prime number = 6n+1 or 6n-1 :::: 3 | 4 | #include 5 | using namespace std; 6 | 7 | int main(int argc, char const *argv[]) { 8 | long long p; 9 | cin >> p; 10 | 11 | long long ans = 1; 12 | while (p != 1) { 13 | ans++; 14 | while (p % ans == 0) { 15 | p = p / ans; 16 | } 17 | } 18 | cout << ans; 19 | } 20 | 21 | 22 | // 描述 23 | // 已知正整数n是两个不同的质数的乘积试求出较大的那个质数。 24 | // 格式 25 | // 输入格式 26 | 27 | // 输入只有一行包含一个正整数n。 28 | // 输出格式 29 | 30 | // 输出只有一行包含一个正整数p, 即较大的那个质数。 31 | // 样例1 32 | // 样例输入1[复制] 33 | 34 | // 21 35 | // 样例输出1[复制] 36 | 37 | // 7 38 | // 限制 39 | // 1S -------------------------------------------------------------------------------- /sources/hash_map.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | /* 15 | * n: number 16 | * i: LSB starting from 1 17 | */ 18 | #define GET_BIT(n, i) (((n) & (1 << ((i)-1))) >> ((i)-1)) 19 | #define SET_BIT(n, i) ((n) | (1 << ((i)-1))) 20 | #define CLR_BIT(n, i) ((n) & ~(1 << ((i)-1))) 21 | #define SHOW_A(x) {cout << #x << " = " << x << endl;} 22 | #define SHOW_B(x, y) {cout << #x << " = " << x << ", " << #y << " = " << y << endl;} 23 | #define SHOW_C(x, y, z) {cout << #x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl;} 24 | #define REACH_HERE {cout << "REACH_HERE!" << endl;} 25 | #define ASSERT(x) { assert(x); cout << #x << endl; } 26 | 27 | const double E = 1e-8; 28 | const double PI = acos(-1); 29 | 30 | using namespace std; 31 | 32 | int test = 0, pass = 0; 33 | 34 | void assert(bool result) { 35 | test++; pass+=result; 36 | cout << (result ? "PASS: " : "FAIL: "); 37 | } 38 | 39 | 40 | int main() { 41 | ios::sync_with_stdio(false); 42 | 43 | __gnu_cxx::hash_map months; 44 | 45 | months["january"] = 31; 46 | months["february"] = 28; 47 | months["march"] = 31; 48 | months["april"] = 30; 49 | months["may"] = 31; 50 | months["june"] = 30; 51 | months["july"] = 31; 52 | months["august"] = 31; 53 | months["september"] = 30; 54 | months["october"] = 31; 55 | months["november"] = 30; 56 | months["december"] = 31; 57 | 58 | ASSERT(months["september"]==30) 59 | ASSERT(months["august"]==31) 60 | 61 | cout << "Passed: " << pass << " (" << 100.0*pass/test << "%%)" << endl; 62 | 63 | return 0; 64 | } -------------------------------------------------------------------------------- /sources/list.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | list ll; 8 | ll.push_back(1); 9 | ll.push_back(2); 10 | ll.push_back(3); 11 | ll.push_back(4); 12 | 13 | for (list::iterator li = ll.begin(); li != ll.end(); li++) { 14 | cout << *li << endl; 15 | } 16 | 17 | return 0; 18 | } -------------------------------------------------------------------------------- /sources/maximum_bipartite_matching.cpp: -------------------------------------------------------------------------------- 1 | // maximum bipartite matching 2 | // Hungarian algorithm 3 | 4 | 5 | // #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define GET_BIT(n, i) ((n) & (1 << ((i)-1))) 19 | #define SET_BIT(n, i) ((n) | (1 << ((i)-1))) 20 | #define CLR_BIT(n, i) ((n) & ~(1 << ((i)-1))) 21 | #define SHOW_A(x) {cout << #x << " = " << x << endl;} 22 | #define SHOW_B(x, y) {cout << #x << " = " << x << ", " << #y << " = " << y << endl;} 23 | #define SHOW_C(x, y, z) {cout << #x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl;} 24 | #define REACH_HERE {cout << "REACH_HERE! line: " << __LINE__ << endl;} 25 | 26 | // const double E = 1e-8; 27 | // const double PI = acos(-1); 28 | 29 | using namespace std; 30 | 31 | int n_cow, n_stall; 32 | 33 | int n_node; 34 | int graph[405][405]; 35 | int match[405]; 36 | int visited[405]; 37 | 38 | bool augment(int cur) { 39 | for (int i = 0; i < n_node; i++) { // for all node 40 | if (graph[cur][i] > 0 && visited[i] == 0) { // if have edge and not visited 41 | visited[i] = 1; // mark visited 42 | if (match[i] == -1 || augment(match[i])) { // if not matched, or its previous can find other match 43 | match[i] = cur; // match it 44 | return true; 45 | } 46 | } 47 | } 48 | return false; // cannot find any match 49 | } 50 | 51 | int solve() { 52 | while (cin >> n_cow >> n_stall) { 53 | memset(graph, 0, sizeof(graph)); 54 | 55 | n_node = n_cow + n_stall; 56 | for (int i = 0; i < n_cow; i++) { 57 | int temp; 58 | cin >> temp; 59 | for (int j = 0; j < temp; j++) { 60 | int temptemp; 61 | cin >> temptemp; 62 | graph[i][--temptemp + n_cow] = 1; 63 | } 64 | } 65 | 66 | int n_match = 0; 67 | memset(match, -1, sizeof(match)); 68 | for (int i = 0; i < n_node; i++) { // for each node, find an augmented path 69 | memset(visited, 0, sizeof(visited)); // each node only visit once 70 | if (augment(i)) // if found 71 | n_match++; // maximum matching ++ 72 | } 73 | 74 | cout << n_match << endl; 75 | } 76 | } 77 | 78 | int main() { 79 | ios::sync_with_stdio(false); 80 | 81 | solve(); 82 | 83 | return 0; 84 | } 85 | 86 | 87 | 88 | // The Perfect Stall 89 | // Time Limit: 1000MS Memory Limit: 10000K 90 | // Total Submissions: 18893 Accepted: 8585 91 | // Description 92 | 93 | // Farmer John completed his new barn just last week, complete with all the latest milking technology. Unfortunately, due to engineering problems, all the stalls in the new barn are different. For the first week, Farmer John randomly assigned cows to stalls, but it quickly became clear that any given cow was only willing to produce milk in certain stalls. For the last week, Farmer John has been collecting data on which cows are willing to produce milk in which stalls. A stall may be only assigned to one cow, and, of course, a cow may be only assigned to one stall. 94 | // Given the preferences of the cows, compute the maximum number of milk-producing assignments of cows to stalls that is possible. 95 | // Input 96 | 97 | // The input includes several cases. For each case, the first line contains two integers, N (0 <= N <= 200) and M (0 <= M <= 200). N is the number of cows that Farmer John has and M is the number of stalls in the new barn. Each of the following N lines corresponds to a single cow. The first integer (Si) on the line is the number of stalls that the cow is willing to produce milk in (0 <= Si <= M). The subsequent Si integers on that line are the stalls in which that cow is willing to produce milk. The stall numbers will be integers in the range (1..M), and no stall will be listed twice for a given cow. 98 | // Output 99 | 100 | // For each case, output a single line with a single integer, the maximum number of milk-producing stall assignments that can be made. 101 | // Sample Input 102 | 103 | // 5 5 104 | // 2 2 5 105 | // 3 2 3 4 106 | // 2 1 5 107 | // 3 1 2 5 108 | // 1 2 109 | // Sample Output 110 | 111 | // 4 -------------------------------------------------------------------------------- /sources/minimum_spanning_tree_Kruskal.cpp: -------------------------------------------------------------------------------- 1 | // minimum spanning tree 2 | // kruskal 3 | // union-find set 4 | // poj 1861 5 | 6 | // #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define GET_BIT(n, i) ((n) & (1 << ((i)-1))) 20 | #define SET_BIT(n, i) ((n) | (1 << ((i)-1))) 21 | #define CLR_BIT(n, i) ((n) & ~(1 << ((i)-1))) 22 | #define SHOW_A(x) {cout << #x << " = " << x << endl;} 23 | #define SHOW_B(x, y) {cout << #x << " = " << x << ", " << #y << " = " << y << endl;} 24 | #define SHOW_C(x, y, z) {cout << #x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl;} 25 | #define REACH_HERE {cout << "REACH_HERE!" << endl;} 26 | 27 | 28 | const double E = 1e-8; 29 | const double PI = acos(-1); 30 | 31 | using namespace std; 32 | 33 | struct Edge { 34 | int from; 35 | int to; 36 | int length; 37 | 38 | bool operator< (Edge b) const { 39 | return this->length < b.length; 40 | } 41 | }; 42 | 43 | int get_father(int father[], int a) { 44 | if (father[a] != a) 45 | return father[a] = get_father(father, father[a]); 46 | return a; 47 | } 48 | 49 | void show(Edge a) { 50 | cout << a.from << "-" << a.to << ": " << a.length << endl; 51 | } 52 | 53 | 54 | void solve() { 55 | int ans_max_len = 0; 56 | vector ans_cable; 57 | 58 | int n_node, n_edge; 59 | vector e; 60 | 61 | cin >> n_node >> n_edge; 62 | for (int i = 0; i < n_edge; i++) { 63 | int from, to, length; 64 | cin >> from >> to >> length; 65 | Edge temp = {--from, --to, length}; 66 | e.push_back(temp); 67 | } 68 | 69 | int added[n_node]; 70 | memset(added, 0, sizeof(added)); 71 | int father[n_node]; 72 | for (int i = 0; i < n_node; i++) 73 | father[i] = i; 74 | 75 | sort(e.begin(), e.end()); 76 | 77 | int to_add = n_node - 1; 78 | for (int cur = 0; to_add; cur++) { 79 | int fromSfather = get_father(father, e[cur].from); 80 | int toSfather = get_father(father, e[cur].to); 81 | if (fromSfather != toSfather) { 82 | father[fromSfather] = toSfather; 83 | to_add--; 84 | 85 | ans_cable.push_back(e[cur]); 86 | ans_max_len = max(ans_max_len, e[cur].length); 87 | } 88 | } 89 | 90 | cout << ans_max_len << endl << n_node - 1 << endl; 91 | for (int i = 0; i < ans_cable.size(); i++) 92 | cout << (ans_cable[i].from + 1) << " " << (ans_cable[i].to + 1) << endl; 93 | } 94 | 95 | int main() { 96 | ios::sync_with_stdio(false); 97 | 98 | solve(); 99 | 100 | return 0; 101 | } 102 | 103 | 104 | // Network 105 | // Time Limit: 1000MS Memory Limit: 30000K 106 | // Total Submissions: 13832 Accepted: 5397 Special Judge 107 | 108 | // Description 109 | // Andrew is working as system administrator and is planning to establish a new network in his company. There will be N hubs in the company, they can be connected to each other using cables. Since each worker of the company must have access to the whole network, each hub must be accessible by cables from any other hub (with possibly some intermediate hubs). 110 | // Since cables of different types are available and shorter ones are cheaper, it is necessary to make such a plan of hub connection, that the maximum length of a single cable is minimal. There is another problem — not each hub can be connected to any other one because of compatibility problems and building geometry limitations. Of course, Andrew will provide you all necessary information about possible hub connections. 111 | // You are to help Andrew to find the way to connect hubs so that all above conditions are satisfied. 112 | 113 | // Input 114 | // The first line of the input contains two integer numbers: N - the number of hubs in the network (2 <= N <= 1000) and M - the number of possible hub connections (1 <= M <= 15000). All hubs are numbered from 1 to N. The following M lines contain information about possible connections - the numbers of two hubs, which can be connected and the cable length required to connect them. Length is a positive integer number that does not exceed 106. There will be no more than one way to connect two hubs. A hub cannot be connected to itself. There will always be at least one way to connect all hubs. 115 | 116 | // Output 117 | // Output first the maximum length of a single cable in your hub connection plan (the value you should minimize). Then output your plan: first output P - the number of cables used, then output P pairs of integer numbers - numbers of hubs connected by the corresponding cable. Separate numbers by spaces and/or line breaks. 118 | 119 | // Sample Input 120 | 121 | // 4 6 122 | // 1 2 1 123 | // 1 3 1 124 | // 1 4 2 125 | // 2 3 1 126 | // 3 4 1 127 | // 2 4 1 128 | 129 | // Sample Output 130 | 131 | // 1 132 | // 4 133 | // 1 2 134 | // 1 3 135 | // 2 3 136 | // 3 4 137 | -------------------------------------------------------------------------------- /sources/minimum_spanning_tree_prim_V2.cpp: -------------------------------------------------------------------------------- 1 | // minimum spanning tree 2 | // prim 3 | // if edge is almost n_node * n_node, then use graph[][] would be faster then vector graph[] 4 | // this kind of Prim: Time complexity = O(V^2) 5 | // use another : O(E*log(V)) 6 | 7 | // Vijos P1190 8 | 9 | // #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #define GET_BIT(n, i) ((n) & (1 << ((i)-1))) 23 | #define SET_BIT(n, i) ((n) | (1 << ((i)-1))) 24 | #define CLR_BIT(n, i) ((n) & ~(1 << ((i)-1))) 25 | #define SHOW_A(x) {cout << #x << " = " << x << endl;} 26 | #define SHOW_B(x, y) {cout << #x << " = " << x << ", " << #y << " = " << y << endl;} 27 | #define SHOW_C(x, y, z) {cout << #x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl;} 28 | #define REACH_HERE {cout << "REACH_HERE!" << endl;} 29 | 30 | using namespace std; 31 | 32 | void mst_prim() { 33 | int ans = 0; 34 | 35 | int n_node; 36 | int n_edge; 37 | //////////////////////////////////////// 38 | cin >> n_node >> n_edge; // read data 39 | //////////////////////////////////////// 40 | int graph[n_node][n_node]; 41 | int min_dis[n_node]; 42 | for (int i = 0; i < n_node; i++) 43 | min_dis[i] = INT_MAX; // initialize 44 | //////////////////////////////////////// 45 | memset(graph, -1, sizeof(graph)); 46 | for (int i = 0; i < n_edge; i++) { 47 | int a, b, length; 48 | cin >> a >> b >> length; 49 | a--; 50 | b--; 51 | graph[a][b] = length; 52 | graph[b][a] = length; 53 | } 54 | for (int i = 0; i < n_node; i++) 55 | for (int j = 0; j < n_node; j++) 56 | if (graph[i][j] == -1) 57 | graph[i][j] = INT_MAX; 58 | //////////////////////////////////////// 59 | 60 | 61 | int cur = 0; // the node just added 62 | for (int i = 1; i < n_node; i++) { // total need pick n-1 edges 63 | min_dis[cur] = -1; // add cur 64 | for (int j = 0; j < n_node; j++) // for all node 65 | if (graph[cur][j] < min_dis[j]) // if can reach from new node and nearer 66 | min_dis[j] = graph[cur][j]; // update the distance 67 | int next = -1; // the node to add 68 | int cur_min_dis = INT_MAX; // current distance of nearest node 69 | for (int j = 0; j < n_node; j++) // check all node 70 | if (min_dis[j] >= 0 && min_dis[j] < cur_min_dis) { // if j node is nearer 71 | next = j; // record 72 | cur_min_dis = min_dis[j]; 73 | } 74 | // add edge: cur->next 75 | cur = next; // next node to add 76 | ans = max(ans, cur_min_dis); // from the question 77 | // should directly maintain the min distance for each node to current tree 78 | // use heapfy... 79 | } 80 | 81 | cout << n_node - 1 << " " << ans << endl; 82 | } 83 | 84 | int main() { 85 | ios::sync_with_stdio(false); 86 | 87 | mst_prim(); 88 | 89 | return 0; 90 | } 91 | 92 | 93 | // P1190繁忙的都市请登录后递交 94 | // 标签:四川2005[显示标签] 95 | // 描述 96 | // 城市C是一个非常繁忙的大都市,城市中的道路十分的拥挤,于是市长决定对其中的道路进行改造。城市C的道路是这样分布的:城市中有n个交叉路口,有些交叉路口之间有道路相连,两个交叉路口之间最多有一条道路相连接。这些道路是双向的,且把所有的交叉路口直接或间接的连接起来了。每条道路都有一个分值,分值越小表示这个道路越繁忙,越需要进行改造。但是市政府的资金有限,市长希望进行改造的道路越少越好,于是他提出下面的要求: 97 | // 1.改造的那些道路能够把所有的交叉路口直接或间接的连通起来。 98 | // 2.在满足要求1的情况下,改造的道路尽量少。 99 | // 3.在满足要求1、2的情况下,改造的那些道路中分值最大的道路分值尽量小。 100 | // 任务:作为市规划局的你,应当作出最佳的决策,选择那些道路应当被修建。 101 | // 格式 102 | // 输入格式 103 | 104 | // 第一行有两个整数n,m表示城市有n个交叉路口,m条道路。接下来m行是对每条道路的描述,u, v, c表示交叉路口u和v之间有道路相连,分值为c。(1≤n≤300,1≤c≤10000) 105 | // 输出格式 106 | 107 | // 两个整数s, max,表示你选出了几条道路,分值最大的那条道路的分值是多少。 108 | // 样例1 109 | // 样例输入1[复制] 110 | 111 | // 4 5 112 | // 1 2 3 113 | // 1 4 5 114 | // 2 4 7 115 | // 2 3 6 116 | // 3 4 8 117 | // 样例输出1[复制] 118 | 119 | // 3 6 120 | // 限制 121 | // 每个测试点1s -------------------------------------------------------------------------------- /sources/network_flow_maximun_flow_Dinic.cpp: -------------------------------------------------------------------------------- 1 | // network flow 2 | // maximun flow 3 | // Dinic 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define min(x, y) (((x) < (y) ? (x) : (y))) 12 | 13 | using namespace std; 14 | 15 | int graph[250][250]; 16 | int level[250]; 17 | int n_node, n_edge; 18 | 19 | int mark_level() { 20 | memset(level, -1, sizeof(level)); 21 | queue to_visit; 22 | 23 | level[1] = 0; 24 | to_visit.push(1); 25 | while (!to_visit.empty()) { 26 | int cur = to_visit.front(); 27 | to_visit.pop(); 28 | for (int i = 1; i <= n_node; ++i) { 29 | if (graph[cur][i] != 0 && level[i] == -1) { 30 | level[i] = level[cur] + 1; 31 | to_visit.push(i); 32 | } 33 | } 34 | } 35 | 36 | if (level[n_node] == -1) 37 | return 0; // cannot reach the sink 38 | return 1; // can reach the sink 39 | } 40 | 41 | //int augment() { 42 | // // 43 | // // // not tested 44 | // // 45 | // int pre_node[n_node + 1]; 46 | // memset(pre_node, -1, sizeof(pre_node)); 47 | // 48 | // stack to_visit; 49 | // to_visit.push(1); 50 | // while (!to_visit.empty()) { 51 | // int cur = to_visit.top(); 52 | // to_visit.pop(); 53 | // for (int i = 1; i <= n_node; ++i) { 54 | // if (level[cur] + 1 == level[i]) { 55 | // pre_node[cur] = i; 56 | // to_visit.push(i); 57 | // if (i == n_node) { 58 | // pre_node[n_node] = i; 59 | // goto FOUND_THE_PATH; 60 | // } 61 | // } 62 | // } 63 | // } 64 | // 65 | // // found an augmented path 66 | // FOUND_THE_PATH: 67 | // int min_flow = LONG_MAX; 68 | // int cur = n_node; 69 | // int pre = pre_node[cur]; 70 | // while (pre != pre_node[cur]) { 71 | // if (graph[pre][cur] < min_flow) 72 | // min_flow = graph[pre][cur]; 73 | // } 74 | // cur = n_node; 75 | // pre = pre_node[cur]; 76 | // while (pre != pre_node[cur]) { 77 | // graph[pre][cur] -= min_flow; 78 | // graph[cur][pre] += min_flow; 79 | // } 80 | // return min_flow; 81 | //} 82 | 83 | int augment_recursive(int cur, int min_flow) { 84 | if (cur == n_node) 85 | return min_flow; 86 | 87 | int augmented_flow = 0; 88 | for (int i = 1; i <= n_node; ++i) { 89 | if (level[i] == level[cur] + 1 && graph[cur][i] > 0 && (augmented_flow = augment_recursive(i, min(graph[cur][i], min_flow)))) { 90 | graph[cur][i] -= augmented_flow; 91 | graph[i][cur] += augmented_flow; 92 | return augmented_flow; 93 | } 94 | } 95 | return 0; 96 | } 97 | 98 | int dinic() { 99 | int ans = 0; 100 | int temp = 0; 101 | while (mark_level()) 102 | while (temp = augment_recursive(1, INT_MAX)) 103 | ans += temp; 104 | return ans; 105 | } 106 | 107 | int main() { 108 | while (cin >> n_edge >> n_node) { 109 | memset(graph, 0, sizeof(graph)); 110 | 111 | int start_node, end_node, flow; 112 | for (int i = 0; i < n_edge; ++i) { 113 | cin >> start_node >> end_node >> flow; 114 | graph[start_node][end_node] += flow; // use "+" to combine !! 115 | } 116 | int ans = dinic(); 117 | cout << ans << endl; 118 | } 119 | } 120 | 121 | // Drainage Ditches 122 | // Time Limit: 1000MS Memory Limit: 10000K 123 | // Total Submissions: 56697 Accepted: 21784 124 | // Description 125 | 126 | // Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This means that the clover is covered by water for awhile and takes quite a long time to regrow. Thus, Farmer John has built a set of drainage ditches so that Bessie's clover patch is never covered in water. Instead, the water is drained to a nearby stream. Being an ace engineer, Farmer John has also installed regulators at the beginning of each ditch, so he can control at what rate water flows into that ditch. 127 | // Farmer John knows not only how many gallons of water each ditch can transport per minute but also the exact layout of the ditches, which feed out of the pond and into each other and stream in a potentially complex network. 128 | // Given all this information, determine the maximum rate at which water can be transported out of the pond and into the stream. For any given ditch, water flows in only one direction, but there might be a way that water can flow in a circle. 129 | // Input 130 | 131 | // The input includes several cases. For each case, the first line contains two space-separated integers, N (0 <= N <= 200) and M (2 <= M <= 200). N is the number of ditches that Farmer John has dug. M is the number of intersections points for those ditches. Intersection 1 is the pond. Intersection point M is the stream. Each of the following N lines contains three integers, Si, Ei, and Ci. Si and Ei (1 <= Si, Ei <= M) designate the intersections between which this ditch flows. Water will flow through this ditch from Si to Ei. Ci (0 <= Ci <= 10,000,000) is the maximum rate at which water will flow through the ditch. 132 | // Output 133 | 134 | // For each case, output a single integer, the maximum rate at which water may emptied from the pond. 135 | // Sample Input 136 | 137 | // 5 4 138 | // 1 2 40 139 | // 1 4 20 140 | // 2 4 20 141 | // 2 3 30 142 | // 3 4 10 143 | // Sample Output 144 | 145 | // 50 -------------------------------------------------------------------------------- /sources/point.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define GET_BIT(n, i) (((n) & (1 << ((i)-1))) >> ((i)-1)) // i start from 1 4 | #define SET_BIT(n, i) ((n) | (1 << ((i)-1))) 5 | #define CLR_BIT(n, i) ((n) & ~(1 << ((i)-1))) 6 | #define SHOW_A(x) {cout << #x << " = " << x << endl;} 7 | #define SHOW_B(x, y) {cout << #x << " = " << x << ", " << #y << " = " << y << endl;} 8 | #define SHOW_C(x, y, z) {cout << #x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl;} 9 | #define REACH_HERE {cout << "REACH_HERE! line: " << __LINE__ << endl;} 10 | #define ASSERT(x) { _assert(x); cout << #x << endl; } 11 | 12 | const double E = 1e-8; 13 | const double PI = acos(-1); 14 | 15 | using namespace std; 16 | 17 | int test = 0, pass = 0; 18 | 19 | void _assert(bool result) { 20 | test++; pass+=result; 21 | cout << (result ? "PASS: " : "FAIL: "); 22 | } 23 | 24 | struct point { 25 | int x, y; 26 | 27 | double length() { 28 | return sqrt(x*x + y*y); 29 | } 30 | 31 | long operator* (const point& b) { 32 | return x*b.y - y*b.x; 33 | } 34 | 35 | bool at_right_of(const point& a, const point& b) const { 36 | // a: relative point, b: base 37 | point vec_self = {x - b.x, y - b.y}; 38 | point vec_that = {a.x - b.x, a.y - b.y}; 39 | long product = vec_self * vec_that; 40 | if (product>0) return true; 41 | if (product==0 && vec_self.length()>vec_that.length()) return true; 42 | return false; 43 | } 44 | 45 | double to_point(const point& b) const { 46 | return sqrt(pow(x-b.x,2) + pow(y-b.y,2)); 47 | } 48 | 49 | double to_segment(const point& a, const point& b) const { 50 | double len_ab = a.to_point(b); 51 | if (abs(len_ab)1 || r<0) return min(to_point(a), to_point(b)); 54 | // projection of p is on extension of AB 55 | r = ((a.y - y)*(b.y - y) - (a.x - x)*(b.y - a.y))/pow(len_ab,2); 56 | return fabs(r*len_ab); 57 | } 58 | }; 59 | 60 | int main() { 61 | ios::sync_with_stdio(false); 62 | 63 | point a = {1, 1}; 64 | point b = {2, 2}; 65 | ASSERT(abs(a.to_point(b) - sqrt(2)) < E); 66 | ASSERT(a.at_right_of(b, (point){0,0}) == false) 67 | ASSERT(a.at_right_of((point){1,2}, (point){0,0}) == true) 68 | 69 | cout << "Passed: " << pass << " (" << 100.0*pass/test << "%%)" << endl; 70 | 71 | return 0; 72 | } -------------------------------------------------------------------------------- /sources/power_modulo.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | /* 14 | * n: number 15 | * i: LSB starting from 1 16 | */ 17 | #define SET_BIT(n, i) ((n) | (1 << ((i)-1))) 18 | #define CLR_BIT(n, i) ((n) & ~(1 << ((i)-1))) 19 | #define GET_BIT(n, i) (((n) & (1 << ((i)-1))) >> ((i)-1)) 20 | #define SHOW(x) {cout << #x << " = " << x << endl;} 21 | #define ASSERT(x) { assert(x); cout << #x << endl; } 22 | const double E = 1e-8; 23 | const double PI = acos(-1); 24 | 25 | using namespace std; 26 | int test = 0, pass = 0; 27 | 28 | void assert(bool result) { 29 | test++; pass+=result; 30 | cout << (result ? "PASS: " : "FAIL: "); 31 | } 32 | 33 | int power_modulo(int n, int p, int M) { // n ^ p % M 34 | int result = 1; 35 | while (p > 0) { 36 | if (p % 2 == 1) 37 | result = (result*n) % M; 38 | p /= 2; 39 | n = (n*n) % M; 40 | } 41 | return result; 42 | } 43 | 44 | int main() { 45 | ios::sync_with_stdio(false); 46 | 47 | ASSERT(power_modulo(2, 0, 10) == 1) 48 | ASSERT(power_modulo(2, 1, 10) == 2) 49 | ASSERT(power_modulo(2, 2, 10) == 4) 50 | ASSERT(power_modulo(2, 3, 10) == 8) 51 | ASSERT(power_modulo(2, 4, 10) == 6) 52 | 53 | cout << "Total test: " << test << endl; 54 | cout << "Passed: " << pass << " (" << 100.0*pass/test << "%%)" << endl; 55 | } -------------------------------------------------------------------------------- /sources/segment_tree.cc: -------------------------------------------------------------------------------- 1 | // Problem http://poj.org/problem?id=2777 2 | 3 | // Count Color 4 | // Time Limit: 1000MS Memory Limit: 65536K 5 | // Total Submissions: 36259 Accepted: 10943 6 | // Description 7 | 8 | // Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem. 9 | 10 | // There is a very long board with length L centimeter, L is a positive integer, so we can evenly divide the board into L segments, and they are labeled by 1, 2, ... L from left to right, each is 1 centimeter long. Now we have to color the board - one segment with only one color. We can do following two operations on the board: 11 | 12 | // 1. "C A B C" Color the board from segment A to segment B with color C. 13 | // 2. "P A B" Output the number of different colors painted between segment A and segment B (including). 14 | 15 | // In our daily life, we have very few words to describe a color (red, green, blue, yellow…), so you may assume that the total number of different colors T is very small. To make it simple, we express the names of colors as color 1, color 2, ... color T. At the beginning, the board was painted in color 1. Now the rest of problem is left to your. 16 | // Input 17 | 18 | // First line of input contains L (1 <= L <= 100000), T (1 <= T <= 30) and O (1 <= O <= 100000). Here O denotes the number of operations. Following O lines, each contains "C A B C" or "P A B" (here A, B, C are integers, and A may be larger than B) as an operation defined previously. 19 | // Output 20 | 21 | // Ouput results of the output operation in order, each line contains a number. 22 | // Sample Input 23 | 24 | // 2 2 4 25 | // C 1 1 2 26 | // P 1 2 27 | // C 2 2 2 28 | // P 1 2 29 | // Sample Output 30 | 31 | // 2 32 | // 1 33 | 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #define SET_BIT(n, i) ((n) | (1 << ((i)-1))) 47 | #define CLR_BIT(n, i) ((n) & ~(1 << ((i)-1))) 48 | #define GET_BIT(n, i) (((n) & (1 << ((i)-1))) >> ((i)-1)) 49 | #define SHOW(x) {cout << #x << " = " << x << endl;} 50 | 51 | using namespace std; 52 | 53 | // mainly copied from http://blog.sina.com.cn/s/blog_6635898a0100kzph.html 54 | 55 | const int MAX = 100000; 56 | 57 | struct node { 58 | int left, right; 59 | int color; 60 | bool cover; 61 | }; 62 | 63 | node nodes[3*MAX]; 64 | 65 | void build_tree(int left, int right, int u) { 66 | nodes[u].left = left; 67 | nodes[u].right = right; 68 | nodes[u].color = 1; 69 | nodes[u].cover = true; 70 | if (left == right) return; 71 | int mid = (left + right)/2; 72 | build_tree(left, mid, 2*u); 73 | build_tree(mid+1, right, 2*u + 1); 74 | } 75 | 76 | void get_down(int u) { 77 | int value = nodes[u].color; 78 | nodes[u].cover = false; 79 | nodes[2*u].color = value; 80 | nodes[2*u].cover = true; 81 | nodes[2*u + 1].color = value; 82 | nodes[2*u + 1].cover = true; 83 | } 84 | 85 | void update(int left, int right, int value, int u) { 86 | if (left <= nodes[u].left && nodes[u].right <= right) { 87 | nodes[u].color = value; 88 | nodes[u].cover = true; 89 | return; 90 | } 91 | if (nodes[u].color == value) return; // optimize purpose 92 | //SHOW(u); 93 | if (nodes[u].cover) get_down(u); 94 | if (left <= nodes[2*u].right) { 95 | update(left, right, value, 2*u); 96 | } 97 | if (right >= nodes[2*u+1].left) { 98 | update(left, right, value, 2*u + 1); 99 | } 100 | nodes[u].color = nodes[2*u].color | nodes[2*u+1].color; 101 | } 102 | 103 | void query(int left, int right, int &sum, int u) { 104 | if (nodes[u].cover) { 105 | sum |= nodes[u].color; 106 | return; 107 | } 108 | if (left <= nodes[u].left && nodes[u].right <= right) { 109 | sum |= nodes[u].color; 110 | return; 111 | } 112 | if (left <= nodes[2*u].right) { 113 | query(left, right, sum, 2*u); 114 | } 115 | if (right >= nodes[2*u+1].left) { 116 | query(left, right, sum, 2*u + 1); 117 | } 118 | } 119 | 120 | int bit_count(int sum) { 121 | int ans = 0; 122 | while (sum) { 123 | if (sum%2) ans++; 124 | sum = sum >> 1; 125 | } 126 | return ans; 127 | } 128 | 129 | int main() { 130 | ios::sync_with_stdio(false); 131 | 132 | int L, T, O; 133 | cin >> L >> T >> O; 134 | build_tree(1, L, 1); 135 | while (O--) { 136 | char op; 137 | int a, b, c; 138 | cin >> op; 139 | if (op == 'C') { 140 | cin >> a >> b >> c; 141 | if (a > b) swap(a, b); 142 | update(a, b, 1<<(c-1), 1); 143 | } else { 144 | cin >> a >> b; 145 | if (a > b) swap(a, b); 146 | int sum = 0; 147 | query(a, b, sum, 1); 148 | cout << bit_count(sum) << endl; 149 | } 150 | } 151 | 152 | return 0; 153 | } 154 | -------------------------------------------------------------------------------- /sources/segment_tree_2.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define GET_BIT(n, i) (((n) & (1 << ((i)-1))) >> ((i)-1)) // i start from 1 4 | #define SET_BIT(n, i) ((n) | (1 << ((i)-1))) 5 | #define CLR_BIT(n, i) ((n) & ~(1 << ((i)-1))) 6 | #define SHOW_A(x) {cout << #x << " = " << x << endl;} 7 | #define SHOW_B(x, y) {cout << #x << " = " << x << ", " << #y << " = " << y << endl;} 8 | #define SHOW_C(x, y, z) {cout << #x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl;} 9 | #define SHOW_D(x, y, z, m) {cout << #x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << ", " << #m << " = " << m << endl;} 10 | #define REACH_HERE {cout << "REACH_HERE! line: " << __LINE__ << endl;} 11 | 12 | const double E = 1e-8; 13 | const double PI = acos(-1); 14 | 15 | using namespace std; 16 | 17 | const int MAX = 30005; 18 | 19 | struct node { 20 | int left, right; 21 | long long sum; 22 | int lazy; 23 | bool dirty; 24 | }; 25 | 26 | node nodes[4*MAX]; 27 | 28 | void build_tree(int left, int right, int u) { 29 | nodes[u].left = left; 30 | nodes[u].right = right; 31 | nodes[u].sum = 0; 32 | nodes[u].lazy = 0; 33 | nodes[u].dirty = false; 34 | if (left == right) return; 35 | int mid = (left + right)/2; 36 | build_tree(left, mid, 2*u); 37 | build_tree(mid+1, right, 2*u + 1); 38 | } 39 | 40 | void get_down(int u) { 41 | if (!nodes[u].dirty) return; 42 | // SHOW_B(nodes[2*u].right, nodes[2*u].left) 43 | // SHOW_B(nodes[2*u+1].right, nodes[2*u+1].left) 44 | nodes[2*u].sum = (long long) nodes[u].lazy * (nodes[2*u].right - nodes[2*u].left + 1); 45 | nodes[2*u].lazy = nodes[u].lazy; 46 | nodes[2*u].dirty = true; 47 | nodes[2*u + 1].sum = (long long) nodes[u].lazy * (nodes[2*u + 1].right - nodes[2*u + 1].left + 1); 48 | nodes[2*u + 1].lazy = nodes[u].lazy; 49 | nodes[2*u + 1].dirty = true; 50 | nodes[u].dirty = false; 51 | } 52 | 53 | void update(int left, int right, int value, int u) { 54 | if (left <= nodes[u].left && nodes[u].right <= right) { 55 | // cout << "UPDATE "; 56 | // SHOW_D(value, u, nodes[u].left, nodes[u].right) 57 | nodes[u].sum = (long long)value * (nodes[u].right - nodes[u].left + 1); 58 | nodes[u].lazy = value; 59 | nodes[u].dirty = true; 60 | return; 61 | } 62 | //SHOW(u); 63 | get_down(u); 64 | if (left <= nodes[2*u].right) { 65 | update(left, right, value, 2*u); 66 | } 67 | if (right >= nodes[2*u+1].left) { 68 | update(left, right, value, 2*u + 1); 69 | } 70 | nodes[u].sum = nodes[2*u].sum + nodes[2*u+1].sum; 71 | // SHOW_A(u) 72 | // SHOW_C(nodes[2*u].sum, nodes[2*u].left, nodes[2*u].right) 73 | // SHOW_C(nodes[2*u+1].sum, nodes[2*u+1].left, nodes[2*u+1].right) 74 | // SHOW_D(nodes[u].sum, u, nodes[u].left, nodes[u].right) 75 | } 76 | 77 | void query(int left, int right, long long &sum, int u) { 78 | if (left <= nodes[u].left && nodes[u].right <= right) { 79 | sum += nodes[u].sum; 80 | // cout << "QUERY " ; 81 | // SHOW_D(left, right, sum, u) 82 | // SHOW_B(nodes[u].left, nodes[u].right) 83 | return; 84 | } 85 | get_down(u); 86 | if (left <= nodes[2*u].right) { 87 | query(left, right, sum, 2*u); 88 | } 89 | if (right >= nodes[2*u+1].left) { 90 | query(left, right, sum, 2*u + 1); 91 | } 92 | } 93 | 94 | long long round_down(long long a, int b) { 95 | if (a%b) { 96 | if (a > 0) return a/b; 97 | return a/b - 1; 98 | } else { 99 | return a/b; 100 | } 101 | } 102 | 103 | long long round_up(long long a, long long b) { 104 | if (a%b) { 105 | if (a > 0) return a/b + 1; 106 | return a/b; 107 | } else { 108 | return a/b; 109 | } 110 | } 111 | 112 | int main() { 113 | ios::sync_with_stdio(false); 114 | 115 | int n, m; 116 | 117 | while (cin >> n >> m) { 118 | long long ori_sum = 0; 119 | 120 | build_tree(1, n, 1); 121 | 122 | int v; 123 | 124 | for (int i = 0; i < n; i++) { 125 | cin >> v; 126 | ori_sum += v; 127 | update(i+1, i+1, v, 1); 128 | } 129 | 130 | int a, b; 131 | 132 | for (int i = 0; i < m; i++) { 133 | cin >> a >> b; 134 | 135 | if (a > b) swap(a, b); 136 | 137 | long long sum = 0; 138 | long long whole_sume = 0; 139 | 140 | query(a, b, sum, 1); 141 | query(1, n, whole_sume, 1); 142 | 143 | // SHOW_C(a, b, sum); 144 | 145 | if (whole_sume > ori_sum) { 146 | // round down 147 | // cout << "down" << endl; 148 | // SHOW_A(sum / (b - a + 1)) 149 | update(a, b, round_down(sum, (b - a + 1)), 1); 150 | } else { 151 | // cout << "up" << endl; 152 | // round up 153 | update(a, b, round_up(sum, (b - a + 1)), 1); 154 | } 155 | } 156 | 157 | for (int i = 0; i < n; i++) { 158 | long long sum = 0; 159 | query(i+1, i+1, sum, 1); 160 | cout << sum; 161 | if (i != n-1) cout << " "; 162 | } 163 | 164 | cout << endl; 165 | cout << endl; 166 | } 167 | 168 | return 0; 169 | } -------------------------------------------------------------------------------- /sources/strings.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() { 8 | /* C++ String */ 9 | string a; 10 | cin >> a; 11 | cout << "[C++] You have input \"" << a << "\", " 12 | << ", whose length is " << a.length() << endl; 13 | 14 | char b[10]; 15 | gets(b); 16 | cout << "[C] You have input \"" << b << "\", " 17 | << ", whose length is " << strlen(b) << endl; 18 | 19 | return 0; 20 | } -------------------------------------------------------------------------------- /sources/strings.in: -------------------------------------------------------------------------------- 1 | hello world 2 | new line 3 | -------------------------------------------------------------------------------- /sources/struct.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | /* 14 | * n: number 15 | * i: LSB starting from 1 16 | */ 17 | #define SET_BIT(n, i) ((n) | (1 << ((i)-1))) 18 | #define CLR_BIT(n, i) ((n) & ~(1 << ((i)-1))) 19 | #define GET_BIT(n, i) (((n) & (1 << ((i)-1))) >> ((i)-1)) 20 | #define SHOW(x) {cout << #x << " = " << x << endl;} 21 | #define ASSERT(x) { assert(x); cout << #x << endl; } 22 | const double E = 1e-8; 23 | const double PI = acos(-1); 24 | 25 | using namespace std; 26 | 27 | struct HHH { 28 | int a; 29 | // bool operator==(HHH that) { 30 | // return this->a == that.a; 31 | // } 32 | // bool operator==(const HHH that) { 33 | // return this->a == that.a; 34 | // } 35 | bool operator==(HHH& that) { 36 | return this->a == that.a; 37 | } 38 | // bool operator==(const HHH& that) { 39 | // return this->a == that.a; 40 | // } 41 | }; 42 | 43 | int main() { 44 | ios::sync_with_stdio(false); 45 | 46 | HHH a = {1}; 47 | HHH b = {2}; 48 | if (a == b) 49 | cout << "yes" << endl; 50 | else 51 | cout << "no" << endl; 52 | } -------------------------------------------------------------------------------- /sources/teamplate.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define GET_BIT(n, i) (((n) & (1 << ((i)-1))) >> ((i)-1)) // i start from 1 4 | #define SET_BIT(n, i) ((n) | (1 << ((i)-1))) 5 | #define CLR_BIT(n, i) ((n) & ~(1 << ((i)-1))) 6 | #define SHOW_A(x) {cout << #x << " = " << x << endl;} 7 | #define SHOW_B(x, y) {cout << #x << " = " << x << ", " << #y << " = " << y << endl;} 8 | #define SHOW_C(x, y, z) {cout << #x << " = " << x << ", " << #y << " = " << y << ", " << #z << " = " << z << endl;} 9 | #define REACH_HERE {cout << "REACH_HERE! line: " << __LINE__ << endl;} 10 | #define ASSERT(x) { _assert(x); cout << #x << endl; } 11 | 12 | const double E = 1e-8; 13 | const double PI = acos(-1); 14 | 15 | using namespace std; 16 | 17 | int test = 0, pass = 0; 18 | 19 | void _assert(bool result) { 20 | test++; pass+=result; 21 | cout << (result ? "PASS: " : "FAIL: "); 22 | } 23 | 24 | 25 | int main() { 26 | ios::sync_with_stdio(false); 27 | 28 | int x = 0; 29 | ASSERT(x==0) 30 | ASSERT((x = SET_BIT(x, 3))==4) 31 | ASSERT((x = CLR_BIT(x, 3))==0) 32 | 33 | cout << "Total test: " << test << endl; 34 | cout << "Passed: " << pass << " (" << 100.0*pass/test << "%%)" << endl; 35 | 36 | return 0; 37 | } -------------------------------------------------------------------------------- /sources/vector.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | vector vt; 8 | vt.push_back(1); 9 | vt.push_back(2); 10 | vt.push_back(3); 11 | vt.push_back(4); 12 | 13 | for (vector::iterator it = vt.begin(); it != vt.end(); it++) { 14 | cout << *it << endl; 15 | } 16 | 17 | cout << vt[2] << endl; 18 | 19 | return 0; 20 | } -------------------------------------------------------------------------------- /theoretical_computer_science_cheat_sheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntuorangejuice/cheat-sheet/bbacdab80b202d905c344ac2fd764995dd6fbead/theoretical_computer_science_cheat_sheet.pdf --------------------------------------------------------------------------------