├── .github └── workflows │ └── build.yml ├── 0-IO.md ├── 1-Structure.md ├── 2-Graph.md ├── 3-String.md ├── 4-Math.md ├── 5-Geometry.md ├── 6-Misc.md ├── 9-Unverified.md ├── LICENSE ├── README.md ├── header ├── Header-Book.md └── Header-non-Book.md └── mkdocs.yml /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - run: | 15 | cat header/Header-Book.md [0-9]*.md > book.md 16 | cat header/Header-non-Book.md [0-9]*.md > non-book.md 17 | - uses: docker://pandoc/latex:latest 18 | with: 19 | entrypoint: /bin/sh 20 | args: | 21 | -c "wget https://github.com/Wandmalfarbe/pandoc-latex-template/releases/download/v2.0.0/Eisvogel-2.0.0.tar.gz && 22 | tar xvzf Eisvogel-2.0.0.tar.gz && 23 | mkdir -p ~/.pandoc/templates/ && 24 | cp eisvogel.latex ~/.pandoc/templates/eisvogel.latex && 25 | apk --update add font-noto font-noto-cjk font-noto-cjk-extra ttf-dejavu && 26 | tlmgr update --self && 27 | tlmgr install ctex fvextra footnotebackref mdframed zref needspace titling pagecolor sourcesanspro sourcecodepro koma-script dejavu lineno && 28 | mkdir output && 29 | pandoc --output=output/book.pdf book.md --shift-heading-level-by=-1 --metadata date=\"`date -u '+%Y-%m-%d'`($GITHUB_SHA)\" --template eisvogel --highlight-style kate --pdf-engine=xelatex && 30 | pandoc --output=output/non-book.pdf non-book.md --shift-heading-level-by=-1 --metadata date=\"`date -u '+%Y-%m-%d'`($GITHUB_SHA)\" --template eisvogel --highlight-style kate --pdf-engine=xelatex 31 | " 32 | - uses: actions/upload-artifact@master 33 | with: 34 | name: output 35 | path: output 36 | -------------------------------------------------------------------------------- /0-IO.md: -------------------------------------------------------------------------------- 1 | ## Input & Output 2 | 3 | ### Setup 4 | 5 | ```cpp 6 | #include 7 | 8 | using namespace std; 9 | 10 | using i64 = long long; 11 | 12 | int main() { 13 | ios::sync_with_stdio(false); 14 | cin.tie(nullptr); 15 | 16 | return 0; 17 | } 18 | ``` 19 | 20 | ### Debug 21 | 22 | ```cpp 23 | // Heltion 24 | template ::value> 25 | string to_debug(T, string s = "") 26 | requires(!ranges::range); 27 | string to_debug(auto x) 28 | requires requires(ostream &os) { os << x; } 29 | { 30 | return static_cast(ostringstream() << x).str(); 31 | } 32 | string to_debug(ranges::range auto x, string s = "") 33 | requires(!is_same_v) 34 | { 35 | for (auto xi : x) s += ", " + to_debug(xi); 36 | return "[" + s.substr(s.empty() ? 0 : 2) + "]"; 37 | } 38 | template 39 | string to_debug(T x, string s) 40 | requires(!ranges::range) 41 | { 42 | [&](index_sequence) { ((s += ", " + to_debug(get(x))), ...); }(make_index_sequence()); 43 | return "(" + s.substr(s.empty() ? 0 : 2) + ")"; 44 | } 45 | #define dbg(x...) ([&] { cerr << __FILE__ ":" << __LINE__ << ": (" #x ") = " << to_debug(tuple(x)) << "\n"; }()) 46 | ``` 47 | 48 | ### Special Formats 49 | 50 | ```cpp 51 | cout << fixed << setprecision(15); // 15 decimal places 52 | 53 | format("{:04d}-{:02d}-{:02d}", y, m, d) // 0001-01-01 54 | ``` 55 | 56 | ### File I/O 57 | 58 | ```cpp 59 | freopen("in.txt", "r", stdin); 60 | freopen("out.txt", "w", stdout); 61 | ``` 62 | 63 | ### Timing 64 | 65 | ```cpp 66 | (double)clock() / CLOCKS_PER_SEC 67 | ``` 68 | 69 | ### Read a Line 70 | 71 | ```cpp 72 | getline(cin, s) 73 | ``` 74 | 75 | ### Read Until End of File 76 | 77 | ```cpp 78 | while (cin) {} 79 | ``` 80 | 81 | ### int128 82 | 83 | ```cpp 84 | // Need to test if usable 85 | istream& operator>>(istream& is, __int128& x) { 86 | string s; 87 | is >> s; 88 | x = 0; 89 | for (char c : s) { 90 | if (c == '-') continue; 91 | x = x * 10 + c - '0'; 92 | } 93 | if (s[0] == '-') x = -x; 94 | return is; 95 | } 96 | 97 | ostream& operator<<(ostream& os, __int128 x) { 98 | if (x < 0) os << '-', x = -x; 99 | if (x > 9) os << x / 10; 100 | os << char(x % 10 + '0'); 101 | return os; 102 | } 103 | ``` 104 | 105 | ### Fast Input 106 | 107 | ```cpp 108 | class Scanner { 109 | #ifdef qdd 110 | static constexpr int BUF_SIZE = 1; 111 | #else 112 | static constexpr int BUF_SIZE = 1048576; // 1MB 113 | #endif 114 | 115 | char buf[BUF_SIZE], *p1 = buf, *p2 = buf; 116 | 117 | char nc() { 118 | if (p1 == p2) { 119 | p1 = buf; p2 = buf + fread(buf, 1, BUF_SIZE, stdin); 120 | // assert(p1 != p2); 121 | } 122 | return p1 == p2 ? EOF : *p1++; 123 | } 124 | 125 | public: 126 | Scanner& operator>>(string& s) { 127 | s.clear(); 128 | char c = nc(); 129 | while (c <= 32) c = nc(); 130 | for (; c > 32; c = nc()) s += c; 131 | return *this; 132 | } 133 | 134 | Scanner& operator>>(int& x) { 135 | x = 0; 136 | int sgn = 1; 137 | char c = nc(); 138 | for (; c < '0' || c > '9'; c = nc()) if (c == '-') sgn = -1; 139 | for (; c >= '0' && c <= '9'; c = nc()) x = x * 10 + (c - '0'); 140 | return x *= sgn, *this; 141 | } 142 | 143 | Scanner& operator>>(double& x) { 144 | x = 0; 145 | double base = 0.1; 146 | int sgn = 1; 147 | char c = nc(); 148 | for (; c < '0' || c > '9'; c = nc()) if (c == '-') sgn = -1; 149 | for (; c >= '0' && c <= '9'; c = nc()) x = x * 10 + (c - '0'); 150 | for (; c < '0' || c > '9'; c = nc()) if (c != '.') return x *= sgn, *this; 151 | for (; c >= '0' && c <= '9'; c = nc()) x += base * (c - '0'), base *= 0.1; 152 | return x *= sgn, *this; 153 | } 154 | } in; 155 | ``` 156 | -------------------------------------------------------------------------------- /1-Structure.md: -------------------------------------------------------------------------------- 1 | ## Data Structures 2 | 3 | **Unless specified, all data structure interfaces are 0-indexed, [l, r]** 4 | 5 | ### Disjoint Set Union (DSU) 6 | 7 | ```cpp 8 | struct dsu { 9 | vector p; 10 | dsu(int n) : p(n, -1) {} 11 | int find(int x) { return (p[x] < 0) ? x : p[x] = find(p[x]); } 12 | bool merge(int x, int y) { 13 | x = find(x), y = find(y); 14 | if (x == y) return 0; 15 | p[y] += p[x]; 16 | p[x] = y; 17 | return 1; 18 | } 19 | }; 20 | ``` 21 | 22 | + Dynamic Allocation DSU 23 | 24 | ```cpp 25 | struct dsu { 26 | unordered_map p; 27 | int data(int x) { 28 | auto it = p.find(x); 29 | return it == p.end() ? p[x] = -1 : it->second; 30 | } 31 | int find(int x) { 32 | int n = data(x); 33 | return n < 0 ? x : p[x] = find(n); 34 | } 35 | bool merge(int x, int y) { 36 | x = find(x), y = find(y); 37 | if (x == y) return 0; 38 | auto itx = p.find(x), ity = p.find(y); 39 | if (itx->second > ity->second) swap(itx, ity), swap(x, y); 40 | itx->second += ity->second; 41 | ity->second = x; 42 | return 1; 43 | } 44 | }; 45 | ``` 46 | 47 | + Rollback DSU 48 | 49 | ```cpp 50 | struct dsu { 51 | vector p, sz, undo; 52 | dsu(int n) : p(n, -1), sz(n, 1) {} 53 | int find(int x) { return (p[x] < 0) ? x : find(p[x]); } 54 | bool merge(int x, int y) { 55 | x = find(x), y = find(y); 56 | if (x == y) return 0; 57 | if (sz[x] > sz[y]) swap(x, y); 58 | undo.push_back(x); 59 | sz[y] += sz[x]; 60 | p[x] = y; 61 | return 1; 62 | } 63 | void rollback() { 64 | int x = undo.back(); 65 | undo.pop_back(); 66 | sz[p[x]] -= sz[x]; 67 | p[x] = -1; 68 | } 69 | }; 70 | ``` 71 | 72 | ### Sparse Table 73 | 74 | + 1D 75 | 76 | ```cpp 77 | struct SparseTable { 78 | vector> st; 79 | 80 | SparseTable(const vector& a) { 81 | int n = a.size(); 82 | st.assign(__lg(n) + 1, vector(n)); 83 | for (int i = 0; i < n; i++) { 84 | st[0][i] = a[i]; 85 | } 86 | for (int k = 1; (1 << k) <= n; k++) { 87 | for (int i = 0; i + (1 << k) <= n; i++) { 88 | st[k][i] = max(st[k - 1][i], st[k - 1][i + (1 << (k - 1))]); 89 | } 90 | } 91 | } 92 | 93 | int query(int l, int r) { 94 | int k = __lg(r - l + 1); 95 | return max(st[k][l], st[k][r - (1 << k) + 1]); 96 | } 97 | }; 98 | ``` 99 | 100 | + 2D 101 | 102 | ```cpp 103 | struct SparseTable { 104 | int st[11][11][N][N]; // 11 = ((int)log2(N) + 1) 105 | 106 | void init(int n, int m) { 107 | for (int i = 0; i < n; i++) { 108 | for (int j = 0; j < m; j++) { 109 | st[0][0][i][j] = a[i][j]; 110 | } 111 | } 112 | for (int i = 0; (1 << i) <= n; i++) { 113 | for (int j = 0; (1 << j) <= m; j++) { 114 | if (i == 0 && j == 0) continue; 115 | for (int r = 0; r + (1 << i) - 1 < n; r++) { 116 | for (int c = 0; c + (1 << j) - 1 < m; c++) { 117 | if (i == 0) { 118 | st[i][j][r][c] = max(st[i][j - 1][r][c], st[i][j - 1][r][c + (1 << (j - 1))]); 119 | } else { 120 | st[i][j][r][c] = max(st[i - 1][j][r][c], st[i - 1][j][r + (1 << (i - 1))][c]); 121 | } 122 | } 123 | } 124 | } 125 | } 126 | } 127 | 128 | int query(int r1, int c1, int r2, int c2) { 129 | int x = __lg(r2 - r1 + 1); 130 | int y = __lg(c2 - c1 + 1); 131 | int m1 = st[x][y][r1][c1]; 132 | int m2 = st[x][y][r1][c2 - (1 << y) + 1]; 133 | int m3 = st[x][y][r2 - (1 << x) + 1][c1]; 134 | int m4 = st[x][y][r2 - (1 << x) + 1][c2 - (1 << y) + 1]; 135 | return max({m1, m2, m3, m4}); 136 | } 137 | }; 138 | ``` 139 | 140 | + Sliding Window RMQ 141 | 142 | ```cpp 143 | // k is the size of the sliding window 144 | deque q; 145 | for (int i = 0, j = 0; i + k <= n; i++) { 146 | while (j < i + k) { 147 | while (!q.empty() && a[q.back()] < a[j]) q.pop_back(); // Change '<' to '>' for minimum 148 | q.push_back(j++); 149 | } 150 | while (q.front() < i) q.pop_front(); 151 | rmq.push_back(a[q.front()]); 152 | } 153 | ``` 154 | 155 | ### Fenwick Tree (Binary Indexed Tree) 156 | 157 | + Point Update, Range Sum 158 | 159 | ```cpp 160 | template 161 | struct fenwick { 162 | int n; 163 | vector t; 164 | fenwick(int n) : n(n), t(n) {} 165 | void add(int p, T x) { 166 | // assert(0 <= p && p < n); 167 | for (; p < n; p |= p + 1) t[p] += x; 168 | } 169 | T sum(int p) { 170 | T ans = 0; 171 | for (; p >= 0; p = (p & (p + 1)) - 1) ans += t[p]; 172 | return ans; 173 | } 174 | void set(int p, T x) { add(p, x - range_sum(p, p)); } 175 | T range_sum(int l, int r) { return sum(r) - sum(l - 1); } 176 | 177 | // smallest is 0-th 178 | int kth(T k) { 179 | int p = 0; 180 | for (int i = 1 << __lg(n); i; i /= 2) { 181 | if (p + i <= n && k >= t[p + i - 1]) { 182 | p += i; 183 | k -= t[p - 1]; 184 | } 185 | } 186 | return p; 187 | } 188 | }; 189 | ``` 190 | 191 | + Range Add, Point Query 192 | 193 | ```cpp 194 | void range_add(int l, int r, i64 x) { 195 | add(l, x); 196 | add(r + 1, -x); 197 | } 198 | ``` 199 | 200 | + Range Add, Range Sum 201 | 202 | ```cpp 203 | template 204 | struct fenwick_range { 205 | fenwick t0, t1; 206 | fenwick_range(int n) : t0(n), t1(n) {} 207 | void range_add(int l, int r, T x) { 208 | t0.add(l, x); 209 | t1.add(l, l * x); 210 | t0.add(r + 1, -x); 211 | t1.add(r + 1, (r + 1) * -x); 212 | } 213 | T range_sum(int l, int r) { 214 | return (r + 1) * t0.sum(r) - t1.sum(r) - l * t0.sum(l - 1) + t1.sum(l - 1); 215 | } 216 | }; 217 | ``` 218 | 219 | + 2D 220 | 221 | ```cpp 222 | template 223 | struct fenwick_2d { 224 | int n, m; 225 | vector> t; 226 | fenwick_2d(int n, int m) : n(n), m(m), t(n, vector(m)) {} 227 | void add(int x, int y, T d) { 228 | for (int i = x; i < n; i |= i + 1) 229 | for (int j = y; j < m; j |= j + 1) t[i][j] += d; 230 | } 231 | T sum(int x, int y) { 232 | T ans = 0; 233 | for (int i = x; i >= 0; i = (i & (i + 1)) - 1) 234 | for (int j = y; j >= 0; j = (j & (j + 1)) - 1) ans += t[i][j]; 235 | return ans; 236 | } 237 | T range_sum(int x, int y, int xx, int yy) { 238 | return sum(xx, yy) - sum(x - 1, yy) - sum(xx, y - 1) + sum(x - 1, y - 1); 239 | } 240 | }; 241 | ``` 242 | 243 | + 2D Range Add, Range Sum 244 | 245 | ```cpp 246 | template 247 | struct fenwick_range_2d { 248 | int n, m; 249 | fenwick_2d t0, t1, t2, t3; 250 | fenwick_range_2d(int n, int m) : n(n), m(m), t0(n, m), t1(n, m), t2(n, m), t3(n, m) {} 251 | void range_add(int x, int y, int xx, int yy, T d) { 252 | add4(x, y, d); 253 | add4(x, yy + 1, -d); 254 | add4(xx + 1, y, -d); 255 | add4(xx + 1, yy + 1, d); 256 | } 257 | T range_sum(int x, int y, int xx, int yy) { 258 | return sum4(xx, yy) - sum4(x - 1, yy) - sum4(xx, y - 1) + sum4(x - 1, y - 1); 259 | } 260 | 261 | private: 262 | void add4(int x, int y, T d) { 263 | t0.add(x, y, d); 264 | t1.add(x, y, d * x); 265 | t2.add(x, y, d * y); 266 | t3.add(x, y, d * x * y); 267 | } 268 | T sum4(int x, int y) { 269 | return (x + 1) * (y + 1) * t0.sum(x, y) 270 | - (y + 1) * t1.sum(x, y) 271 | - (x + 1) * t2.sum(x, y) 272 | + t3.sum(x, y); 273 | } 274 | }; 275 | ``` 276 | 277 | ### Segment Tree 278 | 279 | + ZKW Segment Tree 280 | 281 | ```cpp 282 | struct segt { 283 | using S = int; 284 | 285 | S op(S a, S b) { return max(a, b); } 286 | S e() { return (int)-2e9; } 287 | 288 | int n; 289 | vector d; 290 | segt(int n) : n(n), d(2 * n, e()) {} 291 | 292 | void set(int p, S x) { 293 | for (d[p += n] = x; p > 1; p /= 2) { 294 | d[p / 2] = op(d[p], d[p ^ 1]); 295 | } 296 | } 297 | 298 | S query(int l, int r) { 299 | S lp = e(), rp = e(); 300 | for (l += n, r += n + 1; l < r; l /= 2, r /= 2) { 301 | if (l & 1) lp = op(lp, d[l++]); 302 | if (r & 1) rp = op(d[--r], rp); 303 | } 304 | return op(lp, rp); 305 | } 306 | }; 307 | ``` 308 | 309 | + Point Update, Range Max 310 | 311 | ```cpp 312 | // Use const S& when necessary to optimize constants 313 | template 314 | struct segtree { 315 | using OP = function; 316 | using E = function; 317 | 318 | int _n, size; 319 | vector d; 320 | 321 | const OP op; 322 | const E e; 323 | 324 | segtree(int n, OP op, E e) : _n(n), op(op), e(e) { 325 | size = 1; 326 | while (size < n) size <<= 1; 327 | d.assign(2 * size, e()); 328 | } 329 | 330 | segtree(const vector& v, OP op, E e) : segtree(v.size(), op, e) { 331 | copy(v.begin(), v.end(), d.begin() + size); 332 | for (int i = size - 1; i >= 1; i--) pull(i); 333 | } 334 | 335 | vector operator()() const { return vector(d.begin() + size, d.begin() + size + _n); } 336 | 337 | void pull(int p) { d[p] = op(d[p * 2], d[p * 2 + 1]); } 338 | 339 | void set(int p, S x) { 340 | p += size; 341 | d[p] = x; 342 | for (p >>= 1; p > 0; p >>= 1) pull(p); 343 | } 344 | 345 | S query(int l, int r) { 346 | S lp = e(), rp = e(); 347 | for (l += size, r += size + 1; l < r; l >>= 1, r >>= 1) { 348 | if (l & 1) lp = op(lp, d[l++]); 349 | if (r & 1) rp = op(d[--r], rp); 350 | } 351 | return op(lp, rp); 352 | } 353 | 354 | S operator[](int i) { return d[i + size]; } 355 | 356 | // f(e()) = false 357 | // find the smallest r such that f(sum([l...r])) = true 358 | template 359 | int find_right(int l, F f) { 360 | l += size; 361 | S s = e(); 362 | do { 363 | while (l % 2 == 0) l >>= 1; 364 | if (f(op(s, d[l]))) { 365 | while (l < size) { 366 | l *= 2; 367 | if (!f(op(s, d[l]))) { 368 | s = op(s, d[l]); 369 | l++; 370 | } 371 | } 372 | return l - size; 373 | } 374 | s = op(s, d[l]); 375 | l++; 376 | } while ((l & -l) != l); 377 | return _n; 378 | } 379 | 380 | // find the largest l such that f(sum([l...r])) = true 381 | template 382 | int find_left(int r, F f) { 383 | r += size + 1; 384 | S s = e(); 385 | do { 386 | r--; 387 | while (r > 1 && (r % 2)) r >>= 1; 388 | if (f(op(d[r], s))) { 389 | while (r < size) { 390 | r = 2 * r + 1; 391 | if (!f(op(d[r], s))) { 392 | s = op(d[r], s); 393 | r--; 394 | } 395 | } 396 | return r - size; 397 | } 398 | s = op(d[r], s); 399 | } while ((r & -r) != r); 400 | return -1; 401 | } 402 | }; 403 | 404 | auto op = [](int a, int b) { return max(a, b); }; 405 | auto e = []() { return (int)-2e9; }; 406 | 407 | segtree st(n, op, e); 408 | ``` 409 | 410 | + Range Add, Range Sum 411 | 412 | ```cpp 413 | template 414 | struct lazy_segtree { 415 | using OP = function; 416 | using E = function; 417 | using MAP = function; 418 | using COM = function; 419 | using ID = function; 420 | 421 | int _n, size, log; 422 | vector d; 423 | vector lz; 424 | 425 | const OP op; 426 | const E e; 427 | const MAP mapping; 428 | const COM composition; 429 | const ID id; 430 | 431 | lazy_segtree(int n, OP op, E e, MAP mapping, COM composition, ID id) 432 | : _n(n), op(op), e(e), mapping(mapping), composition(composition), id(id) { 433 | size = 1, log = 0; 434 | while (size < n) size <<= 1, log++; 435 | d.assign(2 * size, e()); 436 | lz.assign(size, id()); 437 | } 438 | 439 | lazy_segtree(const vector& v, OP op, E e, MAP mapping, COM composition, ID id) 440 | : lazy_segtree(v.size(), op, e, mapping, composition, id) { 441 | copy(v.begin(), v.end(), d.begin() + size); 442 | for (int i = size - 1; i >= 1; i--) pull(i); 443 | } 444 | 445 | vector operator()() const { 446 | lazy_segtree cp = *this; 447 | for (int i = 1; i < size; i++) cp.push(i); 448 | return vector(cp.d.begin() + size, cp.d.begin() + size + _n); 449 | } 450 | 451 | void pull(int p) { d[p] = op(d[p * 2], d[p * 2 + 1]); } 452 | 453 | void apply(T t, int p) { 454 | d[p] = mapping(d[p], t); 455 | if (p < size) lz[p] = composition(t, lz[p]); 456 | } 457 | 458 | void push(int p) { 459 | if (lz[p] == id()) return; 460 | apply(lz[p], p * 2); 461 | apply(lz[p], p * 2 + 1); 462 | lz[p] = id(); 463 | } 464 | 465 | void set(int p, S x) { 466 | p += size; 467 | for (int i = log; i >= 1; i--) push(p >> i); 468 | d[p] = x; 469 | for (int i = 1; i <= log; i++) pull(p >> i); 470 | } 471 | 472 | void update(int l, int r, T t) { 473 | function rec = [&](int p, int x, int y) { 474 | if (l > y || r < x) return; 475 | if (l <= x && r >= y) { 476 | apply(t, p); 477 | return; 478 | } 479 | push(p); 480 | int z = (x + y) >> 1; 481 | rec(p * 2, x, z); 482 | rec(p * 2 + 1, z + 1, y); 483 | pull(p); 484 | }; 485 | rec(1, 0, size - 1); 486 | } 487 | 488 | S query(int l, int r) { 489 | function rec = [&](int p, int x, int y) -> S { 490 | if (l > y || r < x) return e(); 491 | if (l <= x && r >= y) return d[p]; 492 | push(p); 493 | int z = (x + y) >> 1; 494 | return op(rec(p * 2, x, z), rec(p * 2 + 1, z + 1, y)); 495 | }; 496 | return rec(1, 0, size - 1); 497 | } 498 | 499 | S operator[](int i) { return query(i, i); } 500 | 501 | // f(e()) = false 502 | // find the smallest r such that f(sum([l...r])) = true 503 | template 504 | int find_right(int l, F f) { 505 | l += size; 506 | for (int i = log; i >= 1; i--) push(l >> i); 507 | S s = e(); 508 | do { 509 | while (l % 2 == 0) l >>= 1; 510 | if (f(op(s, d[l]))) { 511 | while (l < size) { 512 | push(l); 513 | l *= 2; 514 | if (!f(op(s, d[l]))) { 515 | s = op(s, d[l]); 516 | l++; 517 | } 518 | } 519 | return l - size; 520 | } 521 | s = op(s, d[l]); 522 | l++; 523 | } while ((l & -l) != l); 524 | return _n; 525 | } 526 | 527 | // find the largest l such that f(sum([l...r])) = true 528 | template 529 | int find_left(int r, F f) { 530 | r += size + 1; 531 | for (int i = log; i >= 1; i--) push((r - 1) >> i); 532 | S s = e(); 533 | do { 534 | r--; 535 | while (r > 1 && (r % 2)) r >>= 1; 536 | if (f(op(d[r], s))) { 537 | while (r < size) { 538 | push(r); 539 | r = 2 * r + 1; 540 | if (!f(op(d[r], s))) { 541 | s = op(d[r], s); 542 | r--; 543 | } 544 | } 545 | return r - size; 546 | } 547 | s = op(d[r], s); 548 | } while ((r & -r) != r); 549 | return -1; 550 | } 551 | }; 552 | 553 | struct Info { 554 | i64 sum, len; 555 | }; 556 | 557 | auto op = [](Info a, Info b) { return Info{a.sum + b.sum, a.len + b.len}; }; 558 | auto e = []() { return Info{0LL, 0LL}; }; 559 | auto mapping = [](Info a, i64 f) { return Info{a.sum + a.len * f, a.len}; }; 560 | auto composition = [](i64 f, i64 g) { return f + g; }; // f(g()) 561 | auto id = []() { return 0LL; }; // For range assignment, choose a value outside the data range 562 | 563 | lazy_segtree st(vector(n, Info{0LL, 1LL}), op, e, mapping, composition, id); 564 | ``` 565 | 566 | + Range Affine, Range Sum 567 | 568 | ```cpp 569 | const i64 md = 1e9 + 7; 570 | 571 | struct Info { 572 | i64 sum, len; 573 | }; 574 | 575 | struct Tag { 576 | i64 mul, add; 577 | 578 | bool operator==(const Tag& t) const { return mul == t.mul && add == t.add; } 579 | }; 580 | 581 | auto op = [](Info a, Info b) { return Info{(a.sum + b.sum) % md, a.len + b.len}; }; 582 | auto e = []() { return Info{0, 0}; }; 583 | auto mapping = [](Info a, Tag t) { return Info{(a.sum * t.mul + a.len * t.add) % md, a.len}; }; 584 | auto composition = [](Tag f, Tag g) { return Tag{(f.mul * g.mul) % md, (f.mul * g.add + f.add) % md}; }; 585 | auto id = []() { return Tag{1, 0}; }; 586 | ``` 587 | 588 | ### Functional Segment Tree 589 | 590 | ```cpp 591 | struct Node { 592 | int lc, rc, val; 593 | Node(int lc = 0, int rc = 0, int val = 0) : lc(lc), rc(rc), val(val) {} 594 | } t[40 * MAXN]; // Be careful with MLE: (4 + log(size)) * MAXN 595 | 596 | int cnt; 597 | 598 | struct FST { 599 | #define mid ((pl + pr) >> 1) 600 | 601 | int size; 602 | vector root; 603 | 604 | FST(int sz) { 605 | size = 1; 606 | while (size < sz) size <<= 1; 607 | root.push_back(N(0, 0, 0)); 608 | } 609 | 610 | int N(int lc, int rc, int val) { 611 | t[cnt] = Node(lc, rc, val); 612 | return cnt++; 613 | } 614 | 615 | int ins(int p, int pl, int pr, int x) { 616 | if (pl > x || pr < x) return p; 617 | if (pl == pr) return N(0, 0, t[p].val + 1); 618 | return N(ins(t[p].lc, pl, mid, x), ins(t[p].rc, mid + 1, pr, x), t[p].val + 1); 619 | } 620 | 621 | int ask(int p1, int p2, int pl, int pr, int k) { 622 | if (pl == pr) return pl; 623 | i64 vl = t[t[p2].lc].val - t[t[p1].lc].val; 624 | if (k <= vl) return ask(t[p1].lc, t[p2].lc, pl, mid, k); 625 | return ask(t[p1].rc, t[p2].rc, mid + 1, pr, k - vl); 626 | } 627 | 628 | void add(int x) { 629 | root.push_back(ins(root.back(), 0, size - 1, x)); 630 | } 631 | 632 | int query(int l, int r, int k) { 633 | return ask(root[l - 1], root[r], 0, size - 1, k); 634 | } 635 | 636 | #undef mid 637 | }; 638 | ``` 639 | 640 | ### pb_ds 641 | 642 | ```cpp 643 | // Balanced Tree 644 | #include 645 | using namespace __gnu_pbds; 646 | template 647 | using rank_set = tree, rb_tree_tag, tree_order_statistics_node_update>; 648 | template 649 | using rank_map = tree, rb_tree_tag, tree_order_statistics_node_update>; 650 | 651 | void example() { 652 | rank_set t, t2; 653 | t.insert(8); 654 | auto it = t.insert(10).first; 655 | assert(it == t.lower_bound(9)); 656 | assert(t.order_of_key(10) == 1); 657 | assert(t.order_of_key(11) == 2); 658 | assert(*t.find_by_order(0) == 8); 659 | t.join(t2); // assuming t < t2 or t > t2, merge t2 into t 660 | } 661 | 662 | // Priority Queue 663 | #include 664 | using namespace __gnu_pbds; 665 | template> 666 | using pair_heap = __gnu_pbds::priority_queue; 667 | 668 | void example() { 669 | pair_heap q1, q2; 670 | q1.push(5); 671 | q1.push(10); 672 | q2.push(1); 673 | q2.push(7); 674 | q1.join(q2); 675 | } 676 | ``` 677 | 678 | ### Splay 679 | 680 | ```cpp 681 | // Normal Splay 682 | struct Node { 683 | int val, size; 684 | Node *pa, *lc, *rc; 685 | Node(int val = 0, Node *pa = nullptr) : val(val), size(1), pa(pa), lc(nullptr), rc(nullptr) {} 686 | Node*& c(bool x) { return x ? lc : rc; } 687 | bool d() { return pa ? this == pa->lc : 0; } 688 | } pool[MAXN << 2], *tail = pool; 689 | 690 | struct Splay { 691 | Node *root; 692 | 693 | Splay() : root(nullptr) {} 694 | 695 | Node* N(int val, Node *pa) { 696 | return new (tail++) Node(val, pa); 697 | } 698 | 699 | void upd(Node *o) { 700 | o->size = (o->lc ? o->lc->size : 0) + (o->rc ? o->rc->size : 0) + 1; 701 | } 702 | 703 | void link(Node *x, Node *y, bool d) { 704 | if (x) x->pa = y; 705 | if (y) y->c(d) = x; 706 | } 707 | 708 | void rotate(Node *o) { 709 | bool dd = o->d(); 710 | Node *x = o->pa, *xx = x->pa, *y = o->c(!dd); 711 | link(o, xx, x->d()); 712 | link(y, x, dd); 713 | link(x, o, !dd); 714 | upd(x); 715 | upd(o); 716 | } 717 | 718 | void splay(Node *o) { 719 | for (Node *x = o->pa; x = o->pa, x; rotate(o)) { 720 | if (x->pa) rotate(o->d() == x->d() ? x : o); 721 | } 722 | root = o; 723 | } 724 | }; 725 | ``` 726 | 727 | ### Treap 728 | 729 | ```cpp 730 | // split_x: elements on the left are < x 731 | // split_k: split out k elements on the left 732 | namespace tr { 733 | using uint = unsigned int; 734 | 735 | uint rnd() { 736 | static uint A = 1 << 16 | 3, B = 33333331, C = 1091; 737 | return C = A * C + B; 738 | } 739 | 740 | struct Node { 741 | uint key; 742 | int val, size; 743 | Node *lc, *rc; 744 | Node(int val = 0) : key(rnd()), val(val), size(1), lc(nullptr), rc(nullptr) {} 745 | } pool[MAXN << 2], *tail = pool; 746 | 747 | Node* N(int val) { 748 | return new (tail++) Node(val); 749 | } 750 | 751 | void upd(Node *o) { 752 | o->size = (o->lc ? o->lc->size : 0) + (o->rc ? o->rc->size : 0) + 1; 753 | } 754 | 755 | Node* merge(Node *l, Node *r) { 756 | if (!l) return r; 757 | if (!r) return l; 758 | if (l->key > r->key) { 759 | l->rc = merge(l->rc, r); 760 | upd(l); 761 | return l; 762 | } else { 763 | r->lc = merge(l, r->lc); 764 | upd(r); 765 | return r; 766 | } 767 | } 768 | 769 | void split_x(Node *o, int x, Node*& l, Node*& r) { 770 | if (!o) { l = r = nullptr; return; } 771 | if (o->val < x) { 772 | l = o; 773 | split_x(o->rc, x, l->rc, r); 774 | upd(l); 775 | } else { 776 | r = o; 777 | split_x(o->lc, x, l, r->lc); 778 | upd(r); 779 | } 780 | } 781 | 782 | void split_k(Node *o, int k, Node*& l, Node*& r) { 783 | if (!o) { l = r = nullptr; return; } 784 | int lsize = o->lc ? o->lc->size : 0; 785 | if (lsize < k) { 786 | l = o; 787 | split_k(o->rc, k - lsize - 1, o->rc, r); 788 | upd(l); 789 | } else { 790 | r = o; 791 | split_k(o->lc, k, l, o->lc); 792 | upd(r); 793 | } 794 | } 795 | } 796 | ``` 797 | 798 | ### Interval Set 799 | 800 | ```cpp 801 | // For Q assign operation it takes Qlogn time in total 802 | template 803 | struct interval_set { 804 | map, T> mp; // {r,l}=val 805 | interval_set(int l, int r, T v = T()) { mp[{r, l}] = v; } 806 | 807 | // assign a[i]=val for l<=i<=r 808 | // returns affected ranges before performing this assign operation 809 | vector, T>> assign(int l, int r, T v) { 810 | auto b = mp.lower_bound({l, 0})->first; 811 | if (b.second != l) { 812 | T z = mp[b]; 813 | mp.erase(b); 814 | mp[{l - 1, b.second}] = z; 815 | mp[{b.first, l}] = z; 816 | } 817 | 818 | auto e = mp.lower_bound({r, 0})->first; 819 | if (e.first != r) { 820 | T z = mp[e]; 821 | mp.erase(e); 822 | mp[{e.first, r + 1}] = z; 823 | mp[{r, e.second}] = z; 824 | } 825 | 826 | vector, T>> ret; 827 | for (auto it = mp.lower_bound({l, 0}); it != mp.end() && it->first.first <= r; ++it) { 828 | ret.push_back({{it->first.second, it->first.first}, it->second}); 829 | } 830 | for (auto it : ret) mp.erase({it.first.second, it.first.first}); 831 | mp[{r, l}] = v; 832 | return ret; 833 | } 834 | 835 | T operator[](int i) const { return mp.lower_bound({i, 0})->second; } 836 | }; 837 | ``` 838 | 839 | ### CDQ Divide and Conquer 840 | 841 | + Three-dimensional partial order (non-strict) 842 | 843 | ```cpp 844 | struct Node { 845 | int x, y, z, sum, ans; 846 | } p[N], q[N]; 847 | 848 | void CDQ(int l, int r) { 849 | if (l == r) return; 850 | int mid = (l + r) >> 1; 851 | CDQ(l, mid); 852 | CDQ(mid + 1, r); 853 | int i = l, j = mid + 1; 854 | for (int t = l; t <= r; t++) { 855 | if (j > r || (i <= mid && p[i].y <= p[j].y)) { 856 | q[t] = p[i++]; 857 | bit.add(q[t].z, q[t].sum); 858 | } else { 859 | q[t] = p[j++]; 860 | q[t].ans += bit.get(q[t].z); 861 | } 862 | } 863 | for (i = l; i <= r; i++) { 864 | p[i] = q[i]; 865 | bit.set(p[i].z, 0); 866 | } 867 | } 868 | 869 | void go() { 870 | sort(p, p + n, [](const Node &a, const Node &b) { 871 | if (a.x != b.x) return a.x < b.x; 872 | if (a.y != b.y) return a.y < b.y; 873 | return a.z < b.z; 874 | }); 875 | auto eq = [](const Node& a, const Node& b) { 876 | return a.x == b.x && a.y == b.y && a.z == b.z; 877 | }; 878 | int k = n; 879 | for (int i = 0, j = 0; i < n; i++, j++) { 880 | if (eq(p[i], p[j - 1])) j--, k--; 881 | else if (i != j) p[j] = p[i]; 882 | p[j].sum++; 883 | } 884 | bit.init(m); 885 | CDQ(0, k - 1); 886 | } 887 | ``` 888 | 889 | ### Mo's Algorithm 890 | 891 | ```cpp 892 | int unit = max(1, int(n / sqrt(q))); 893 | sort(qry.begin(), qry.end(), [&](auto &a, auto &b) { 894 | if (a.l / unit != b.l / unit) return a.l < b.l; 895 | return ((a.l / unit) & 1) ? a.r < b.r : a.r > b.r; 896 | }); 897 | 898 | // [l, r) 899 | while (l > q.l) add_left(--l); 900 | while (r < q.r) add_right(r++); 901 | while (l < q.l) delete_left(l++); 902 | while (r > q.r) delete_right(--r); 903 | ``` -------------------------------------------------------------------------------- /2-Graph.md: -------------------------------------------------------------------------------- 1 | ## Graph Theory 2 | 3 | ### Shortest Path 4 | 5 | + Dijkstra 6 | 7 | ```cpp 8 | struct Dijkstra { 9 | struct Edge { 10 | int to, val; 11 | Edge(int to = 0, int val = 0) : to(to), val(val) {} 12 | }; 13 | 14 | int n; 15 | vector> g; 16 | 17 | Dijkstra(int n) : n(n), g(n) {} 18 | 19 | void add_edge(int u, int v, int val) { g[u].emplace_back(v, val); } 20 | 21 | vector solve(int s) { 22 | using pii = pair; 23 | vector dis(n, 1LL << 60); 24 | priority_queue, greater> q; 25 | dis[s] = 0; 26 | q.emplace(0, s); 27 | while (!q.empty()) { 28 | pii p = q.top(); 29 | q.pop(); 30 | int u = p.second; 31 | if (dis[u] < p.first) continue; 32 | for (Edge& e : g[u]) { 33 | int v = e.to; 34 | if (dis[v] > dis[u] + e.val) { 35 | dis[v] = dis[u] + e.val; 36 | q.emplace(dis[v], v); 37 | } 38 | } 39 | } 40 | return dis; 41 | } 42 | }; 43 | ``` 44 | 45 | + Bellman-Ford 46 | 47 | ```cpp 48 | struct SPFA { 49 | struct Edge { 50 | int to, val; 51 | Edge(int to = 0, int val = 0) : to(to), val(val) {} 52 | }; 53 | 54 | int n; 55 | vector> g; 56 | 57 | SPFA(int n) : n(n), g(n) {} 58 | 59 | void add_edge(int u, int v, int val) { g[u].emplace_back(v, val); } 60 | 61 | vector solve(int s) { 62 | queue q; 63 | vector dis(n, 1LL << 60); 64 | vector in(n, 0); 65 | q.push(s); 66 | dis[s] = 0; 67 | in[s] = 1; 68 | while (!q.empty()) { 69 | int u = q.front(); 70 | q.pop(); 71 | in[u] = 0; 72 | for (Edge& e : g[u]) { 73 | int v = e.to; 74 | if (dis[v] > dis[u] + e.val) { 75 | dis[v] = dis[u] + e.val; 76 | if (!in[v]) { 77 | in[v] = 1; 78 | q.push(v); 79 | } 80 | } 81 | } 82 | } 83 | return dis; 84 | } 85 | }; 86 | ``` 87 | 88 | + Floyd–Warshall, with Shortest Cycle 89 | 90 | ```cpp 91 | // Note: INF should not exceed 1/3 LLONG_MAX 92 | for (int k = 0; k < n; k++) { 93 | for (int i = 0; i < k; i++) { 94 | for (int j = 0; j < i; j++) { 95 | ans = min(ans, g[i][k] + g[k][j] + dis[i][j]); 96 | } 97 | } 98 | for (int i = 0; i < n; i++) { 99 | for (int j = 0; j < n; j++) { 100 | dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]); 101 | } 102 | } 103 | } 104 | ``` 105 | 106 | ### Topological Sorting 107 | 108 | ```cpp 109 | // Use max/min heap for lexicographically largest/smallest 110 | int n, deg[N], dis[N]; 111 | vector g[N]; 112 | 113 | bool topo(vector& ans) { 114 | queue q; 115 | for (int i = 1; i <= n; i++) { 116 | if (deg[i] == 0) { 117 | q.push(i); 118 | dis[i] = 1; 119 | } 120 | } 121 | while (!q.empty()) { 122 | int u = q.front(); 123 | q.pop(); 124 | ans.push_back(u); 125 | for (int v : g[u]) { 126 | deg[v]--; 127 | dis[v] = max(dis[v], dis[u] + 1); 128 | if (deg[v] == 0) q.push(v); 129 | } 130 | } 131 | return ans.size() == n; 132 | } 133 | ``` 134 | 135 | ### Minimum Spanning Tree 136 | 137 | ```cpp 138 | // Prerequisite: Disjoint Set Union 139 | struct Edge { 140 | int u, v, w; 141 | Edge(int u = 0, int v = 0, int w = 0) : u(u), v(v), w(w) {} 142 | }; 143 | 144 | i64 kruskal(vector& es, int n) { 145 | sort(es.begin(), es.end(), [](Edge& x, Edge& y) { return x.w < y.w; }); 146 | dsu d(n + 1); 147 | i64 ans = 0; 148 | for (Edge& e : es) { 149 | if (d.merge(e.u, e.v)) { 150 | ans += e.w; 151 | } 152 | } 153 | return ans; 154 | } 155 | ``` 156 | 157 | ### Lowest Common Ancestor 158 | 159 | ```cpp 160 | struct LCA { 161 | int n, log; 162 | vector> g; 163 | vector dep; 164 | vector> up; 165 | LCA(int n) 166 | : n(n), log(__lg(n) + 1), g(n), dep(n), up(n, vector(log, -1)) {} 167 | 168 | void add_edge(int u, int v) { 169 | g[u].push_back(v); 170 | g[v].push_back(u); 171 | } 172 | 173 | void dfs(int u, int p) { 174 | up[u][0] = p; 175 | for (int i = 1; i < log; i++) { 176 | up[u][i] = (up[u][i - 1] == -1 ? -1 : up[up[u][i - 1]][i - 1]); 177 | } 178 | for (int v : g[u]) { 179 | if (v == p) continue; 180 | dep[v] = dep[u] + 1; 181 | dfs(v, u); 182 | } 183 | } 184 | 185 | void build(int root = 0) { dfs(root, -1); } 186 | 187 | int lca(int u, int v) { 188 | if (dep[u] < dep[v]) swap(u, v); 189 | for (int i = log - 1; i >= 0; i--) { 190 | if (dep[u] - (1 << i) >= dep[v]) u = up[u][i]; 191 | } 192 | if (u == v) return u; 193 | for (int i = log - 1; i >= 0; i--) { 194 | if (up[u][i] != up[v][i]) u = up[u][i], v = up[v][i]; 195 | } 196 | return up[u][0]; 197 | } 198 | }; 199 | ``` 200 | 201 | ### Network Flow 202 | 203 | + Max Flow 204 | 205 | ```cpp 206 | const int INF = 0x7fffffff; 207 | 208 | struct Dinic { 209 | struct Edge { 210 | int to, cap; 211 | Edge(int to, int cap) : to(to), cap(cap) {} 212 | }; 213 | 214 | int n, s, t; 215 | vector es; 216 | vector> g; 217 | vector dis, cur; 218 | 219 | Dinic(int n, int s, int t) : n(n), s(s), t(t), g(n), dis(n), cur(n) {} 220 | 221 | void add_edge(int u, int v, int cap) { 222 | g[u].push_back(es.size()); 223 | es.emplace_back(v, cap); 224 | g[v].push_back(es.size()); 225 | es.emplace_back(u, 0); 226 | } 227 | 228 | bool bfs() { 229 | dis.assign(n, 0); 230 | queue q; 231 | q.push(s); 232 | dis[s] = 1; 233 | while (!q.empty()) { 234 | int u = q.front(); 235 | q.pop(); 236 | for (int i : g[u]) { 237 | Edge& e = es[i]; 238 | if (!dis[e.to] && e.cap > 0) { 239 | dis[e.to] = dis[u] + 1; 240 | q.push(e.to); 241 | } 242 | } 243 | } 244 | return dis[t]; 245 | } 246 | 247 | int dfs(int u, int cap) { 248 | if (u == t || cap == 0) return cap; 249 | int tmp = cap; 250 | for (int& i = cur[u]; i < (int)g[u].size(); i++) { 251 | Edge& e = es[g[u][i]]; 252 | if (dis[e.to] == dis[u] + 1) { 253 | int f = dfs(e.to, min(cap, e.cap)); 254 | e.cap -= f; 255 | es[g[u][i] ^ 1].cap += f; 256 | cap -= f; 257 | if (cap == 0) break; 258 | } 259 | } 260 | return tmp - cap; 261 | } 262 | 263 | i64 solve() { 264 | i64 flow = 0; 265 | while (bfs()) { 266 | cur.assign(n, 0); 267 | flow += dfs(s, INF); 268 | } 269 | return flow; 270 | } 271 | }; 272 | ``` 273 | 274 | + Minimum Cost Flow 275 | 276 | ```cpp 277 | const i64 INF = 1e15; 278 | 279 | struct MCMF { 280 | struct Edge { 281 | int from, to; 282 | i64 cap, cost; 283 | Edge(int from, int to, i64 cap, i64 cost) : from(from), to(to), cap(cap), cost(cost) {} 284 | }; 285 | 286 | int n, s, t; 287 | i64 flow, cost; 288 | vector es; 289 | vector> g; 290 | vector d, a; // dis, add, prev 291 | vector p, in; 292 | 293 | MCMF(int n, int s, int t) : n(n), s(s), t(t), flow(0), cost(0), g(n), p(n), a(n) {} 294 | 295 | void add_edge(int u, int v, i64 cap, i64 cost) { 296 | g[u].push_back(es.size()); 297 | es.emplace_back(u, v, cap, cost); 298 | g[v].push_back(es.size()); 299 | es.emplace_back(v, u, 0, -cost); 300 | } 301 | 302 | bool spfa() { 303 | d.assign(n, INF); 304 | in.assign(n, 0); 305 | d[s] = 0; 306 | in[s] = 1; 307 | a[s] = INF; 308 | queue q; 309 | q.push(s); 310 | while (!q.empty()) { 311 | int u = q.front(); 312 | q.pop(); 313 | in[u] = 0; 314 | for (int& i : g[u]) { 315 | Edge& e = es[i]; 316 | if (e.cap && d[e.to] > d[u] + e.cost) { 317 | d[e.to] = d[u] + e.cost; 318 | p[e.to] = i; 319 | a[e.to] = min(a[u], e.cap); 320 | if (!in[e.to]) { 321 | q.push(e.to); 322 | in[e.to] = 1; 323 | } 324 | } 325 | } 326 | } 327 | return d[t] != INF; 328 | } 329 | 330 | void solve() { 331 | while (spfa()) { 332 | flow += a[t]; 333 | cost += a[t] * d[t]; 334 | int u = t; 335 | while (u != s) { 336 | es[p[u]].cap -= a[t]; 337 | es[p[u] ^ 1].cap += a[t]; 338 | u = es[p[u]].from; 339 | } 340 | } 341 | } 342 | }; 343 | ``` 344 | 345 | ### Minimum Cut of Undirected Graph 346 | 347 | ```cpp 348 | namespace stoer_wagner { 349 | bool vis[N], in[N]; 350 | int g[N][N], w[N]; 351 | 352 | void init() { 353 | memset(g, 0, sizeof(g)); 354 | memset(in, 0, sizeof(in)); 355 | } 356 | 357 | void add_edge(int u, int v, int w) { 358 | g[u][v] += w; 359 | g[v][u] += w; 360 | } 361 | 362 | int search(int& s, int& t) { 363 | memset(vis, 0, sizeof(vis)); 364 | memset(w, 0, sizeof(w)); 365 | int maxw, tt = n + 1; 366 | for (int i = 0; i < n; i++) { 367 | maxw = -INF; 368 | for (int j = 0; j < n; j++) { 369 | if (!in[j] && !vis[j] && w[j] > maxw) { 370 | maxw = w[j]; 371 | tt = j; 372 | } 373 | } 374 | if (t == tt) return w[t]; 375 | s = t; t = tt; 376 | vis[tt] = true; 377 | for (int j = 0; j < n; j++) { 378 | if (!in[j] && !vis[j]) { 379 | w[j] += g[tt][j]; 380 | } 381 | } 382 | } 383 | return w[t]; 384 | } 385 | 386 | int go() { 387 | int s, t, ans = INF; 388 | for (int i = 0; i < n - 1; i++) { 389 | s = t = -1; 390 | ans = min(ans, search(s, t)); 391 | if (ans == 0) return 0; 392 | in[t] = true; 393 | for (int j = 0; j < n; j++) { 394 | if (!in[j]) { 395 | g[s][j] += g[t][j]; 396 | g[j][s] += g[j][t]; 397 | } 398 | } 399 | } 400 | return ans; 401 | } 402 | } 403 | ``` 404 | 405 | ### Heavy-Light Decomposition 406 | 407 | ```cpp 408 | // jiangly 409 | struct HLD { 410 | int n; 411 | vector siz, top, dep, parent, in, out, seq; 412 | vector> adj; 413 | int cur; 414 | 415 | explicit HLD(int n) : n(n), siz(n), top(n), dep(n), parent(n), in(n), out(n), seq(n), adj(n), cur(0) {} 416 | 417 | void addEdge(int u, int v) { 418 | adj[u].push_back(v); 419 | adj[v].push_back(u); 420 | } 421 | 422 | void work(int root = 0) { 423 | top[root] = root; 424 | dep[root] = 0; 425 | parent[root] = -1; 426 | dfs1(root); 427 | dfs2(root); 428 | } 429 | 430 | void dfs1(int u) { 431 | if (parent[u] != -1) { 432 | adj[u].erase(find(adj[u].begin(), adj[u].end(), parent[u])); 433 | } 434 | siz[u] = 1; 435 | for (auto& v : adj[u]) { 436 | parent[v] = u; 437 | dep[v] = dep[u] + 1; 438 | dfs1(v); 439 | siz[u] += siz[v]; 440 | if (siz[v] > siz[adj[u][0]]) { 441 | swap(v, adj[u][0]); 442 | } 443 | } 444 | } 445 | 446 | void dfs2(int u) { 447 | in[u] = cur++; 448 | seq[in[u]] = u; 449 | for (auto v : adj[u]) { 450 | top[v] = v == adj[u][0] ? top[u] : v; 451 | dfs2(v); 452 | } 453 | out[u] = cur; 454 | } 455 | 456 | int lca(int u, int v) { 457 | while (top[u] != top[v]) { 458 | if (dep[top[u]] > dep[top[v]]) { 459 | u = parent[top[u]]; 460 | } else { 461 | v = parent[top[v]]; 462 | } 463 | } 464 | return dep[u] < dep[v] ? u : v; 465 | } 466 | 467 | int dist(int u, int v) { return dep[u] + dep[v] - 2 * dep[lca(u, v)]; } 468 | 469 | int jump(int u, int k) { 470 | if (dep[u] < k) { 471 | return -1; 472 | } 473 | int d = dep[u] - k; 474 | while (dep[top[u]] > d) { 475 | u = parent[top[u]]; 476 | } 477 | return seq[in[u] - dep[u] + d]; 478 | } 479 | 480 | bool isAncester(int u, int v) { return in[u] <= in[v] && in[v] < out[u]; } 481 | 482 | int rootedParent(int u, int v) { 483 | swap(u, v); 484 | if (u == v) { 485 | return u; 486 | } 487 | if (!isAncester(u, v)) { 488 | return parent[u]; 489 | } 490 | auto it = upper_bound(adj[u].begin(), adj[u].end(), v, [&](int x, int y) { return in[x] < in[y]; }) - 1; 491 | return *it; 492 | } 493 | 494 | int rootedSize(int u, int v) { 495 | if (u == v) { 496 | return n; 497 | } 498 | if (!isAncester(v, u)) { 499 | return siz[v]; 500 | } 501 | return n - siz[rootedParent(u, v)]; 502 | } 503 | 504 | int rootedLca(int a, int b, int c) { return lca(a, b) ^ lca(b, c) ^ lca(c, a); } 505 | 506 | // [u, v] if inclusive is true, otherwise [u, v) 507 | vector> path(int u, int v, bool inclusive) { 508 | assert(isAncester(v, u)); 509 | vector> res; 510 | while (top[u] != top[v]) { 511 | res.emplace_back(u, top[u]); 512 | u = parent[top[u]]; 513 | } 514 | if (inclusive) { 515 | res.emplace_back(u, v); 516 | } else if (u != v) { 517 | res.emplace_back(u, seq[in[v] + 1]); 518 | } 519 | return res; 520 | } 521 | }; 522 | ``` 523 | 524 | ### Tree Hash 525 | 526 | ```cpp 527 | const uint64_t mask = chrono::steady_clock::now().time_since_epoch().count(); 528 | 529 | uint64_t f(uint64_t x) { 530 | x ^= mask; 531 | x ^= x << 13; 532 | x ^= x >> 7; 533 | x ^= x << 17; 534 | x ^= mask; 535 | return x; 536 | } 537 | 538 | uint64_t dfs(int u, int p) { 539 | uint64_t h = 1; 540 | for (int v : g[u]) { 541 | if (v == p) continue; 542 | h += f(dfs(v, u)); 543 | } 544 | return h; 545 | } 546 | ``` 547 | 548 | ### Tarjan 549 | 550 | + Cut Points 551 | 552 | ```cpp 553 | int dfn[N], low[N], clk; 554 | 555 | void init() { clk = 0; memset(dfn, 0, sizeof(dfn)); } 556 | 557 | void tarjan(int u, int pa) { 558 | low[u] = dfn[u] = ++clk; 559 | int cc = (pa != 0); 560 | for (int v : g[u]) { 561 | if (v == pa) continue; 562 | if (!dfn[v]) { 563 | tarjan(v, u); 564 | low[u] = min(low[u], low[v]); 565 | cc += low[v] >= dfn[u]; 566 | } else low[u] = min(low[u], dfn[v]); 567 | } 568 | if (cc > 1) // ... 569 | } 570 | ``` 571 | 572 | + Bridges 573 | 574 | ```cpp 575 | int dfn[N], low[N], clk; 576 | 577 | void init() { clk = 0; memset(dfn, 0, sizeof(dfn)); } 578 | 579 | void tarjan(int u, int pa) { 580 | low[u] = dfn[u] = ++clk; 581 | int f = 0; 582 | for (int v : g[u]) { 583 | if (v == pa && ++f == 1) continue; 584 | if (!dfn[v]) { 585 | tarjan(v, u); 586 | if (low[v] > dfn[u]) // ... 587 | low[u] = min(low[u], low[v]); 588 | } else low[u] = min(low[u], dfn[v]); 589 | } 590 | } 591 | ``` 592 | 593 | + Strongly Connected Components (SCC) 594 | 595 | ```cpp 596 | struct SCC { 597 | int n, tot; 598 | vector> g; 599 | vector color; 600 | 601 | SCC(int n) : n(n), g(n) {} 602 | 603 | void add_edge(int u, int v) { g[u].push_back(v); } 604 | 605 | void work() { 606 | tot = 0; 607 | color.assign(n, -1); 608 | vector dfn(n), low(n), st; 609 | int clk = 0; 610 | function dfs = [&](int u) { 611 | dfn[u] = low[u] = ++clk; 612 | st.push_back(u); 613 | for (int v : g[u]) { 614 | if (!dfn[v]) { 615 | dfs(v); 616 | low[u] = min(low[u], low[v]); 617 | } else if (color[v] == -1) { 618 | low[u] = min(low[u], dfn[v]); 619 | } 620 | } 621 | if (dfn[u] == low[u]) { 622 | for (;;) { 623 | int x = st.back(); 624 | st.pop_back(); 625 | color[x] = tot; 626 | if (x == u) break; 627 | } 628 | tot++; 629 | } 630 | }; 631 | for (int i = 0; i < n; i++) { 632 | if (!dfn[i]) dfs(i); 633 | } 634 | for (int& x : color) { 635 | x = tot - 1 - x; 636 | } 637 | } 638 | 639 | vector> scc() { 640 | vector> res(tot); 641 | for (int i = 0; i < n; i++) { 642 | res[color[i]].push_back(i); 643 | } 644 | return res; 645 | } 646 | 647 | vector> dag() { 648 | vector> res(tot); 649 | for (int i = 0; i < n; i++) { 650 | for (int j : g[i]) { 651 | if (color[i] != color[j]) { 652 | res[color[i]].push_back(color[j]); 653 | } 654 | } 655 | } 656 | for (auto& v : res) { 657 | sort(v.begin(), v.end()); 658 | v.erase(unique(v.begin(), v.end()), v.end()); 659 | } 660 | return res; 661 | } 662 | }; 663 | ``` 664 | 665 | + 2-SAT 666 | 667 | ```cpp 668 | struct two_sat { 669 | int n; 670 | SCC scc; 671 | 672 | two_sat(int n) : n(n), scc(n * 2) {} 673 | 674 | void add_clause(int u, bool f, int v, bool g) { 675 | u = u * 2 + f; 676 | v = v * 2 + g; 677 | scc.add_edge(u ^ 1, v); 678 | scc.add_edge(v ^ 1, u); 679 | } 680 | 681 | bool solve() { 682 | scc.work(); 683 | for (int i = 0; i < n; i++) { 684 | if (scc.color[i * 2] == scc.color[i * 2 + 1]) { 685 | return false; 686 | } 687 | } 688 | return true; 689 | } 690 | 691 | vector answer() { 692 | vector res(n); 693 | for (int i = 0; i < n; i++) { 694 | res[i] = scc.color[i * 2 + 1] > scc.color[i * 2]; 695 | } 696 | return res; 697 | } 698 | }; 699 | ``` 700 | 701 | ### Eulerian Path 702 | 703 | ```cpp 704 | struct EulerPath { 705 | int n; 706 | vector> g; 707 | vector> es; 708 | 709 | EulerPath(int n) : n(n), g(n) {} 710 | 711 | void add_edge(int u, int v, bool directed = false) { 712 | g[u].push_back(es.size()); 713 | if (!directed) g[v].push_back(es.size()); 714 | es.emplace_back(u, v); 715 | } 716 | 717 | vector solve(int s) { 718 | vector path, ptr(n), st; 719 | vector used(es.size()); 720 | st.push_back(s); 721 | while (!st.empty()) { 722 | int u = st.back(); 723 | int& i = ptr[u]; 724 | while (i < g[u].size() && used[g[u][i]]) i++; 725 | if (i == g[u].size()) { 726 | path.push_back(u); 727 | st.pop_back(); 728 | } else { 729 | int e = g[u][i]; 730 | used[e] = 1; 731 | int v = es[e].first ^ es[e].second ^ u; 732 | st.push_back(v); 733 | } 734 | } 735 | reverse(path.begin(), path.end()); 736 | return path; 737 | } 738 | }; 739 | ``` 740 | 741 | ### Dominator Tree 742 | 743 | ```cpp 744 | vector g[N], rg[N]; 745 | vector dt[N]; 746 | 747 | namespace tl { 748 | int pa[N], dfn[N], clk, rdfn[N]; 749 | int c[N], best[N], sdom[N], idom[N]; 750 | 751 | void init(int n) { 752 | clk = 0; 753 | fill(c, c + n + 1, -1); 754 | fill(dfn, dfn + n + 1, 0); 755 | for (int i = 1; i <= n; i++) { 756 | dt[i].clear(); 757 | sdom[i] = best[i] = i; 758 | } 759 | } 760 | 761 | void dfs(int u) { 762 | dfn[u] = ++clk; 763 | rdfn[clk] = u; 764 | for (int& v : g[u]) { 765 | if (!dfn[v]) { 766 | pa[v] = u; 767 | dfs(v); 768 | } 769 | } 770 | } 771 | 772 | int fix(int x) { 773 | if (c[x] == -1) return x; 774 | int& f = c[x], rt = fix(f); 775 | if (dfn[sdom[best[x]]] > dfn[sdom[best[f]]]) best[x] = best[f]; 776 | return f = rt; 777 | } 778 | 779 | void go(int rt) { 780 | dfs(rt); 781 | for (int i = clk; i > 1; i--) { 782 | int x = rdfn[i], mn = clk + 1; 783 | for (int& u : rg[x]) { 784 | if (!dfn[u]) continue; // may not reach all vertices 785 | fix(u); 786 | mn = min(mn, dfn[sdom[best[u]]]); 787 | } 788 | c[x] = pa[x]; 789 | dt[sdom[x] = rdfn[mn]].push_back(x); 790 | x = rdfn[i - 1]; 791 | for (int& u: dt[x]) { 792 | fix(u); 793 | idom[u] = (sdom[best[u]] == x) ? x : best[u]; 794 | } 795 | dt[x].clear(); 796 | } 797 | for (int i = 2; i <= clk; i++) { 798 | int u = rdfn[i]; 799 | if (idom[u] != sdom[u]) idom[u] = idom[idom[u]]; 800 | dt[idom[u]].push_back(u); 801 | } 802 | } 803 | } 804 | ``` 805 | -------------------------------------------------------------------------------- /3-String.md: -------------------------------------------------------------------------------- 1 | ## Strings 2 | 3 | ### Hash 4 | 5 | ```cpp 6 | // open hack 7 | mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count()); 8 | 9 | struct Hash { 10 | static const i64 md = (1LL << 61) - 1; 11 | static i64 step; 12 | static vector pw; 13 | 14 | static i64 mul(i64 a, i64 b) { return (i64)(__int128(a) * b % md); } 15 | 16 | static void init(int N) { 17 | pw.resize(N + 1); 18 | pw[0] = 1; 19 | for (int i = 1; i <= N; i++) pw[i] = mul(pw[i - 1], step); 20 | } 21 | 22 | vector h; 23 | 24 | template 25 | Hash(const T& s) { 26 | int n = s.size(); 27 | h.resize(n + 1); 28 | for (int i = 0; i < n; i++) h[i + 1] = (mul(h[i], step) + s[i]) % md; 29 | } 30 | 31 | i64 operator()(int l, int r) { return (h[r + 1] - mul(h[l], pw[r - l + 1]) + md) % md; } 32 | }; 33 | 34 | i64 Hash::step = uniform_int_distribution(256, md - 1)(rng); 35 | vector Hash::pw; 36 | int _ = (Hash::init(1e6), 0); 37 | ``` 38 | 39 | + 2D Hash 40 | 41 | ```cpp 42 | const i64 basex = 239, basey = 241, p = 998244353; 43 | 44 | i64 pwx[N], pwy[N]; 45 | 46 | void init_xp() { 47 | pwx[0] = pwy[0] = 1; 48 | for (int i = 1; i < N; i++) { 49 | pwx[i] = pwx[i - 1] * basex % p; 50 | pwy[i] = pwy[i - 1] * basey % p; 51 | } 52 | } 53 | 54 | struct Hash2D { 55 | vector> h; 56 | 57 | Hash2D(const vector>& a, int n, int m) : h(n + 1, vector(m + 1)) { 58 | for (int i = 0; i < n; i++) { 59 | i64 s = 0; 60 | for (int j = 0; j < m; j++) { 61 | s = (s * basey + a[i][j] + 1) % p; 62 | h[i + 1][j + 1] = (h[i][j + 1] * basex + s) % p; 63 | } 64 | } 65 | } 66 | 67 | i64 get(int x, int y, int xx, int yy) { 68 | ++xx; ++yy; 69 | int dx = xx - x, dy = yy - y; 70 | i64 res = h[xx][yy] 71 | - h[x][yy] * pwx[dx] 72 | - h[xx][y] * pwy[dy] 73 | + h[x][y] * pwx[dx] % p * pwy[dy]; 74 | return (res % p + p) % p; 75 | } 76 | }; 77 | ``` 78 | 79 | + SplitMix 80 | 81 | ```cpp 82 | // tourist 83 | mt19937_64 rng((unsigned int)chrono::steady_clock::now().time_since_epoch().count()); 84 | 85 | struct hash61 { 86 | static const uint64_t md = (1LL << 61) - 1; 87 | static uint64_t step; 88 | static vector pw; 89 | 90 | uint64_t addmod(uint64_t a, uint64_t b) const { 91 | a += b; 92 | if (a >= md) a -= md; 93 | return a; 94 | } 95 | 96 | uint64_t submod(uint64_t a, uint64_t b) const { 97 | a += md - b; 98 | if (a >= md) a -= md; 99 | return a; 100 | } 101 | 102 | uint64_t mulmod(uint64_t a, uint64_t b) const { 103 | uint64_t l1 = (uint32_t)a, h1 = a >> 32, l2 = (uint32_t)b, h2 = b >> 32; 104 | uint64_t l = l1 * l2, m = l1 * h2 + l2 * h1, h = h1 * h2; 105 | uint64_t ret = (l & md) + (l >> 61) + (h << 3) + (m >> 29) + (m << 35 >> 3) + 1; 106 | ret = (ret & md) + (ret >> 61); 107 | ret = (ret & md) + (ret >> 61); 108 | return ret - 1; 109 | } 110 | 111 | void ensure_pw(int sz) { 112 | int cur = (int)pw.size(); 113 | if (cur < sz) { 114 | pw.resize(sz); 115 | for (int i = cur; i < sz; i++) { 116 | pw[i] = mulmod(pw[i - 1], step); 117 | } 118 | } 119 | } 120 | 121 | vector pref; 122 | int n; 123 | 124 | template 125 | hash61(const T& s) { 126 | n = (int)s.size(); 127 | ensure_pw(n + 1); 128 | pref.resize(n + 1); 129 | pref[0] = 1; 130 | for (int i = 0; i < n; i++) { 131 | pref[i + 1] = addmod(mulmod(pref[i], step), s[i]); 132 | } 133 | } 134 | 135 | inline uint64_t operator()(const int from, const int to) const { 136 | assert(0 <= from && from <= to && to <= n - 1); 137 | return submod(pref[to + 1], mulmod(pref[from], pw[to - from + 1])); 138 | } 139 | }; 140 | 141 | uint64_t hash61::step = (md >> 2) + rng() % (md >> 1); 142 | vector hash61::pw = vector(1, 1); 143 | ``` 144 | 145 | ### Manacher 146 | 147 | ```cpp 148 | // "aba" => "#a#b#a#" 149 | struct Manacher { 150 | vector d; 151 | 152 | Manacher(const string& s) { 153 | string t = "#"; 154 | for (int i = 0; i < s.size(); i++) { 155 | t.push_back(s[i]); 156 | t.push_back('#'); 157 | } 158 | int n = t.size(); 159 | d.resize(n); 160 | for (int i = 0, l = 0, r = -1; i < n; i++) { 161 | int k = (i > r) ? 1 : min(d[l + r - i], r - i); 162 | while (i - k >= 0 && i + k < n && t[i - k] == t[i + k]) k++; 163 | d[i] = --k; 164 | if (i + k > r) { 165 | l = i - k; 166 | r = i + k; 167 | } 168 | } 169 | } 170 | 171 | // 0-indexed [l, r] 172 | bool is_p(int l, int r) { return d[l + r + 1] >= r - l + 1; } 173 | }; 174 | ``` 175 | 176 | ### KMP 177 | 178 | ```cpp 179 | // prefix function (the longest common prefix and suffix for each prefix) 180 | // the smallest period of [0...i] is i + 1 - a[i] 181 | vector get_pi(const string& s) { 182 | int n = s.size(); 183 | vector a(n); 184 | for (int i = 1, j = 0; i < n; i++) { 185 | while (j && s[j] != s[i]) j = a[j - 1]; 186 | if (s[j] == s[i]) j++; 187 | a[i] = j; 188 | } 189 | return a; 190 | } 191 | 192 | struct KMP { 193 | string s; 194 | vector a; 195 | 196 | KMP(const string& s) : s(s), a(get_pi(s)) {} 197 | 198 | vector find_in(const string& t) { 199 | vector res; 200 | for (int i = 0, j = 0; i < t.size(); i++) { 201 | while (j && s[j] != t[i]) j = a[j - 1]; 202 | if (s[j] == t[i]) j++; 203 | if (j == s.size()) { 204 | res.push_back(i - j + 1); 205 | j = a[j - 1]; // Allowing overlapping matches j = 0 not allowed 206 | } 207 | } 208 | return res; 209 | } 210 | }; 211 | 212 | // Z function, z[i] = LCP(s, s[i:]) 213 | vector get_z(const string& s) { 214 | int n = s.size(), l = 0, r = 0; 215 | vector z(n); 216 | for (int i = 1; i < n; i++) { 217 | if (i <= r) z[i] = min(r - i + 1, z[i - l]); 218 | while (i + z[i] < n && s[z[i]] == s[i + z[i]]) z[i]++; 219 | if (i + z[i] - 1 > r) { 220 | l = i; 221 | r = i + z[i] - 1; 222 | } 223 | } 224 | return z; 225 | } 226 | ``` 227 | 228 | ### Lyndon Decomposition 229 | 230 | ```cpp 231 | vector duval(const string& s) { 232 | int n = s.size(), i = 0; 233 | vector d; 234 | while (i < n) { 235 | int j = i + 1, k = i; 236 | while (j < n && s[k] <= s[j]) { 237 | if (s[k] < s[j]) k = i; 238 | else k++; 239 | j++; 240 | } 241 | while (i <= k) { 242 | d.push_back(s.substr(i, j - k)); 243 | i += j - k; 244 | } 245 | } 246 | return d; 247 | } 248 | ``` 249 | 250 | ### Lexicographically Minimal String Rotation 251 | 252 | ```cpp 253 | int get(const string& s) { 254 | int k = 0, i = 0, j = 1, n = s.size(); 255 | while (k < n && i < n && j < n) { 256 | if (s[(i + k) % n] == s[(j + k) % n]) { 257 | k++; 258 | } else { 259 | s[(i + k) % n] > s[(j + k) % n] ? i = i + k + 1 : j = j + k + 1; 260 | if (i == j) i++; 261 | k = 0; 262 | } 263 | } 264 | return min(i, j); 265 | } 266 | ``` 267 | 268 | ### Trie 269 | 270 | ```cpp 271 | // 01 Trie 272 | struct Trie { 273 | int t[31 * N][2], sz; 274 | 275 | void init() { 276 | memset(t, 0, 2 * (sz + 2) * sizeof(int)); 277 | sz = 1; 278 | } 279 | 280 | void insert(int x) { 281 | int p = 0; 282 | for (int i = 30; i >= 0; i--) { 283 | bool d = (x >> i) & 1; 284 | if (!t[p][d]) t[p][d] = sz++; 285 | p = t[p][d]; 286 | } 287 | } 288 | }; 289 | 290 | // Normal Trie 291 | struct Trie { 292 | int t[N][26], sz, cnt[N]; 293 | 294 | void init() { 295 | memset(t, 0, 26 * (sz + 2) * sizeof(int)); 296 | memset(cnt, 0, (sz + 2) * sizeof(int)); 297 | sz = 1; 298 | } 299 | 300 | void insert(const string& s) { 301 | int p = 0; 302 | for (char c : s) { 303 | int d = c - 'a'; 304 | if (!t[p][d]) t[p][d] = sz++; 305 | p = t[p][d]; 306 | } 307 | cnt[p]++; 308 | } 309 | }; 310 | ``` 311 | 312 | ### Aho-Corasick Automaton 313 | 314 | ```cpp 315 | struct ACA { 316 | int t[N][26], sz, fail[N], nxt[N], cnt[N]; 317 | 318 | void init() { 319 | memset(t, 0, 26 * (sz + 2) * sizeof(int)); 320 | memset(fail, 0, (sz + 2) * sizeof(int)); 321 | memset(nxt, 0, (sz + 2) * sizeof(int)); 322 | memset(cnt, 0, (sz + 2) * sizeof(int)); 323 | sz = 1; 324 | } 325 | 326 | void insert(const string& s) { 327 | int p = 0; 328 | for (char c : s) { 329 | int d = c - 'a'; 330 | if (!t[p][d]) t[p][d] = sz++; 331 | p = t[p][d]; 332 | } 333 | cnt[p]++; 334 | } 335 | 336 | void build() { 337 | queue q; 338 | for (int i = 0; i < 26; i++) { 339 | if (t[0][i]) q.push(t[0][i]); 340 | } 341 | while (!q.empty()) { 342 | int u = q.front(); 343 | q.pop(); 344 | for (int i = 0; i < 26; i++) { 345 | int& v = t[u][i]; 346 | if (v) { 347 | fail[v] = t[fail[u]][i]; 348 | nxt[v] = cnt[fail[v]] ? fail[v] : nxt[fail[v]]; 349 | q.push(v); 350 | } else { 351 | v = t[fail[u]][i]; 352 | } 353 | } 354 | } 355 | } 356 | }; 357 | ``` 358 | 359 | ### Palindromic Tree 360 | 361 | ```cpp 362 | // WindJ0Y 363 | struct Palindromic_Tree { 364 | static constexpr int N = 300005; 365 | 366 | int next[N][26]; // next pointer, similar to trie, points to the string formed by adding the same character at the beginning and end of the current string 367 | int fail[N]; // fail pointer, jumps to the node pointed to by fail pointer after mismatch 368 | int cnt[N]; // represents the number of different essential strings represented by node i after count() 369 | int num[N]; // represents the number of palindrome strings with the last character of the palindrome string represented by node i as the end of the palindrome string. 370 | int len[N]; // len[i] represents the length of the palindrome string represented by node i 371 | int lcnt[N]; 372 | int S[N]; // Store the added characters 373 | int last; // Points to the node where the last character is located for easy addition next time 374 | int n; // Character array pointer 375 | int p; // Node pointer 376 | 377 | int newnode(int l, int vc) { // Create a new node 378 | for (int i = 0; i < 26; ++i) next[p][i] = 0; 379 | cnt[p] = 0; 380 | num[p] = 0; 381 | len[p] = l; 382 | lcnt[p] = vc; 383 | return p++; 384 | } 385 | 386 | void init() { // Initialize 387 | p = 0; 388 | newnode(0, 0); 389 | newnode(-1, 0); 390 | last = 0; 391 | n = 0; 392 | S[n] = -1; // Put a character not in the character set at the beginning to reduce special cases 393 | fail[0] = 1; 394 | } 395 | 396 | int get_fail(int x) { // Similar to KMP, find the longest one after mismatch 397 | while (S[n - len[x] - 1] != S[n]) x = fail[x]; 398 | return x; 399 | } 400 | 401 | void add(int c) { 402 | S[++n] = c; 403 | int cur = get_fail(last); // Find the matching position of this palindrome string through the last palindrome string 404 | if (!next[cur][c]) { // If this palindrome string has not appeared, it means a new essential different palindrome string has appeared 405 | int now = newnode(len[cur] + 2, lcnt[cur] | (1 << c)); // Create a new node 406 | fail[now] = next[get_fail(fail[cur])][c]; // Establish a fail pointer as in AC automation, so as to jump after mismatch 407 | next[cur][c] = now; 408 | num[now] = num[fail[now]] + 1; 409 | } 410 | last = next[cur][c]; 411 | cnt[last]++; 412 | } 413 | 414 | void count() { 415 | for (int i = p - 1; i >= 0; --i) cnt[fail[i]] += cnt[i]; 416 | // Parent node accumulates child node's cnt, because if fail[v]=u, then u must be v's child palindrome string 417 | } 418 | } pt; 419 | ``` 420 | 421 | ### Suffix Automaton 422 | 423 | ```cpp 424 | // 1-indexed 425 | // the array a in rsort is the topological order [1, sz) 426 | struct SAM { 427 | static constexpr int M = N << 1; 428 | int t[M][26], len[M], fa[M], sz = 2, last = 1; 429 | void init() { 430 | memset(t, 0, (sz + 2) * sizeof t[0]); 431 | sz = 2; 432 | last = 1; 433 | } 434 | void ins(int ch) { 435 | int p = last, np = last = sz++; 436 | len[np] = len[p] + 1; 437 | for (; p && !t[p][ch]; p = fa[p]) t[p][ch] = np; 438 | if (!p) { 439 | fa[np] = 1; 440 | return; 441 | } 442 | int q = t[p][ch]; 443 | if (len[q] == len[p] + 1) { 444 | fa[np] = q; 445 | } else { 446 | int nq = sz++; 447 | len[nq] = len[p] + 1; 448 | memcpy(t[nq], t[q], sizeof t[0]); 449 | fa[nq] = fa[q]; 450 | fa[np] = fa[q] = nq; 451 | for (; t[p][ch] == q; p = fa[p]) t[p][ch] = nq; 452 | } 453 | } 454 | 455 | int c[M] = {1}, a[M]; 456 | void rsort() { 457 | for (int i = 1; i < sz; ++i) c[i] = 0; 458 | for (int i = 1; i < sz; ++i) c[len[i]]++; 459 | for (int i = 1; i < sz; ++i) c[i] += c[i - 1]; 460 | for (int i = 1; i < sz; ++i) a[--c[len[i]]] = i; 461 | } 462 | }; 463 | ``` 464 | 465 | + Multiple Strings, Online Construction 466 | 467 | ```cpp 468 | // set last to 1 before inserting a new string 469 | struct SAM { 470 | static constexpr int M = N << 1; 471 | int t[M][26], len[M], fa[M], sz = 2, last = 1; 472 | void init() { 473 | memset(t, 0, (sz + 2) * sizeof t[0]); 474 | sz = 2; 475 | last = 1; 476 | } 477 | void ins(int ch) { 478 | int p = last, np = 0, nq = 0, q = -1; 479 | if (!t[p][ch]) { 480 | np = sz++; 481 | len[np] = len[p] + 1; 482 | for (; p && !t[p][ch]; p = fa[p]) t[p][ch] = np; 483 | } 484 | if (!p) { 485 | fa[np] = 1; 486 | } else { 487 | q = t[p][ch]; 488 | if (len[p] + 1 == len[q]) { 489 | fa[np] = q; 490 | } else { 491 | nq = sz++; 492 | len[nq] = len[p] + 1; 493 | memcpy(t[nq], t[q], sizeof t[0]); 494 | fa[nq] = fa[q]; 495 | fa[np] = fa[q] = nq; 496 | for (; t[p][ch] == q; p = fa[p]) t[p][ch] = nq; 497 | } 498 | } 499 | last = np ? np : nq ? nq : q; 500 | } 501 | }; 502 | ``` 503 | 504 | ### Suffix Array 505 | 506 | ```cpp 507 | // 0-indexed 508 | // sa[i]: position of the suffix with rank i 509 | // rk[i]: rank of the i-th suffix 510 | // lc[i]: LCP(sa[i], sa[i + 1]) 511 | struct SuffixArray { 512 | int n; 513 | vector sa, rk, lc; 514 | SuffixArray(const string& s) { 515 | n = s.length(); 516 | sa.resize(n); 517 | lc.resize(n - 1); 518 | rk.resize(n); 519 | iota(sa.begin(), sa.end(), 0); 520 | sort(sa.begin(), sa.end(), [&](int a, int b) { return s[a] < s[b]; }); 521 | rk[sa[0]] = 0; 522 | for (int i = 1; i < n; ++i) rk[sa[i]] = rk[sa[i - 1]] + (s[sa[i]] != s[sa[i - 1]]); 523 | int k = 1; 524 | vector tmp, cnt(n); 525 | tmp.reserve(n); 526 | while (rk[sa[n - 1]] < n - 1) { 527 | tmp.clear(); 528 | for (int i = 0; i < k; ++i) tmp.push_back(n - k + i); 529 | for (auto i : sa) 530 | if (i >= k) tmp.push_back(i - k); 531 | fill(cnt.begin(), cnt.end(), 0); 532 | for (int i = 0; i < n; ++i) ++cnt[rk[i]]; 533 | for (int i = 1; i < n; ++i) cnt[i] += cnt[i - 1]; 534 | for (int i = n - 1; i >= 0; --i) sa[--cnt[rk[tmp[i]]]] = tmp[i]; 535 | swap(rk, tmp); 536 | rk[sa[0]] = 0; 537 | for (int i = 1; i < n; ++i) 538 | rk[sa[i]] = rk[sa[i - 1]] + (tmp[sa[i - 1]] < tmp[sa[i]] || sa[i - 1] + k == n || tmp[sa[i - 1] + k] < tmp[sa[i] + k]); 539 | k *= 2; 540 | } 541 | for (int i = 0, j = 0; i < n; ++i) { 542 | if (rk[i] == 0) { 543 | j = 0; 544 | } else { 545 | for (j -= j > 0; i + j < n && sa[rk[i] - 1] + j < n && s[i + j] == s[sa[rk[i] - 1] + j];) ++j; 546 | lc[rk[i] - 1] = j; 547 | } 548 | } 549 | } 550 | }; 551 | ``` 552 | -------------------------------------------------------------------------------- /4-Math.md: -------------------------------------------------------------------------------- 1 | ## Math 2 | 3 | ### Safe Multiplication & Fast Exponentiation 4 | 5 | ```cpp 6 | // Use if modulus exceeds INT_MAX 7 | i64 mul(i64 a, i64 b, i64 p) { 8 | i64 ans = 0; 9 | for (a %= p; b; b >>= 1, a = (a << 1) % p) 10 | if (b & 1) ans = (ans + a) % p; 11 | return ans; 12 | } 13 | 14 | // O(1) 15 | i64 mul(i64 a, i64 b, i64 p) { 16 | return (i64)(__int128(a) * b % p); 17 | } 18 | 19 | i64 qk(i64 a, i64 b, i64 p) { 20 | i64 ans = 1 % p; 21 | for (a %= p; b; b >>= 1, a = a * a % p) 22 | if (b & 1) ans = ans * a % p; 23 | return ans; 24 | } 25 | 26 | // If modulus exceeds INT_MAX 27 | i64 qk(i64 a, i64 b, i64 p) { 28 | i64 ans = 1 % p; 29 | for (a %= p; b; b >>= 1, a = mul(a, a, p)) 30 | if (b & 1) ans = mul(ans, a, p); 31 | return ans; 32 | } 33 | 34 | // Decimal fast exponentiation 35 | i64 qk(i64 a, const string& b, i64 p) { 36 | i64 ans = 1; 37 | for (int i = b.size() - 1; i >= 0; i--) { 38 | ans = ans * qk(a, b[i] - '0', p) % p; 39 | a = qk(a, 10, p); 40 | } 41 | return ans; 42 | } 43 | ``` 44 | 45 | ### Matrix Fast Exponentiation 46 | 47 | ```cpp 48 | const int M_SZ = 3; 49 | 50 | using Mat = array, M_SZ>; 51 | using Vec = array; 52 | 53 | #define rep2 for (int i = 0; i < M_SZ; i++) for (int j = 0; j < M_SZ; j++) 54 | 55 | void zero(Mat& a) { rep2 a[i][j] = 0; } 56 | void one(Mat& a) { rep2 a[i][j] = (i == j); } 57 | 58 | Vec mul(const Mat& a, const Vec& b, i64 p) { 59 | Vec ans; 60 | fill(ans.begin(), ans.end(), 0); 61 | rep2 { (ans[i] += a[i][j] * b[j]) %= p; } 62 | return ans; 63 | } 64 | 65 | Mat mul(const Mat& a, const Mat& b, i64 p) { 66 | Mat ans; zero(ans); 67 | rep2 if (a[i][j]) for (int k = 0; k < M_SZ; k++) { 68 | (ans[i][k] += a[i][j] * b[j][k]) %= p; 69 | } 70 | return ans; 71 | } 72 | 73 | Mat qk(Mat a, i64 b, i64 p) { 74 | Mat ans; one(ans); 75 | for (; b; b >>= 1) { 76 | if (b & 1) ans = mul(a, ans, p); 77 | a = mul(a, a, p); 78 | } 79 | return ans; 80 | } 81 | 82 | // Decimal fast exponentiation 83 | Mat qk(Mat a, const string& b, i64 p) { 84 | Mat ans; one(ans); 85 | for (int i = b.size() - 1; i >= 0; i--) { 86 | ans = mul(qk(a, b[i] - '0', p), ans, p); 87 | a = qk(a, 10, p); 88 | } 89 | return ans; 90 | } 91 | 92 | #undef rep2 93 | ``` 94 | 95 | ### Prime Test 96 | 97 | ```cpp 98 | bool isprime(int x) { 99 | if (x < 2) return false; 100 | for (int i = 2; i * i <= x; i++) { 101 | if (x % i == 0) return false; 102 | } 103 | return true; 104 | } 105 | ``` 106 | 107 | ### Sieves 108 | 109 | ```cpp 110 | struct sieve { 111 | static constexpr bool calc_phi = false; 112 | static constexpr bool calc_mu = false; 113 | 114 | vector vis; 115 | vector prime, spf, phi, mu; 116 | 117 | sieve(int N) : vis(N + 1), spf(N + 1), phi(calc_phi ? N + 1 : 0), mu(calc_mu ? N + 1 : 0) { 118 | vis[0] = vis[1] = spf[1] = 1; 119 | if constexpr (calc_phi) phi[1] = 1; 120 | if constexpr (calc_mu) mu[1] = 1; 121 | for (int i = 2; i <= N; i++) { 122 | if (!vis[i]) { 123 | prime.push_back(i); 124 | spf[i] = i; 125 | if constexpr (calc_phi) phi[i] = i - 1; 126 | if constexpr (calc_mu) mu[i] = -1; 127 | } 128 | for (int p : prime) { 129 | int d = i * p; 130 | if (d > N) break; 131 | vis[d] = true; 132 | spf[d] = p; 133 | if (i % p == 0) { 134 | if constexpr (calc_phi) phi[d] = phi[i] * p; 135 | if constexpr (calc_mu) mu[d] = 0; 136 | break; 137 | } else { 138 | if constexpr (calc_phi) phi[d] = phi[i] * (p - 1); 139 | if constexpr (calc_mu) mu[d] = -mu[i]; 140 | } 141 | } 142 | } 143 | } 144 | 145 | bool is_prime(int x) { return !vis[x]; } 146 | 147 | vector> factorize(int x) { 148 | vector> v; 149 | while (x > 1) { 150 | int p = spf[x]; 151 | int cnt = 0; 152 | while (x % p == 0) x /= p, cnt++; 153 | v.emplace_back(p, cnt); 154 | } 155 | return v; 156 | } 157 | 158 | vector divisors(int x) { 159 | vector v = {1}; 160 | for (auto [p, cnt] : factorize(x)) { 161 | int m = v.size(); 162 | for (int i = 0; i < m; i++) { 163 | int y = 1; 164 | for (int j = 0; j < cnt; j++) { 165 | y *= p; 166 | v.push_back(v[i] * y); 167 | } 168 | } 169 | } 170 | sort(v.begin(), v.end()); 171 | return v; 172 | } 173 | }; 174 | ``` 175 | 176 | ### Interval Sieve 177 | 178 | ```cpp 179 | // a, b <= 1e13, b - a <= 1e6 180 | bool vis_small[N], vis_big[N]; 181 | i64 prime[N]; 182 | int tot = 0; 183 | 184 | void get_prime(i64 a, i64 b) { 185 | i64 c = ceil(sqrt(b)); 186 | for (i64 i = 2; i <= c; i++) { 187 | if (!vis_small[i]) { 188 | for (i64 j = i * i; j <= c; j += i) { 189 | vis_small[j] = 1; 190 | } 191 | for (i64 j = max(i, (a + i - 1) / i) * i; j <= b; j += i) { 192 | vis_big[j - a] = 1; 193 | } 194 | } 195 | } 196 | for (int i = max(0LL, 2 - a); i <= b - a; i++) { 197 | if (!vis_big[i]) prime[tot++] = i + a; 198 | } 199 | } 200 | ``` 201 | 202 | ### Find Divisors 203 | 204 | ```cpp 205 | // O(sqrt(n)) 206 | vector divisors(int x) { 207 | vector v; 208 | for (int i = 1; i * i <= x; i++) { 209 | if (x % i == 0) { 210 | v.push_back(i); 211 | if (x / i != i) v.push_back(x / i); 212 | } 213 | } 214 | sort(v.begin(), v.end()); 215 | return v; 216 | } 217 | ``` 218 | 219 | ### Prime Factorization 220 | 221 | ```cpp 222 | // O(sqrt(n)) 223 | vector> factorize(int x) { 224 | vector> v; 225 | for (int i = 2; i * i <= x; i++) { 226 | if (x % i == 0) { 227 | int cnt = 0; 228 | while (x % i == 0) x /= i, cnt++; 229 | v.emplace_back(i, cnt); 230 | } 231 | } 232 | if (x != 1) v.emplace_back(x, 1); 233 | return v; 234 | } 235 | ``` 236 | 237 | ### Miller & Pollard 238 | 239 | ```cpp 240 | i64 mul(i64 a, i64 b, i64 p) { return (i64)(__int128(a) * b % p); } 241 | 242 | i64 qk(i64 a, i64 b, i64 p) { 243 | i64 ans = 1 % p; 244 | for (a %= p; b; b >>= 1, a = mul(a, a, p)) 245 | if (b & 1) ans = mul(ans, a, p); 246 | return ans; 247 | } 248 | 249 | // O(logn) 250 | // Only need to check 2, 7, 61 for 32-bit ints 251 | bool isprime(i64 n) { 252 | if (n < 3) return n == 2; 253 | if (!(n & 1)) return false; 254 | i64 d = n - 1, r = 0; 255 | while (!(d & 1)) d >>= 1, r++; 256 | static vector A = {2, 325, 9375, 28178, 450775, 9780504, 1795265022}; 257 | for (i64 a : A) { 258 | i64 t = qk(a, d, n); 259 | if (t <= 1 || t == n - 1) continue; 260 | for (int i = 0; i < r; i++) { 261 | t = mul(t, t, n); 262 | if (t == 1) return false; 263 | if (t == n - 1) break; 264 | } 265 | if (t != 1 && t != n - 1) return false; 266 | } 267 | return true; 268 | } 269 | 270 | mt19937_64 rng(42); 271 | 272 | i64 pollard_rho(i64 n, i64 c) { 273 | i64 x = rng() % (n - 1) + 1, y = x; 274 | auto f = [&](i64 v) { 275 | i64 t = mul(v, v, n) + c; 276 | return t < n ? t : t - n; 277 | }; 278 | for (;;) { 279 | x = f(x); y = f(f(y)); 280 | if (x == y) return n; 281 | i64 d = gcd(abs(x - y), n); 282 | if (d != 1) return d; 283 | } 284 | } 285 | 286 | vector> factorize(i64 x) { 287 | if (x <= 1) return {}; 288 | map mp; 289 | function f = [&](i64 n) { 290 | if (n == 4) { mp[2] += 2; return; } 291 | if (isprime(n)) { mp[n]++; return; } 292 | i64 p = n, c = 19260817; 293 | while (p == n) p = pollard_rho(n, --c); 294 | f(p); f(n / p); 295 | }; 296 | f(x); 297 | return vector>(mp.begin(), mp.end()); 298 | } 299 | ``` 300 | 301 | ### Euler's Totient Function 302 | 303 | ```cpp 304 | // Prerequisite: Prime Factorization 305 | int phi(int x) { 306 | int ret = x; 307 | for (auto& [f, _] : factorize(x)) ret = ret / f * (f - 1); 308 | return ret; 309 | } 310 | ``` 311 | 312 | ### Extended Euclidean 313 | 314 | ```cpp 315 | // ax + by = gcd(a, b) 316 | // return {gcd, x, y} 317 | array exgcd(i64 a, i64 b) { 318 | if (b == 0) return {a, 1, 0}; 319 | auto [d, x, y] = exgcd(b, a % b); 320 | return {d, y, x - a / b * y}; 321 | } 322 | ``` 323 | 324 | ### Euclidean-like Functions 325 | 326 | ```cpp 327 | // f(a,b,c,n) = ∑(i=[0,n]) (ai+b)/c 328 | // g(a,b,c,n) = ∑(i=[0,n]) i*((ai+b)/c) 329 | // h(a,b,c,n) = ∑(i=[0,n]) ((ai+b)/c)^2 330 | i64 f(i64 a, i64 b, i64 c, i64 n); 331 | i64 g(i64 a, i64 b, i64 c, i64 n); 332 | i64 h(i64 a, i64 b, i64 c, i64 n); 333 | 334 | i64 f(i64 a, i64 b, i64 c, i64 n) { 335 | if (n < 0) return 0; 336 | i64 m = (a * n + b) / c; 337 | if (a >= c || b >= c) { 338 | return (a / c) * n * (n + 1) / 2 339 | + (b / c) * (n + 1) 340 | + f(a % c, b % c, c, n); 341 | } else { 342 | return n * m - f(c, c - b - 1, a, m - 1); 343 | } 344 | } 345 | 346 | i64 g(i64 a, i64 b, i64 c, i64 n) { 347 | if (n < 0) return 0; 348 | i64 m = (a * n + b) / c; 349 | if (a >= c || b >= c) { 350 | return (a / c) * n * (n + 1) * (2 * n + 1) / 6 351 | + (b / c) * n * (n + 1) / 2 352 | + g(a % c, b % c, c, n); 353 | } else { 354 | return (n * (n + 1) * m 355 | - f(c, c - b - 1, a, m - 1) 356 | - h(c, c - b - 1, a, m - 1)) / 2; 357 | } 358 | } 359 | 360 | i64 h(i64 a, i64 b, i64 c, i64 n) { 361 | if (n < 0) return 0; 362 | i64 m = (a * n + b) / c; 363 | if (a >= c || b >= c) { 364 | return (a / c) * (a / c) * n * (n + 1) * (2 * n + 1) / 6 365 | + (b / c) * (b / c) * (n + 1) 366 | + (a / c) * (b / c) * n * (n + 1) 367 | + h(a % c, b % c, c, n) 368 | + 2 * (a / c) * g(a % c, b % c, c, n) 369 | + 2 * (b / c) * f(a % c, b % c, c, n); 370 | } else { 371 | return n * m * (m + 1) 372 | - 2 * g(c, c - b - 1, a, m - 1) 373 | - 2 * f(c, c - b - 1, a, m - 1) 374 | - f(a, b, c, n); 375 | } 376 | } 377 | ``` 378 | 379 | ### Modular Inverse 380 | 381 | ```cpp 382 | i64 inv(i64 x) { return qk(x, md - 2, md); } 383 | 384 | // EXGCD 385 | // Inverse exists iff gcd(a, p) = 1 386 | i64 inv(i64 a, i64 p) { 387 | auto [d, x, y] = exgcd(a, p); 388 | if (d == 1) return (x % p + p) % p; 389 | return -1; 390 | } 391 | 392 | // Inverse Table 393 | i64 inv[N]; 394 | 395 | void init_inv() { 396 | inv[1] = 1; 397 | for (int i = 2; i < N; i++) { 398 | inv[i] = 1LL * (md - md / i) * inv[md % i] % md; 399 | } 400 | } 401 | ``` 402 | 403 | ### Binomial Coefficient 404 | 405 | ```cpp 406 | // Pascal's Triangle 407 | i64 C[N][N]; 408 | 409 | void initC() { 410 | C[0][0] = 1; 411 | for (int i = 1; i < N; i++) { 412 | C[i][0] = 1; 413 | for (int j = 1; j <= i; j++) { 414 | C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % md; 415 | } 416 | } 417 | } 418 | 419 | // Fast Binomial Coefficient 420 | struct Factorial { 421 | static constexpr int md = 1e9 + 7; 422 | vector f, g; 423 | 424 | Factorial(int N) { 425 | N *= 2; 426 | f.resize(N + 1); 427 | g.resize(N + 1); 428 | f[0] = 1; 429 | for (int i = 1; i <= N; i++) { 430 | f[i] = 1LL * f[i - 1] * i % md; 431 | } 432 | g[N] = pow(f[N], md - 2); 433 | for (int i = N - 1; i >= 0; i--) { 434 | g[i] = 1LL * g[i + 1] * (i + 1) % md; 435 | } 436 | } 437 | 438 | int pow(int a, int b) { 439 | int r = 1; 440 | for (; b; b >>= 1, a = 1LL * a * a % md) { 441 | if (b & 1) r = 1LL * r * a % md; 442 | } 443 | return r; 444 | } 445 | 446 | int fac(int n) { return f[n]; } 447 | 448 | int ifac(int n) { return g[n]; } 449 | 450 | int inv(int n) { return 1LL * f[n - 1] * g[n] % md; } 451 | 452 | int comb(int n, int m) { 453 | if (n < m || m < 0) return 0; 454 | return 1LL * f[n] * g[m] % md * g[n - m] % md; 455 | } 456 | 457 | int perm(int n, int m) { 458 | if (n < m || m < 0) return 0; 459 | return 1LL * f[n] * g[n - m] % md; 460 | } 461 | 462 | int comb_rep(int n, int m) { return comb(n + m - 1, m); } 463 | 464 | int catalan(int n) { return (comb(2 * n, n) - comb(2 * n, n - 1) + md) % md; } 465 | }; 466 | 467 | // Lucas Theorem 468 | i64 C(i64 n, i64 m) { 469 | if (n < m || m < 0) return 0; 470 | if (n < md && m < md) return fac[n] * ifac[m] % md * ifac[n - m] % md; 471 | return C(n / md, m / md) * C(n % md, m % md) % md; 472 | } 473 | ``` 474 | 475 | ### Stirling Numbers 476 | 477 | ```cpp 478 | // 2nd kind: #ways to partition n objects into k non-empty subsets 479 | i64 S[N][N]; 480 | void initS() { 481 | S[0][0] = 1; 482 | for (int i = 1; i < N; i++) { 483 | for (int j = 1; j <= i; j++) { 484 | S[i][j] = (j * S[i - 1][j] + S[i - 1][j - 1]) % md; 485 | } 486 | } 487 | } 488 | 489 | // 1st kind: #ways to arrange n objects into k non-empty cycles 490 | i64 s[N][N]; 491 | void inits1() { 492 | s[0][0] = 1; 493 | for (int i = 1; i < N; i++) { 494 | for (int j = 1; j <= i; j++) { 495 | s[i][j] = ((i - 1) * s[i - 1][j] + s[i - 1][j - 1]) % md; 496 | } 497 | } 498 | } 499 | ``` 500 | 501 | ### Cantor Expansion 502 | 503 | ```cpp 504 | // Requires pre-processing of factorials 505 | int cantor(vector& s) { 506 | int n = s.size(), ans = 0; 507 | for (int i = 0; i < n - 1; i++) { 508 | int cnt = 0; 509 | for (int j = i + 1; j < n; j++) { 510 | if (s[j] < s[i]) cnt++; 511 | } 512 | ans += cnt * fac[n - i - 1]; 513 | } 514 | return ans + 1; 515 | } 516 | 517 | vector inv_cantor(int x, int n) { 518 | x--; 519 | vector ans(n), rk(n); 520 | iota(rk.begin(), rk.end(), 1); 521 | for (int i = 0; i < n; i++) { 522 | int t = x / fac[n - i - 1]; 523 | x %= fac[n - i - 1]; 524 | ans[i] = rk[t]; 525 | for (int j = t; rk[j] < n; j++) { 526 | rk[j] = rk[j + 1]; 527 | } 528 | } 529 | return ans; 530 | } 531 | ``` 532 | 533 | ### Gauss-Jordan Elimination 534 | 535 | + Floating-point version 536 | 537 | ```cpp 538 | // n: number of equations, m: number of variables, a: augmented matrix of size n*(m+1) 539 | const double EPS = 1e-8; 540 | 541 | int gauss(vector> a, vector& ans) { 542 | int n = (int)a.size(), m = (int)a[0].size() - 1; 543 | vector pos(m, -1); 544 | double det = 1; 545 | int rank = 0; 546 | for (int r = 0, c = 0; r < n && c < m; ++c) { 547 | int k = r; 548 | for (int i = r; i < n; i++) 549 | if (abs(a[i][c]) > abs(a[k][c])) k = i; 550 | if (abs(a[k][c]) < EPS) { 551 | det = 0; 552 | continue; 553 | } 554 | swap(a[r], a[k]); 555 | if (r != k) det = -det; 556 | det *= a[r][c]; 557 | pos[c] = r; 558 | for (int i = 0; i < n; i++) { 559 | if (i != r && abs(a[i][c]) > EPS) { 560 | double t = a[i][c] / a[r][c]; 561 | for (int j = c; j <= m; j++) a[i][j] -= a[r][j] * t; 562 | } 563 | } 564 | ++r; 565 | ++rank; 566 | } 567 | ans.assign(m, 0); 568 | for (int i = 0; i < m; i++) { 569 | if (pos[i] != -1) ans[i] = a[pos[i]][m] / a[pos[i]][i]; 570 | } 571 | for (int i = 0; i < n; i++) { 572 | double sum = 0; 573 | for (int j = 0; j < m; j++) sum += ans[j] * a[i][j]; 574 | if (abs(sum - a[i][m]) > EPS) return -1; // no solution 575 | } 576 | for (int i = 0; i < m; i++) 577 | if (pos[i] == -1) return 2; // infinite solutions 578 | return 1; // unique solution 579 | } 580 | ``` 581 | 582 | + XOR Equations 583 | 584 | ```cpp 585 | const int N = 2010; 586 | 587 | int gauss(int n, int m, vector> a, bitset& ans) { 588 | vector pos(m, -1); 589 | for (int r = 0, c = 0; r < n && c < m; ++c) { 590 | int k = r; 591 | while (k < n && !a[k][c]) k++; 592 | if (k == n) continue; 593 | swap(a[r], a[k]); 594 | pos[c] = r; 595 | for (int i = 0; i < n; i++) 596 | if (i != r && a[i][c]) a[i] ^= a[r]; 597 | ++r; 598 | } 599 | ans.reset(); 600 | for (int i = 0; i < m; i++) { 601 | if (pos[i] != -1) ans[i] = a[pos[i]][m]; 602 | } 603 | for (int i = 0; i < n; i++) 604 | if (((ans & a[i]).count() & 1) != a[i][m]) return -1; // no solution 605 | for (int i = 0; i < m; i++) 606 | if (pos[i] == -1) return 2; // infinite solutions 607 | return 1; // unique solution 608 | } 609 | ``` 610 | 611 | ### Linear Basis 612 | 613 | ```cpp 614 | struct Basis { 615 | vector a; 616 | void insert(i64 x) { 617 | x = minxor(x); 618 | if (!x) return; 619 | for (i64& i : a) 620 | if ((i ^ x) < i) i ^= x; 621 | a.push_back(x); 622 | sort(a.begin(), a.end()); 623 | } 624 | bool can(i64 x) { return !minxor(x); } 625 | i64 maxxor(i64 x = 0) { 626 | for (i64 i : a) x = max(x, x ^ i); 627 | return x; 628 | } 629 | i64 minxor(i64 x = 0) { 630 | for (i64 i : a) x = min(x, x ^ i); 631 | return x; 632 | } 633 | i64 kth(i64 k) { // 1st is 0 634 | int sz = a.size(); 635 | if (k > (1LL << sz)) return -1; 636 | k--; 637 | i64 ans = 0; 638 | for (int i = 0; i < sz; i++) 639 | if (k >> i & 1) ans ^= a[i]; 640 | return ans; 641 | } 642 | }; 643 | ``` 644 | 645 | ### Chinese Remainder Theorem 646 | 647 | ```cpp 648 | // Prerequisite: exgcd 649 | i64 excrt(const vector>& a) { 650 | auto [m, r] = a[0]; 651 | for (int i = 1; i < a.size(); i++) { 652 | auto [m1, r1] = a[i]; 653 | auto [d, x, y] = exgcd(m, m1); 654 | if ((r1 - r) % d) return -1; 655 | x = mul(x, (r1 - r) / d, m1 / d); 656 | r += x * m; 657 | m = m / d * m1; 658 | r %= m; 659 | } 660 | return r >= 0 ? r : r + m; 661 | } 662 | ``` 663 | 664 | ### Primitive Root 665 | 666 | ```cpp 667 | // Prerequisite: Prime Factorization 668 | i64 primitive_root(i64 p) { 669 | vector> facs = factorize(p - 1); 670 | for (i64 i = 2; i < p; i++) { 671 | bool flag = true; 672 | for (auto& [x, _] : facs) { 673 | if (qk(i, (p - 1) / x, p) == 1) { 674 | flag = false; 675 | break; 676 | } 677 | } 678 | if (flag) return i; 679 | } 680 | return -1; 681 | } 682 | ``` 683 | 684 | ### Discrete Logarithm 685 | 686 | ```cpp 687 | // a^x = b (mod p), where p is a prime number 688 | i64 BSGS(i64 a, i64 b, i64 p) { 689 | a %= p; 690 | if (!a && !b) return 1; 691 | if (!a) return -1; 692 | map mp; 693 | i64 m = ceil(sqrt(p)), v = 1; 694 | for (int i = 1; i <= m; i++) { 695 | (v *= a) %= p; 696 | mp[v * b % p] = i; 697 | } 698 | i64 vv = v; 699 | for (int i = 1; i <= m; i++) { 700 | auto it = mp.find(vv); 701 | if (it != mp.end()) return i * m - it->second; 702 | (vv *= v) %= p; 703 | } 704 | return -1; 705 | } 706 | 707 | // Modulus can be non-prime 708 | i64 exBSGS(i64 a, i64 b, i64 p) { 709 | a %= p; b %= p; 710 | if (a == 0) return b > 1 ? -1 : (b == 0 && p != 1); 711 | i64 c = 0, q = 1; 712 | for (;;) { 713 | i64 g = gcd(a, p); 714 | if (g == 1) break; 715 | if (b == 1) return c; 716 | if (b % g) return -1; 717 | ++c; b /= g; p /= g; q = a / g * q % p; 718 | } 719 | map mp; 720 | i64 m = ceil(sqrt(p)), v = 1; 721 | for (int i = 1; i <= m; i++) { 722 | (v *= a) %= p; 723 | mp[v * b % p] = i; 724 | } 725 | for (int i = 1; i <= m; i++) { 726 | (q *= v) %= p; 727 | auto it = mp.find(q); 728 | if (it != mp.end()) return i * m - it->second + c; 729 | } 730 | return -1; 731 | } 732 | 733 | // Given x, b, p, find a 734 | i64 SGSB(i64 x, i64 b, i64 p) { 735 | i64 g = primitive_root(p); 736 | return qk(g, BSGS(qk(g, x, p), b, p), p); 737 | } 738 | ``` 739 | 740 | ### Sqrt Decomposition 741 | 742 | ```cpp 743 | // When floor(n/i) = v, the range of i is [l,r] 744 | vector> quotients(i64 n) { 745 | vector> res; 746 | i64 h = sqrt(n); 747 | res.reserve(2 * h - (h == n / h)); 748 | for (i64 l = 1, v, r; l <= n; l = r + 1) { 749 | v = n / l; 750 | r = n / v; 751 | res.push_back({l, r, v}); 752 | } 753 | return res; 754 | } 755 | ``` 756 | 757 | ### Quadratic Residue 758 | 759 | ```cpp 760 | i64 Quadratic_residue(i64 a) { 761 | if (a == 0) return 0; 762 | i64 b; 763 | do b = rng() % md; 764 | while (qk(b, (md - 1) >> 1, md) != md - 1); 765 | i64 s = md - 1, t = 0, f = 1; 766 | while (!(s & 1)) s >>= 1, t++, f <<= 1; 767 | t--, f >>= 1; 768 | i64 x = qk(a, (s + 1) >> 1, md), inv_a = qk(a, md - 2, md); 769 | while (t) { 770 | f >>= 1; 771 | if (qk(inv_a * x % md * x % md, f, md) != 1) { 772 | (x *= qk(b, s, md)) %= md; 773 | } 774 | t--, s <<= 1; 775 | } 776 | if (x * x % md != a) return -1; 777 | return min(x, md - x); 778 | } 779 | ``` 780 | 781 | ### FFT & NTT & FWT 782 | 783 | + FFT 784 | 785 | ```cpp 786 | const double PI = acos(-1); 787 | using cp = complex; 788 | 789 | int n1, n2, n, k, rev[N]; 790 | 791 | void fft(vector& a, int p) { 792 | for (int i = 0; i < n; i++) if (i < rev[i]) swap(a[i], a[rev[i]]); 793 | for (int h = 1; h < n; h <<= 1) { 794 | cp wn(cos(PI / h), p * sin(PI / h)); 795 | for (int i = 0; i < n; i += (h << 1)) { 796 | cp w(1, 0); 797 | for (int j = 0; j < h; j++, w *= wn) { 798 | cp x = a[i + j], y = w * a[i + j + h]; 799 | a[i + j] = x + y, a[i + j + h] = x - y; 800 | } 801 | } 802 | } 803 | if (p == -1) for (int i = 0; i < n; i++) a[i] /= n; 804 | } 805 | 806 | void go(vector& a, vector& b) { 807 | n = 1, k = 0; 808 | while (n <= n1 + n2) n <<= 1, k++; 809 | a.resize(n); b.resize(n); 810 | for (int i = 0; i < n; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (k - 1)); 811 | fft(a, 1); fft(b, 1); 812 | for (int i = 0; i < n; i++) a[i] *= b[i]; 813 | fft(a, -1); 814 | } 815 | ``` 816 | 817 | + NTT 818 | 819 | ```cpp 820 | const int md = 998244353, G = 3, IG = 332748118; 821 | 822 | int n1, n2, n, k, rev[N]; 823 | 824 | void ntt(vector& a, int p) { 825 | for (int i = 0; i < n; i++) if (i < rev[i]) swap(a[i], a[rev[i]]); 826 | for (int h = 1; h < n; h <<= 1) { 827 | i64 wn = qk(p == 1 ? G : IG, (md - 1) / (h << 1), md); 828 | for (int i = 0; i < n; i += (h << 1)) { 829 | i64 w = 1; 830 | for (int j = 0; j < h; j++, (w *= wn) %= md) { 831 | i64 x = a[i + j], y = w * a[i + j + h] % md; 832 | a[i + j] = (x + y) % md, a[i + j + h] = (x - y + md) % md; 833 | } 834 | } 835 | } 836 | if (p == -1) { 837 | i64 ninv = qk(n, md - 2, md); 838 | for (int i = 0; i < n; i++) (a[i] *= ninv) %= md; 839 | } 840 | } 841 | 842 | void go(vector& a, vector& b) { 843 | n = 1, k = 0; 844 | while (n <= n1 + n2) n <<= 1, k++; 845 | a.resize(n); b.resize(n); 846 | for (int i = 0; i < n; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (k - 1)); 847 | ntt(a, 1); ntt(b, 1); 848 | for (int i = 0; i < n; i++) (a[i] *= b[i]) %= md; 849 | ntt(a, -1); 850 | } 851 | ``` 852 | 853 | + FWT 854 | 855 | ```cpp 856 | void AND(i64& a, i64& b) { a += b; } 857 | void rAND(i64& a, i64& b) { a -= b; } 858 | 859 | void OR(i64& a, i64& b) { b += a; } 860 | void rOR(i64& a, i64& b) { b -= a; } 861 | 862 | void XOR(i64& a, i64& b) { 863 | i64 x = a, y = b; 864 | a = (x + y) % md; 865 | b = (x - y + md) % md; 866 | } 867 | void rXOR(i64& a, i64& b) { 868 | static i64 inv2 = (md + 1) / 2; 869 | i64 x = a, y = b; 870 | a = (x + y) * inv2 % md; 871 | b = (x - y + md) * inv2 % md; 872 | } 873 | 874 | template 875 | void fwt(vector& a, int n, T f) { 876 | for (int d = 1; d < n; d <<= 1) { 877 | for (int i = 0; i < n; i += (d << 1)) { 878 | for (int j = 0; j < d; j++) { 879 | f(a[i + j], a[i + j + d]); 880 | } 881 | } 882 | } 883 | } 884 | ``` 885 | 886 | ### Numerical Integration 887 | 888 | ```cpp 889 | double simpson(double l, double r) { 890 | double c = (l + r) / 2; 891 | return (f(l) + 4 * f(c) + f(r)) * (r - l) / 6; 892 | } 893 | 894 | double asr(double l, double r, double eps, double S) { 895 | double mid = (l + r) / 2; 896 | double L = simpson(l, mid), R = simpson(mid, r); 897 | if (fabs(L + R - S) < 15 * eps) return L + R + (L + R - S) / 15; 898 | return asr(l, mid, eps / 2, L) + asr(mid, r, eps / 2, R); 899 | } 900 | 901 | double asr(double l, double r) { return asr(l, r, EPS, simpson(l, r)); } 902 | ``` 903 | 904 | ### Berlekamp-Massey 905 | 906 | ```cpp 907 | // given S[0..2n-1], find tr[0..n-1] 908 | // O(n^2) 909 | vector BM(vector S) { 910 | int n = S.size(), L = 0, m = 0; 911 | vector C(n), B(n), T; 912 | C[0] = B[0] = 1; 913 | i64 b = 1; 914 | for (int i = 0; i < n; i++) { 915 | m++; 916 | i64 d = S[i] % md; 917 | for (int j = 1; j <= L; j++) { 918 | d = (d + C[j] * S[i - j]) % md; 919 | } 920 | if (!d) continue; 921 | T = C; 922 | i64 coef = d * qk(b, md - 2, md) % md; 923 | for (int j = m; j < n; j++) { 924 | C[j] = (C[j] - coef * B[j - m]) % md; 925 | } 926 | if (2 * L > i) continue; 927 | L = i + 1 - L; 928 | B = T; 929 | b = d; 930 | m = 0; 931 | } 932 | C.resize(L + 1); 933 | C.erase(C.begin()); 934 | for (i64& x : C) x = (md - x) % md; 935 | return C; 936 | } 937 | 938 | // S[i] = sum_j tr[j] S[i-1-j] 939 | // given S[0..n-1] and tr[0..n-1], find S[k] 940 | // O(n^2 log k) 941 | i64 linearRec(vector S, vector tr, i64 k) { 942 | int n = tr.size(); 943 | auto combine = [&](vector a, vector b) { 944 | vector res(n * 2 + 1); 945 | for (int i = 0; i <= n; i++) { 946 | for (int j = 0; j <= n; j++) { 947 | (res[i + j] += a[i] * b[j]) %= md; 948 | } 949 | } 950 | for (int i = 2 * n; i > n; i--) { 951 | for (int j = 0; j < n; j++) { 952 | (res[i - 1 - j] += res[i] * tr[j]) %= md; 953 | } 954 | } 955 | res.resize(n + 1); 956 | return res; 957 | }; 958 | vector pol(n + 1), e(pol); 959 | pol[0] = e[1] = 1; 960 | for (++k; k; k /= 2) { 961 | if (k % 2) pol = combine(pol, e); 962 | e = combine(e, e); 963 | } 964 | i64 res = 0; 965 | for (int i = 0; i < n; i++) { 966 | (res += pol[i + 1] * S[i]) %= md; 967 | } 968 | return res; 969 | } 970 | ``` 971 | 972 | ### Lagrange Interpolation 973 | 974 | ```cpp 975 | // find the coefficients of f(x), O(n^2) 976 | template 977 | vector La(vector x, vector y) { 978 | int n = x.size(); 979 | vector ret(n), sum(n); 980 | ret[0] = y[0], sum[0] = 1; 981 | for (int i = 1; i < n; i++) { 982 | for (int j = n - 1; j >= i; j--) { 983 | y[j] = (y[j] - y[j - 1]) / (x[j] - x[j - i]); 984 | } 985 | for (int j = i; j; j--) { 986 | sum[j] = -sum[j] * x[i - 1] + sum[j - 1]; 987 | ret[j] += sum[j] * y[i]; 988 | } 989 | sum[0] = -sum[0] * x[i - 1]; 990 | ret[0] += sum[0] * y[i]; 991 | } 992 | return ret; 993 | } 994 | ``` 995 | -------------------------------------------------------------------------------- /5-Geometry.md: -------------------------------------------------------------------------------- 1 | ## Geometry 2 | 3 | ### 2D Geometry Basics 4 | 5 | ```cpp 6 | #define y1 qwq 7 | 8 | using ld = double; 9 | using V = complex; 10 | 11 | const ld eps = 1e-8; 12 | 13 | int sign(ld x) { return x < -eps ? -1 : x > eps; } 14 | 15 | ld dot(V a, V b) { return (conj(a) * b).real(); } 16 | ld det(V a, V b) { return (conj(a) * b).imag(); } 17 | 18 | ld to_rad(ld deg) { return deg / 180 * numbers::pi; } 19 | 20 | // quadrant 21 | int quad(V p) { 22 | int x = sign(p.real()), y = sign(p.imag()); 23 | if (x > 0 && y >= 0) return 1; 24 | if (x <= 0 && y > 0) return 2; 25 | if (x < 0 && y <= 0) return 3; 26 | if (x >= 0 && y < 0) return 4; 27 | assert(0); 28 | } 29 | 30 | // sorting by polar angle 31 | struct cmp_angle { 32 | V p; 33 | cmp_angle(V p = V()) : p(p) {} 34 | bool operator()(V a, V b) const { 35 | int qa = quad(a - p), qb = quad(b - p); 36 | if (qa != qb) return qa < qb; 37 | int s = sign(det(a - p, b - p)); 38 | return s ? s > 0 : abs(a - p) < abs(b - p); 39 | } 40 | }; 41 | 42 | // unit vector 43 | V unit(V p) { return sign(abs(p)) == 0 ? V(1, 0) : p / abs(p); } 44 | 45 | // rotate conterclockwise by r radians 46 | V rot(V p, ld r) { 47 | return p * polar(1.0, r); 48 | } 49 | V rot_ccw90(V p) { return p * V(0, 1); } 50 | V rot_cw90(V p) { return p * V(0, -1); } 51 | 52 | // point on segment, dot(...) <= 0 contains endpoints, < otherwise 53 | bool p_on_seg(V p, V a, V b) { 54 | return sign(det(p - a, b - a)) == 0 && sign(dot(p - a, p - b)) <= 0; 55 | } 56 | 57 | // point on ray, dot(...) >= 0 contains the endpoint, > otherwise 58 | bool p_on_ray(V p, V a, V b) { 59 | return sign(det(p - a, b - a)) == 0 && sign(dot(p - a, b - a)) >= 0; 60 | } 61 | 62 | // intersection of lines 63 | V intersect(V a, V b, V c, V d) { 64 | ld s1 = det(c - a, d - a), s2 = det(c - b, d - b); 65 | return (a * s2 - b * s1) / (s2 - s1); 66 | } 67 | 68 | // projection of a point onto a line 69 | V proj(V p, V a, V b) { 70 | return a + (b - a) * dot(b - a, p - a) / norm(b - a); 71 | } 72 | 73 | // symmetric point about a line 74 | V reflect(V p, V a, V b) { 75 | return proj(p, a, b) * 2.0 - p; 76 | } 77 | 78 | // closest point on segment 79 | V closest_point_on_seg(V p, V a, V b) { 80 | if (sign(dot(b - a, p - a)) < 0) return a; 81 | if (sign(dot(a - b, p - b)) < 0) return b; 82 | return proj(p, a, b); 83 | } 84 | 85 | // centroid 86 | V centroid(V a, V b, V c) { 87 | return (a + b + c) / 3.0; 88 | } 89 | 90 | // incenter 91 | V incenter(V a, V b, V c) { 92 | ld AB = abs(a - b), AC = abs(a - c), BC = abs(b - c); 93 | // ld r = abs(det(b - a, c - a)) / (AB + AC + BC); 94 | return (a * BC + b * AC + c * AB) / (AB + BC + AC); 95 | } 96 | 97 | // circumcenter 98 | V circumcenter(V a, V b, V c) { 99 | V mid1 = (a + b) / 2.0, mid2 = (a + c) / 2.0; 100 | // ld r = dist(a, b) * dist(b, c) * dist(c, a) / 2 / abs(det(b - a, c - a)); 101 | return intersect(mid1, mid1 + rot_ccw90(b - a), mid2, mid2 + rot_ccw90(c - a)); 102 | } 103 | 104 | // orthocenter 105 | V orthocenter(V a, V b, V c) { 106 | return centroid(a, b, c) * 3.0 - circumcenter(a, b, c) * 2.0; 107 | } 108 | 109 | // excenters (opposite to a, b, c) 110 | vector excenters(V a, V b, V c) { 111 | ld AB = abs(a - b), AC = abs(a - c), BC = abs(b - c); 112 | V p1 = (a * (-BC) + b * AC + c * AB) / (AB + AC - BC); 113 | V p2 = (a * BC + b * (-AC) + c * AB) / (AB - AC + BC); 114 | V p3 = (a * BC + b * AC + c * (-AB)) / (-AB + AC + BC); 115 | return {p1, p2, p3}; 116 | } 117 | ``` 118 | 119 | ### Polygons 120 | 121 | ```cpp 122 | // polygon area 123 | ld area(const vector& s) { 124 | ld ret = 0; 125 | for (int i = 0; i < s.size(); i++) { 126 | ret += det(s[i], s[(i + 1) % s.size()]); 127 | } 128 | return ret / 2; 129 | } 130 | 131 | // polygon centroid 132 | V centroid(const vector& s) { 133 | V c; 134 | for (int i = 0; i < s.size(); i++) { 135 | c = c + (s[i] + s[(i + 1) % s.size()]) * det(s[i], s[(i + 1) % s.size()]); 136 | } 137 | return c / 6.0 / area(s); 138 | } 139 | 140 | // point and polygon 141 | // 1 inside 0 on border -1 outside 142 | int inside(const vector& s, V p) { 143 | int cnt = 0; 144 | for (int i = 0; i < s.size(); i++) { 145 | V a = s[i], b = s[(i + 1) % s.size()]; 146 | if (p_on_seg(p, a, b)) return 0; 147 | if (sign(a.imag() - b.imag()) <= 0) swap(a, b); 148 | if (sign(p.imag() - a.imag()) > 0) continue; 149 | if (sign(p.imag() - b.imag()) <= 0) continue; 150 | cnt += sign(det(b - p, a - p)) > 0; 151 | } 152 | return (cnt & 1) ? 1 : -1; 153 | } 154 | 155 | // convex hull, points cannot be duplicated 156 | // det(...) < 0 allow point on edges det(...) <= 0 otherwise 157 | // will change the order of the input points 158 | vector convex_hull(vector& s) { 159 | // assert(s.size() >= 3); 160 | sort(s.begin(), s.end(), [](V &a, V &b) { 161 | return a.real() == b.real() ? a.imag() < b.imag() : a.real() < b.real(); 162 | }); 163 | vector ret(2 * s.size()); 164 | int sz = 0; 165 | for (int i = 0; i < s.size(); i++) { 166 | while (sz > 1 && sign(det(ret[sz - 1] - ret[sz - 2], s[i] - ret[sz - 2])) <= 0) sz--; 167 | ret[sz++] = s[i]; 168 | } 169 | int k = sz; 170 | for (int i = s.size() - 2; i >= 0; i--) { 171 | while (sz > k && sign(det(ret[sz - 1] - ret[sz - 2], s[i] - ret[sz - 2])) <= 0) sz--; 172 | ret[sz++] = s[i]; 173 | } 174 | ret.resize(sz - (s.size() > 1)); 175 | return ret; 176 | } 177 | 178 | // is convex? 179 | bool is_convex(const vector& s) { 180 | for (int i = 0; i < s.size(); i++) { 181 | int j = (i + 1) % s.size(), k = (i + 2) % s.size(); 182 | if (sign(det(s[j] - s[i], s[k] - s[i])) < 0) return false; 183 | } 184 | return true; 185 | } 186 | 187 | // point and convex hull 188 | // 1 inside 0 on border -1 outside 189 | int inside(const vector& s, V p) { 190 | for (int i = 0; i < s.size(); i++) { 191 | int j = (i + 1) % s.size(); 192 | if (sign(det(s[i] - p, s[j] - p)) < 0) return -1; 193 | if (p_on_seg(p, s[i], s[j])) return 0; 194 | } 195 | return 1; 196 | } 197 | 198 | // closest pair of points, sort by x-coordinate first 199 | // min_dist(s, 0, s.size()) 200 | ld min_dist(const vector& s, int l, int r) { 201 | if (r - l <= 5) { 202 | ld ret = 1e100; 203 | for (int i = l; i < r; i++) { 204 | for (int j = i + 1; j < r; j++) { 205 | ret = min(ret, abs(s[i] - s[j])); 206 | } 207 | } 208 | return ret; 209 | } 210 | int m = (l + r) >> 1; 211 | ld ret = min(min_dist(s, l, m), min_dist(s, m, r)); 212 | vector q; 213 | for (int i = l; i < r; i++) { 214 | if (abs(s[i].real() - s[m].real()) <= ret) q.push_back(s[i]); 215 | } 216 | sort(q.begin(), q.end(), [](auto& a, auto& b) { return a.imag() < b.imag(); }); 217 | for (int i = 1; i < q.size(); i++) { 218 | for (int j = i - 1; j >= 0 && q[j].imag() >= q[i].imag() - ret; j--) { 219 | ret = min(ret, abs(q[i] - q[j])); 220 | } 221 | } 222 | return ret; 223 | } 224 | ``` 225 | 226 | ### Circles 227 | 228 | ```cpp 229 | struct C { 230 | V o; 231 | ld r; 232 | C(V o, ld r) : o(o), r(r) {} 233 | }; 234 | 235 | // sector area, radius r, angle d 236 | ld area_sector(ld r, ld d) { return r * r * d / 2; } 237 | 238 | // find the tangent line to a circle and return the tangent point 239 | vector tangent_point(C c, V p) { 240 | ld k = c.r / abs(c.o - p); 241 | if (sign(k - 1) > 0) return {}; 242 | if (sign(k - 1) == 0) return {p}; 243 | V a = (p - c.o) * k; 244 | return {c.o + rot(a, acos(k)), c.o + rot(a, -acos(k))}; 245 | } 246 | 247 | vector circle_line_inter(C c, V a, V b) { 248 | V p = proj(c.o, a, b); 249 | ld d = abs(p - c.o); 250 | if (sign(d - c.r) > 0) return {}; 251 | if (sign(d - c.r) == 0) return {p}; 252 | ld l = sqrt(c.r * c.r - d * d); 253 | V v = unit(b - a) * l; 254 | return {p + v, p - v}; 255 | } 256 | 257 | // 0: disjoint 1: touch externally 2: intersect 3: touch internally 4: contain 258 | int circle_circle_relation(C c1, C c2) { 259 | ld d = abs(c1.o - c2.o); 260 | if (sign(d - c1.r - c2.r) > 0) return 0; 261 | if (sign(d - c1.r - c2.r) == 0) return 1; 262 | if (sign(d - abs(c1.r - c2.r)) < 0) return 4; 263 | if (sign(d - abs(c1.r - c2.r)) == 0) return 3; 264 | return 2; 265 | } 266 | 267 | vector circle_circle_inter(C c1, C c2) { 268 | if (c1.r < c2.r) swap(c1, c2); 269 | int rel = circle_circle_relation(c1, c2); 270 | if (rel == 0 || rel == 4) return {}; 271 | if (rel == 1 || rel == 3) return {c1.o + unit(c2.o - c1.o) * c1.r}; 272 | ld d = abs(c1.o - c2.o); 273 | ld a = (c1.r * c1.r + d * d - c2.r * c2.r) / 2 / d; 274 | V p = c1.o + (c2.o - c1.o) * a / d; 275 | V v = rot_ccw90(unit(c2.o - c1.o)) * sqrt(c1.r * c1.r - a * a); 276 | return {p + v, p - v}; 277 | } 278 | 279 | // min circle cover 280 | C min_circle_cover(vector a) { 281 | shuffle(a.begin(), a.end(), rng); 282 | V o = a[0]; 283 | ld r = 0; 284 | int n = a.size(); 285 | for (int i = 1; i < n; i++) if (sign(abs(a[i] - o) - r) > 0) { 286 | o = a[i]; r = 0; 287 | for (int j = 0; j < i; j++) if (sign(abs(a[j] - o) - r) > 0) { 288 | o = (a[i] + a[j]) / 2.0; 289 | r = abs(a[j] - o); 290 | for (int k = 0; k < j; k++) if (sign(abs(a[k] - o) - r) > 0) { 291 | o = circumcenter(a[i], a[j], a[k]); 292 | r = abs(a[k] - o); 293 | } 294 | } 295 | } 296 | return C(o, r); 297 | } 298 | ``` 299 | 300 | ### 3D Geometry 301 | 302 | ```cpp 303 | struct V { 304 | ld x, y, z; 305 | constexpr V(ld x = 0, ld y = 0, ld z = 0) : x(x), y(y), z(z) {} 306 | V operator+(V b) const { return V(x + b.x, y + b.y, z + b.z); } 307 | V operator-(V b) const { return V(x - b.x, y - b.y, z - b.z); } 308 | V operator*(ld k) const { return V(x * k, y * k, z * k); } 309 | V operator/(ld k) const { return V(x / k, y / k, z / k); } 310 | ld len() const { return sqrt(len2()); } 311 | ld len2() const { return x * x + y * y + z * z; } 312 | }; 313 | 314 | ostream& operator<<(ostream& os, V p) { return os << "(" << p.x << "," << p.y << "," << p.z << ")"; } 315 | istream& operator>>(istream& is, V& p) { return is >> p.x >> p.y >> p.z; } 316 | 317 | ld dist(V a, V b) { return (b - a).len(); } 318 | ld dot(V a, V b) { return a.x * b.x + a.y * b.y + a.z * b.z; } 319 | V det(V a, V b) { return V(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); } 320 | ld mix(V a, V b, V c) { return dot(a, det(b, c)); } 321 | ``` 322 | -------------------------------------------------------------------------------- /6-Misc.md: -------------------------------------------------------------------------------- 1 | ## Miscellaneous 2 | 3 | ### Sliding Window 4 | 5 | ```cpp 6 | // [start, end) 7 | // [l, r) 8 | void sliding_window(int start, int end, 9 | function add, 10 | function del, 11 | function f, 12 | function callback) { 13 | for (int l = start, r = start; r != end; callback(l, r)) 14 | for (add(r++); l != r && f(); del(l++)); 15 | } 16 | ``` 17 | 18 | ### Binary Search 19 | 20 | ```cpp 21 | // [l, r] 22 | template 23 | T min_left(T l, T r, F f) { 24 | while (l < r) { 25 | T p = l + (r - l) / 2; 26 | f(p) ? r = p : l = p + 1; 27 | } 28 | return l; 29 | } 30 | 31 | template 32 | T max_right(T l, T r, F f) { 33 | while (l < r) { 34 | T p = l + (r - l + 1) / 2; 35 | f(p) ? l = p : r = p - 1; 36 | } 37 | return l; 38 | } 39 | ``` 40 | 41 | ### Ternary Search 42 | 43 | ```cpp 44 | // for real numbers 45 | template > 46 | double ternary_search(double l, double r, F f, C cmp = C()) { 47 | for (int i = 0; i < 75; i++) { 48 | double x1 = (l * 5 + r * 4) / 9; 49 | double x2 = (l * 4 + r * 5) / 9; 50 | cmp(f(x1), f(x2)) ? r = x2 : l = x1; 51 | } 52 | return l; 53 | } 54 | 55 | // for integers 56 | template > 57 | T ternary_search(T l, T r, F f, C cmp = C()) { 58 | while (l < r - 2) { 59 | T x = l + (r - l) / 2; 60 | cmp(f(x), f(x + 1)) ? r = x + 1 : l = x; 61 | } 62 | auto bestval = f(l); 63 | T ans = l; 64 | for (T i = l + 1; i <= r; i++) { 65 | if (cmp(f(i), bestval)) bestval = f(i), ans = i; 66 | } 67 | return ans; 68 | } 69 | ``` 70 | 71 | ### Date 72 | 73 | ```cpp 74 | // 0 ~ 6 corresponds to Monday ~ Sunday 75 | int zeller(int y, int m, int d) { 76 | if (m <= 2) m += 12, y--; 77 | return (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7; 78 | } 79 | 80 | // date_to_int(1, 1, 1) = 1721426 81 | // date_to_int(2019, 10, 27) = 2458784 82 | int date_to_int(int y, int m, int d) { 83 | return 84 | 1461 * (y + 4800 + (m - 14) / 12) / 4 + 85 | 367 * (m - 2 - (m - 14) / 12 * 12) / 12 - 86 | 3 * ((y + 4900 + (m - 14) / 12) / 100) / 4 + 87 | d - 32075; 88 | } 89 | 90 | void int_to_date(int jd, int &y, int &m, int &d) { 91 | int x, n, i, j; 92 | 93 | x = jd + 68569; 94 | n = 4 * x / 146097; 95 | x -= (146097 * n + 3) / 4; 96 | i = (4000 * (x + 1)) / 1461001; 97 | x -= 1461 * i / 4 - 31; 98 | j = 80 * x / 2447; 99 | d = x - 2447 * j / 80; 100 | x = j / 11; 101 | m = j + 2 - 12 * x; 102 | y = 100 * (n - 49) + i + x; 103 | } 104 | ``` 105 | 106 | ### Subset Enumeration 107 | 108 | ```cpp 109 | // all strict subsets 110 | for (int t = (x - 1) & x; t; t = (t - 1) & x) 111 | 112 | // subsets of size k 113 | // Note: k cannot be 0 114 | void subset(int k, int n) { 115 | int t = (1 << k) - 1; 116 | while (t < (1 << n)) { 117 | // do something 118 | int x = t & -t, y = t + x; 119 | t = ((t & ~y) / x >> 1) | y; 120 | } 121 | } 122 | 123 | // enumerate supersets 124 | for (int t = (x + 1) | x; t < (1 << n); t = (t + 1) | x) 125 | ``` 126 | 127 | ### Sum Over Subsets DP 128 | 129 | ```cpp 130 | // sum over subsets 131 | for (int i = 0; i < k; i++) 132 | for (int s = 0; s < (1 << k); s++) 133 | if ((s >> i) & 1) dp[s] += dp[s - (1 << i)]; 134 | 135 | // sum over supersets 136 | for (int i = 0; i < k; i++) 137 | for (int s = 0; s < (1 << k); s++) 138 | if (!((s >> i) & 1)) dp[s] += dp[s + (1 << i)]; 139 | ``` 140 | 141 | ### Longest Increasing Subsequence 142 | 143 | ```cpp 144 | // dp[i]: the minimum value of the last element of a non-decreasing subsequence with length i+1 145 | template 146 | int lis(const vector& a) { 147 | vector dp(a.size() + 1, numeric_limits::max()); 148 | T mx = dp[0]; 149 | for (auto& x : a) *upper_bound(dp.begin(), dp.end(), x) = x; // use lower_bound for increasing 150 | int ans = 0; 151 | while (dp[ans] != mx) ++ans; 152 | return ans; 153 | } 154 | 155 | // output actual solution 156 | template 157 | vector lis(const vector& S) { 158 | if (S.empty()) return {}; 159 | vector prev(S.size()); 160 | using P = pair; 161 | vector

res; 162 | for (int i = 0; i < int(S.size()); i++) { 163 | // use lower_bound P{S[i], 0} for increasing 164 | auto it = upper_bound(res.begin(), res.end(), P{S[i], INT_MAX}); 165 | if (it == res.end()) res.emplace_back(), it = res.end() - 1; 166 | *it = {S[i], i}; 167 | prev[i] = it == res.begin() ? 0 : (it - 1)->second; 168 | } 169 | int L = res.size(), cur = res.back().second; 170 | vector ans(L); 171 | while (L--) ans[L] = cur, cur = prev[cur]; 172 | return ans; 173 | } 174 | ``` 175 | 176 | ### Divide and Conquer DP 177 | 178 | ```cpp 179 | vector dp(n), new_dp(n); 180 | 181 | // compute new_dp[l], ... new_dp[r] (inclusive) 182 | function compute = [&](int l, int r, int optl, int optr) { 183 | if (l > r) return; 184 | int mid = (l + r) >> 1; 185 | pair best = {LLONG_MAX, -1}; 186 | for (int j = optl; j <= min(mid, optr); j++) { 187 | best = min(best, {(j ? dp[j - 1] : 0) + C(j, mid), j}); 188 | } 189 | new_dp[mid] = best.first; 190 | int opt = best.second; 191 | compute(l, mid - 1, optl, opt); 192 | compute(mid + 1, r, opt, optr); 193 | }; 194 | 195 | for (int i = 0; i < n; i++) { 196 | dp[i] = C(0, i); 197 | } 198 | for (int i = 1; i <= k; i++) { 199 | compute(0, n - 1, 0, n - 1); 200 | swap(dp, new_dp); 201 | } 202 | // return dp[n - 1]; 203 | ``` 204 | 205 | ### Gray Code 206 | 207 | ```cpp 208 | int g(int n) { return n ^ (n >> 1); } 209 | 210 | int rev_g(int g) { 211 | int n = 0; 212 | for (; g; g >>= 1) n ^= g; 213 | return n; 214 | } 215 | ``` 216 | 217 | ### Digit DP 218 | 219 | ```cpp 220 | struct DigitDP { 221 | int n; 222 | vector a, b; 223 | vector dp; 224 | 225 | DigitDP(i64 x, i64 y) { 226 | while (x) { 227 | a.push_back(x % 10); 228 | x /= 10; 229 | } 230 | while (y) { 231 | b.push_back(y % 10); 232 | y /= 10; 233 | } 234 | n = b.size(); 235 | while (a.size() < n) a.push_back(0); 236 | dp.assign(n, -1); 237 | } 238 | 239 | i64 dfs(int i, bool tight_lo, bool tight_hi, bool zero) { 240 | if (i == -1) return 1; 241 | if (!tight_lo && !tight_hi && !zero && dp[i] != -1) return dp[i]; 242 | i64 res = 0; 243 | int lo = tight_lo ? a[i] : 0; 244 | int hi = tight_hi ? b[i] : 9; 245 | for (int d = lo; d <= hi; d++) { 246 | res += dfs(i - 1, tight_lo && d == lo, tight_hi && d == hi, zero && d == 0); 247 | } 248 | return tight_lo || tight_hi || zero ? res : dp[i] = res; 249 | } 250 | 251 | i64 count() { return dfs(n - 1, true, true, true); } 252 | }; 253 | ``` 254 | 255 | ### Random Set 256 | 257 | ```cpp 258 | vector randset(int l, int r, int k) { 259 | // assert(l <= r && k <= r - l + 1); 260 | unordered_map p; 261 | for (int i = l; i < l + k; i++) p[i] = i; 262 | for (int i = l; i < l + k; i++) { 263 | int j = randint(i, r); 264 | if (!p.count(j)) p[j] = j; 265 | swap(p[i], p[j]); 266 | } 267 | vector a(k); 268 | for (int i = 0; i < k; i++) a[i] = p[i + l]; 269 | return a; 270 | } 271 | ``` 272 | 273 | ### Expression Evaluation 274 | 275 | ```py 276 | print(input()) # Python2 277 | print(eval(input())) # Python3 278 | ``` 279 | 280 | ### Regex 281 | 282 | ```py 283 | import re 284 | 285 | pattern = r'hello' 286 | text = 'hello world' 287 | match = re.search(pattern, text) # or re.match(pattern, text) 288 | if match: 289 | print('Match found:', match.group(), match.start(), match.end()) 290 | else: 291 | print('No match') 292 | 293 | # identifier 294 | r'^[a-zA-Z_]\w*$' 295 | 296 | # email 297 | r'^[\w\.-]+@[\w\.-]+\.\w+$' 298 | 299 | # URL 300 | r'^(https?|ftp)://[^\s/$.?#].[^\s]*$' 301 | ``` 302 | 303 | ### Stress Test 304 | 305 | + *unix 306 | 307 | ```bash 308 | #!/bin/bash 309 | cd "$(dirname "${BASH_SOURCE[0]}")" 310 | 311 | g++ gen.cpp -o gen -O2 -std=c++17 312 | g++ my.cpp -o my -O2 -std=c++17 313 | g++ std.cpp -o std -O2 -std=c++17 314 | 315 | while true 316 | do 317 | ./gen > in.txt 318 | ./std < in.txt > stdout.txt 319 | ./my < in.txt > myout.txt 320 | 321 | if test $? -ne 0 322 | then 323 | printf "RE\n" 324 | exit 0 325 | fi 326 | 327 | if diff stdout.txt myout.txt 328 | then 329 | printf "AC\n" 330 | else 331 | printf "WA\n" 332 | exit 0 333 | fi 334 | done 335 | ``` 336 | 337 | + Windows 338 | 339 | ``` 340 | @echo off 341 | 342 | g++ gen.cpp -o gen.exe -O2 -std=c++17 343 | g++ my.cpp -o my.exe -O2 -std=c++17 344 | g++ std.cpp -o std.exe -O2 -std=c++17 345 | 346 | :loop 347 | gen.exe > in.txt 348 | std.exe < in.txt > stdout.txt 349 | my.exe < in.txt > myout.txt 350 | if errorlevel 1 ( 351 | echo RE 352 | pause 353 | exit 354 | ) 355 | fc stdout.txt myout.txt 356 | if errorlevel 1 ( 357 | echo WA 358 | pause 359 | exit 360 | ) 361 | goto loop 362 | ``` 363 | 364 | ### Safe std::vector 365 | 366 | ```cpp 367 | namespace std { 368 | template 369 | class vector_s : public vector { 370 | public: 371 | vector_s(size_t n = 0, const T& x = T()) : vector(n, x) {} 372 | T& operator [] (size_t n) { return this->at(n); } 373 | const T& operator [] (size_t n) const { return this->at(n); } 374 | }; 375 | } 376 | 377 | #define vector vector_s 378 | ``` 379 | 380 | ### More Hash 381 | 382 | ```cpp 383 | template 384 | struct pair_hash { 385 | size_t operator () (const pair& p) const { 386 | return hash()(p.first) * 19260817 + hash()(p.second); 387 | } 388 | }; 389 | 390 | unordered_set, pair_hash> st; 391 | unordered_map, int, pair_hash> mp; 392 | 393 | struct custom_hash { 394 | static uint64_t splitmix64(uint64_t x) { 395 | // http://xorshift.di.unimi.it/splitmix64.c 396 | x += 0x9e3779b97f4a7c15; 397 | x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; 398 | x = (x ^ (x >> 27)) * 0x94d049bb133111eb; 399 | return x ^ (x >> 31); 400 | } 401 | 402 | size_t operator()(uint64_t x) const { 403 | static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count(); 404 | return splitmix64(x + FIXED_RANDOM); 405 | } 406 | }; 407 | 408 | unordered_map safe_map; 409 | ``` 410 | 411 | ### Max/Min with Assignment 412 | 413 | ```cpp 414 | template bool umax(T& a, U b) { return a < b ? a = b, 1 : 0; } 415 | template bool umin(T& a, U b) { return a > b ? a = b, 1 : 0; } 416 | ``` 417 | 418 | ### Split and Join 419 | 420 | ```cpp 421 | vector split(const string& s, string sep) { 422 | size_t b = 0, e; 423 | vector res; 424 | while ((e = s.find(sep, b)) != string::npos) { 425 | res.push_back(s.substr(b, e - b)); 426 | b = e + sep.size(); 427 | } 428 | res.push_back(s.substr(b)); 429 | return res; 430 | } 431 | 432 | template 433 | string join(const vector& v, string sep) { 434 | stringstream ss; 435 | bool f = 0; 436 | for (const T& x : v) (f ? ss << sep : ss) << x, f = 1; 437 | return ss.str(); 438 | } 439 | ``` 440 | 441 | ### Coordinate Compressor 442 | 443 | ```cpp 444 | template 445 | struct CoordinateCompressor { 446 | vector v; 447 | CoordinateCompressor(const vector& a) : v(a) { 448 | sort(v.begin(), v.end()); 449 | v.erase(unique(v.begin(), v.end()), v.end()); 450 | } 451 | int operator()(const T& x) const { 452 | return lower_bound(v.begin(), v.end(), x) - v.begin(); 453 | } 454 | }; 455 | ``` 456 | 457 | ### Merge Same Items 458 | 459 | ```cpp 460 | template 461 | vector> norm(vector& v) { 462 | // sort(v.begin(), v.end()); 463 | vector> p; 464 | for (int i = 0; i < (int)v.size(); i++) { 465 | if (i == 0 || v[i] != v[i - 1]) 466 | p.emplace_back(v[i], 1); 467 | else 468 | p.back().second++; 469 | } 470 | return p; 471 | } 472 | ``` 473 | 474 | ### 2D Transformation 475 | 476 | ```cpp 477 | struct Transformation { 478 | int n, m; 479 | Transformation(int n, int m) : n(n), m(m) {} 480 | pair rotate_90(int x, int y) const { return {y, n - x - 1}; } 481 | pair rotate_180(int x, int y) const { return {n - x - 1, m - y - 1}; } 482 | pair rotate_270(int x, int y) const { return {m - y - 1, x}; } 483 | pair flip_horizontal(int x, int y) const { return {x, m - y - 1}; } 484 | pair flip_vertical(int x, int y) const { return {n - x - 1, y}; } 485 | pair flip_diagonal(int x, int y) const { return {y, x}; } 486 | pair flip_antidiagonal(int x, int y) const { return {m - y - 1, n - x - 1}; } 487 | }; 488 | ``` 489 | 490 | ### Priority Queue with Erase 491 | 492 | ```cpp 493 | template > 494 | struct heap { 495 | priority_queue, C> q1, q2; 496 | void push(const T& x) { q1.push(x); } 497 | void erase(const T& x) { q2.push(x); } 498 | T top() { 499 | while (q2.size() && q1.top() == q2.top()) q1.pop(), q2.pop(); 500 | return q1.top(); 501 | } 502 | void pop() { 503 | while (q2.size() && q1.top() == q2.top()) q1.pop(), q2.pop(); 504 | q1.pop(); 505 | } 506 | int size() const { return q1.size() - q2.size(); } 507 | }; 508 | ``` 509 | 510 | ### Fractions 511 | 512 | ```cpp 513 | template 514 | struct Frac { 515 | T x, y; 516 | 517 | Frac(const T& p = 0, const T& q = 1) { 518 | T d = gcd(p, q); 519 | x = p / d; 520 | y = q / d; 521 | if (y < 0) { 522 | x = -x; 523 | y = -y; 524 | } 525 | } 526 | 527 | Frac operator+(const Frac& b) { return Frac(x * b.y + y * b.x, y * b.y); } 528 | Frac operator-(const Frac& b) { return Frac(x * b.y - y * b.x, y * b.y); } 529 | Frac operator*(const Frac& b) { return Frac(x * b.x, y * b.y); } 530 | Frac operator/(const Frac& b) { return Frac(x * b.y, y * b.x); } 531 | 532 | bool operator==(const Frac& b) { return x * b.y == y * b.x; } 533 | bool operator!=(const Frac& b) { return !(*this == b); } 534 | bool operator<(const Frac& b) { return x * b.y < y * b.x; } 535 | bool operator>(const Frac& b) { return x * b.y > y * b.x; } 536 | bool operator<=(const Frac& b) { return !(*this > b); } 537 | bool operator>=(const Frac& b) { return !(*this < b); } 538 | 539 | Frac& operator+=(const Frac& b) { *this = *this + b; return *this; } 540 | Frac& operator-=(const Frac& b) { *this = *this - b; return *this; } 541 | Frac& operator*=(const Frac& b) { *this = *this * b; return *this; } 542 | Frac& operator/=(const Frac& b) { *this = *this / b; return *this; } 543 | }; 544 | 545 | template 546 | ostream& operator<<(ostream& os, const Frac& f) { 547 | if (f.y == 1) return os << f.x; 548 | else return os << f.x << '/' << f.y; 549 | } 550 | ``` 551 | 552 | ### ModInt 553 | 554 | + Industrial ModInt 555 | 556 | ```cpp 557 | // tourist 558 | template 559 | T inverse(T a, T m) { 560 | T u = 0, v = 1; 561 | while (a != 0) { 562 | T t = m / a; 563 | m -= t * a; swap(a, m); 564 | u -= t * v; swap(u, v); 565 | } 566 | assert(m == 1); 567 | return u; 568 | } 569 | 570 | template 571 | class Modular { 572 | public: 573 | using Type = typename decay::type; 574 | 575 | constexpr Modular() : value() {} 576 | template 577 | Modular(const U& x) { 578 | value = normalize(x); 579 | } 580 | 581 | template 582 | static Type normalize(const U& x) { 583 | Type v; 584 | if (-mod() <= x && x < mod()) v = static_cast(x); 585 | else v = static_cast(x % mod()); 586 | if (v < 0) v += mod(); 587 | return v; 588 | } 589 | 590 | const Type& operator()() const { return value; } 591 | template 592 | explicit operator U() const { return static_cast(value); } 593 | constexpr static Type mod() { return T::value; } 594 | 595 | Modular& operator+=(const Modular& other) { if ((value += other.value) >= mod()) value -= mod(); return *this; } 596 | Modular& operator-=(const Modular& other) { if ((value -= other.value) < 0) value += mod(); return *this; } 597 | template Modular& operator+=(const U& other) { return *this += Modular(other); } 598 | template Modular& operator-=(const U& other) { return *this -= Modular(other); } 599 | Modular& operator++() { return *this += 1; } 600 | Modular& operator--() { return *this -= 1; } 601 | Modular operator++(int) { Modular result(*this); *this += 1; return result; } 602 | Modular operator--(int) { Modular result(*this); *this -= 1; return result; } 603 | Modular operator-() const { return Modular(-value); } 604 | 605 | template 606 | typename enable_if::Type, int>::value, Modular>::type& operator*=(const Modular& rhs) { 607 | #ifdef _WIN32 608 | uint64_t x = static_cast(value) * static_cast(rhs.value); 609 | uint32_t xh = static_cast(x >> 32), xl = static_cast(x), d, m; 610 | asm( 611 | "divl %4; \n\t" 612 | : "=a" (d), "=d" (m) 613 | : "d" (xh), "a" (xl), "r" (mod()) 614 | ); 615 | value = m; 616 | #else 617 | value = normalize(static_cast(value) * static_cast(rhs.value)); 618 | #endif 619 | return *this; 620 | } 621 | template 622 | typename enable_if::Type, long long>::value, Modular>::type& operator*=(const Modular& rhs) { 623 | #ifdef __SIZEOF_INT128__ 624 | value = normalize(static_cast<__int128>(value) * static_cast<__int128>(rhs.value)); 625 | #else 626 | long long q = static_cast(static_cast(value) * rhs.value / mod()); 627 | value = normalize(value * rhs.value - q * mod()); 628 | #endif 629 | return *this; 630 | } 631 | template 632 | typename enable_if::Type>::value, Modular>::type& operator*=(const Modular& rhs) { 633 | value = normalize(value * rhs.value); 634 | return *this; 635 | } 636 | 637 | Modular& operator/=(const Modular& other) { return *this *= Modular(inverse(other.value, mod())); } 638 | 639 | friend const Type& abs(const Modular& x) { return x.value; } 640 | 641 | template 642 | friend bool operator==(const Modular& lhs, const Modular& rhs); 643 | 644 | template 645 | friend bool operator<(const Modular& lhs, const Modular& rhs); 646 | 647 | template 648 | friend V& operator>>(V& stream, Modular& number); 649 | 650 | private: 651 | Type value; 652 | }; 653 | 654 | template bool operator==(const Modular& lhs, const Modular& rhs) { return lhs.value == rhs.value; } 655 | template bool operator==(const Modular& lhs, U rhs) { return lhs == Modular(rhs); } 656 | template bool operator==(U lhs, const Modular& rhs) { return Modular(lhs) == rhs; } 657 | 658 | template bool operator!=(const Modular& lhs, const Modular& rhs) { return !(lhs == rhs); } 659 | template bool operator!=(const Modular& lhs, U rhs) { return !(lhs == rhs); } 660 | template bool operator!=(U lhs, const Modular& rhs) { return !(lhs == rhs); } 661 | 662 | template bool operator<(const Modular& lhs, const Modular& rhs) { return lhs.value < rhs.value; } 663 | 664 | template Modular operator+(const Modular& lhs, const Modular& rhs) { return Modular(lhs) += rhs; } 665 | template Modular operator+(const Modular& lhs, U rhs) { return Modular(lhs) += rhs; } 666 | template Modular operator+(U lhs, const Modular& rhs) { return Modular(lhs) += rhs; } 667 | 668 | template Modular operator-(const Modular& lhs, const Modular& rhs) { return Modular(lhs) -= rhs; } 669 | template Modular operator-(const Modular& lhs, U rhs) { return Modular(lhs) -= rhs; } 670 | template Modular operator-(U lhs, const Modular& rhs) { return Modular(lhs) -= rhs; } 671 | 672 | template Modular operator*(const Modular& lhs, const Modular& rhs) { return Modular(lhs) *= rhs; } 673 | template Modular operator*(const Modular& lhs, U rhs) { return Modular(lhs) *= rhs; } 674 | template Modular operator*(U lhs, const Modular& rhs) { return Modular(lhs) *= rhs; } 675 | 676 | template Modular operator/(const Modular& lhs, const Modular& rhs) { return Modular(lhs) /= rhs; } 677 | template Modular operator/(const Modular& lhs, U rhs) { return Modular(lhs) /= rhs; } 678 | template Modular operator/(U lhs, const Modular& rhs) { return Modular(lhs) /= rhs; } 679 | 680 | template 681 | Modular power(const Modular& a, const U& b) { 682 | assert(b >= 0); 683 | Modular x = a, res = 1; 684 | U p = b; 685 | while (p > 0) { 686 | if (p & 1) res *= x; 687 | x *= x; 688 | p >>= 1; 689 | } 690 | return res; 691 | } 692 | 693 | template 694 | bool IsZero(const Modular& number) { 695 | return number() == 0; 696 | } 697 | 698 | template 699 | string to_string(const Modular& number) { 700 | return to_string(number()); 701 | } 702 | 703 | // U == std::ostream? but done this way because of fastoutput 704 | template 705 | U& operator<<(U& stream, const Modular& number) { 706 | return stream << number(); 707 | } 708 | 709 | // U == std::istream? but done this way because of fastinput 710 | template 711 | U& operator>>(U& stream, Modular& number) { 712 | typename common_type::Type, long long>::type x; 713 | stream >> x; 714 | number.value = Modular::normalize(x); 715 | return stream; 716 | } 717 | 718 | /* using ModType = int; 719 | 720 | struct VarMod { static ModType value; }; 721 | ModType VarMod::value; 722 | ModType& md = VarMod::value; 723 | using Mint = Modular; */ 724 | 725 | constexpr int md = (int) 1e9 + 7; 726 | using Mint = Modular::type, md>>; 727 | 728 | /* const int N = 2e5 + 10; 729 | Mint fac[N], ifac[N]; 730 | 731 | void init_inv() { 732 | fac[0] = 1; 733 | for (int i = 1; i < N; i++) { 734 | fac[i] = fac[i - 1] * i; 735 | } 736 | ifac[N - 1] = 1 / fac[N - 1]; 737 | for (int i = N - 2; i >= 0; i--) { 738 | ifac[i] = ifac[i + 1] * (i + 1); 739 | } 740 | } 741 | 742 | Mint C(int n, int m) { 743 | if (n < m || m < 0) return 0; 744 | return fac[n] * ifac[m] * ifac[n - m]; 745 | } 746 | 747 | Mint H(int n, int m) { return C(n + m - 1, m); } */ 748 | ``` 749 | 750 | ### BigInt 751 | 752 | ```cpp 753 | // wxh 754 | class BigInt { 755 | #define w size() 756 | 757 | static constexpr int base = 1000000000; 758 | static constexpr int base_digits = 9; 759 | 760 | using vi = vector; 761 | using vll = vector; 762 | 763 | vi z; 764 | int f; 765 | 766 | void trim() { 767 | while (!z.empty() && z.back() == 0) { 768 | z.pop_back(); 769 | } 770 | if (z.empty()) { 771 | f = 1; 772 | } 773 | } 774 | 775 | void read(const string& s) { 776 | f = 1; 777 | z.clear(); 778 | int pos = 0; 779 | while (pos < (int)s.w && (s[pos] == '-' || s[pos] == '+')) { 780 | if (s[pos] == '-') { 781 | f = -f; 782 | } 783 | ++pos; 784 | } 785 | for (int i = s.w - 1; i >= pos; i -= base_digits) { 786 | int x = 0; 787 | for (int j = max(pos, i - base_digits + 1); j <= i; j++) { 788 | x = x * 10 + s[j] - '0'; 789 | } 790 | z.push_back(x); 791 | } 792 | trim(); 793 | } 794 | 795 | static vi convert_base(const vi& a, int old_digits, int new_digits) { 796 | vll p(max(old_digits, new_digits) + 1); 797 | p[0] = 1; 798 | for (int i = 1; i < (int)p.w; i++) { 799 | p[i] = p[i - 1] * 10; 800 | } 801 | vi res; 802 | long long cur = 0; 803 | int cur_digits = 0; 804 | for (int i = 0; i < (int)a.w; i++) { 805 | cur += a[i] * p[cur_digits]; 806 | cur_digits += old_digits; 807 | while (cur_digits >= new_digits) { 808 | res.push_back(cur % p[new_digits]); 809 | cur /= p[new_digits]; 810 | cur_digits -= new_digits; 811 | } 812 | } 813 | res.push_back(cur); 814 | while (!res.empty() && res.back() == 0) { 815 | res.pop_back(); 816 | } 817 | return res; 818 | } 819 | 820 | static vll karatsuba(const vll& a, const vll& b) { 821 | int n = a.w; 822 | vll res(n + n); 823 | if (n <= 32) { 824 | for (int i = 0; i < n; i++) { 825 | for (int j = 0; j < n; j++) { 826 | res[i + j] += a[i] * b[j]; 827 | } 828 | } 829 | return res; 830 | } 831 | int k = n >> 1; 832 | vll a1(a.begin(), a.begin() + k); 833 | vll a2(a.begin() + k, a.end()); 834 | vll b1(b.begin(), b.begin() + k); 835 | vll b2(b.begin() + k, b.end()); 836 | vll a1b1 = karatsuba(a1, b1); 837 | vll a2b2 = karatsuba(a2, b2); 838 | for (int i = 0; i < k; i++) { 839 | a2[i] += a1[i]; 840 | } 841 | for (int i = 0; i < k; i++) { 842 | b2[i] += b1[i]; 843 | } 844 | vll r = karatsuba(a2, b2); 845 | for (int i = 0; i < (int)a1b1.w; i++) { 846 | r[i] -= a1b1[i]; 847 | } 848 | for (int i = 0; i < (int)a2b2.w; i++) { 849 | r[i] -= a2b2[i]; 850 | } 851 | for (int i = 0; i < (int)r.w; i++) { 852 | res[i + k] += r[i]; 853 | } 854 | for (int i = 0; i < (int)a1b1.w; i++) { 855 | res[i] += a1b1[i]; 856 | } 857 | for (int i = 0; i < (int)a2b2.w; i++) { 858 | res[i + n] += a2b2[i]; 859 | } 860 | return res; 861 | } 862 | 863 | public: 864 | BigInt() : f(1) {} 865 | BigInt(long long v) { *this = v; } 866 | BigInt(const string& s) { read(s); } 867 | 868 | void operator=(const BigInt& v) { 869 | f = v.f; 870 | z = v.z; 871 | } 872 | 873 | void operator=(long long v) { 874 | f = 1; 875 | if (v < 0) { 876 | f = -1, v = -v; 877 | } 878 | z.clear(); 879 | for (; v > 0; v = v / base) { 880 | z.push_back(v % base); 881 | } 882 | } 883 | 884 | BigInt operator+(const BigInt& v) const { 885 | if (f == v.f) { 886 | BigInt res = v; 887 | for (int i = 0, carry = 0; i < (int)max(z.w, v.z.w) || carry; ++i) { 888 | if (i == (int)res.z.w) { 889 | res.z.push_back(0); 890 | } 891 | res.z[i] += carry + (i < (int)z.w ? z[i] : 0); 892 | carry = res.z[i] >= base; 893 | if (carry) { 894 | res.z[i] -= base; 895 | } 896 | } 897 | return res; 898 | } else { 899 | return *this - (-v); 900 | } 901 | } 902 | 903 | BigInt operator-(const BigInt& v) const { 904 | if (f == v.f) { 905 | if (abs() >= v.abs()) { 906 | BigInt res = *this; 907 | for (int i = 0, carry = 0; i < (int)v.z.w || carry; ++i) { 908 | res.z[i] -= carry + (i < (int)v.z.w ? v.z[i] : 0); 909 | carry = res.z[i] < 0; 910 | if (carry) { 911 | res.z[i] += base; 912 | } 913 | } 914 | res.trim(); 915 | return res; 916 | } else { 917 | return -(v - *this); 918 | } 919 | } else { 920 | return *this + (-v); 921 | } 922 | } 923 | 924 | void operator*=(int v) { 925 | if (v < 0) { 926 | f = -f, v = -v; 927 | } 928 | for (int i = 0, carry = 0; i < (int)z.w || carry; ++i) { 929 | if (i == (int)z.w) { 930 | z.push_back(0); 931 | } 932 | long long cur = (long long)z[i] * v + carry; 933 | carry = cur / base; 934 | z[i] = cur % base; 935 | // asm("divl %%ecx" : "=a"(carry), "=d"(a[i]) : "A"(cur), "c"(base)); 936 | } 937 | trim(); 938 | } 939 | 940 | BigInt operator*(int v) const { 941 | BigInt res = *this; 942 | res *= v; 943 | return res; 944 | } 945 | 946 | friend pair divmod(const BigInt& a1, const BigInt& b1) { 947 | int norm = base / (b1.z.back() + 1); 948 | BigInt a = a1.abs() * norm; 949 | BigInt b = b1.abs() * norm; 950 | BigInt q, r; 951 | q.z.resize(a.z.w); 952 | for (int i = a.z.w - 1; i >= 0; i--) { 953 | r *= base; 954 | r += a.z[i]; 955 | int s1 = b.z.w < r.z.w ? r.z[b.z.w] : 0; 956 | int s2 = b.z.w - 1 < r.z.w ? r.z[b.z.w - 1] : 0; 957 | int d = ((long long)s1 * base + s2) / b.z.back(); 958 | r -= b * d; 959 | while (r < 0) { 960 | r += b, --d; 961 | } 962 | q.z[i] = d; 963 | } 964 | q.f = a1.f * b1.f; 965 | r.f = a1.f; 966 | q.trim(); 967 | r.trim(); 968 | return make_pair(q, r / norm); 969 | } 970 | 971 | friend BigInt sqrt(const BigInt& a1) { 972 | BigInt a = a1; 973 | while (a.z.empty() || (int)a.z.w % 2 == 1) { 974 | a.z.push_back(0); 975 | } 976 | int n = a.z.w; 977 | int firstDigit = sqrt((long long)a.z[n - 1] * base + a.z[n - 2]); 978 | int norm = base / (firstDigit + 1); 979 | a *= norm; 980 | a *= norm; 981 | while (a.z.empty() || (int)a.z.w % 2 == 1) { 982 | a.z.push_back(0); 983 | } 984 | BigInt r = (long long)a.z[n - 1] * base + a.z[n - 2]; 985 | firstDigit = sqrt((long long)a.z[n - 1] * base + a.z[n - 2]); 986 | int q = firstDigit; 987 | BigInt res; 988 | for (int j = n / 2 - 1; j >= 0; j--) { 989 | for (;; --q) { 990 | BigInt r1 = (r - (res * 2 * base + q) * q) * base * base + 991 | (j > 0 ? (long long)a.z[2 * j - 1] * base + a.z[2 * j - 2] : 0); 992 | if (r1 >= 0) { 993 | r = r1; 994 | break; 995 | } 996 | } 997 | res *= base; 998 | res += q; 999 | if (j > 0) { 1000 | int d1 = res.z.w + 2 < r.z.w ? r.z[res.z.w + 2] : 0; 1001 | int d2 = res.z.w + 1 < r.z.w ? r.z[res.z.w + 1] : 0; 1002 | int d3 = res.z.w < r.z.w ? r.z[res.z.w] : 0; 1003 | q = ((long long)d1 * base * base + (long long)d2 * base + d3) / (firstDigit * 2); 1004 | } 1005 | } 1006 | res.trim(); 1007 | return res / norm; 1008 | } 1009 | 1010 | BigInt operator/(const BigInt& v) const { return divmod(*this, v).first; } 1011 | BigInt operator%(const BigInt& v) const { return divmod(*this, v).second; } 1012 | 1013 | void operator/=(int v) { 1014 | if (v < 0) { 1015 | f = -f, v = -v; 1016 | } 1017 | for (int i = z.w - 1, rem = 0; i >= 0; --i) { 1018 | long long cur = z[i] + (long long)rem * base; 1019 | z[i] = cur / v; 1020 | rem = cur % v; 1021 | } 1022 | trim(); 1023 | } 1024 | 1025 | BigInt operator/(int v) const { 1026 | BigInt res = *this; 1027 | res /= v; 1028 | return res; 1029 | } 1030 | 1031 | int operator%(int v) const { 1032 | if (v < 0) { 1033 | v = -v; 1034 | } 1035 | int m = 0; 1036 | for (int i = z.w - 1; i >= 0; --i) { 1037 | m = ((long long)m * base + z[i]) % v; 1038 | } 1039 | return m * f; 1040 | } 1041 | 1042 | void operator+=(const BigInt& v) { *this = *this + v; } 1043 | void operator-=(const BigInt& v) { *this = *this - v; } 1044 | void operator*=(const BigInt& v) { *this = *this * v; } 1045 | void operator/=(const BigInt& v) { *this = *this / v; } 1046 | 1047 | bool operator<(const BigInt& v) const { 1048 | if (f != v.f) { 1049 | return f < v.f; 1050 | } 1051 | if (z.w != v.z.w) { 1052 | return z.w * f < v.z.w * v.f; 1053 | } 1054 | for (int i = z.w - 1; i >= 0; i--) { 1055 | if (z[i] != v.z[i]) { 1056 | return z[i] * f < v.z[i] * f; 1057 | } 1058 | } 1059 | return false; 1060 | } 1061 | 1062 | bool operator>(const BigInt& v) const { return v < *this; } 1063 | bool operator<=(const BigInt& v) const { return !(v < *this); } 1064 | bool operator>=(const BigInt& v) const { return !(*this < v); } 1065 | bool operator==(const BigInt& v) const { return !(*this < v) && !(v < *this); } 1066 | bool operator!=(const BigInt& v) const { return *this < v || v < *this; } 1067 | 1068 | bool is_zero() const { return z.empty() || ((int)z.w == 1 && !z[0]); } 1069 | 1070 | BigInt operator-() const { 1071 | BigInt res = *this; 1072 | res.f = -f; 1073 | return res; 1074 | } 1075 | 1076 | BigInt abs() const { 1077 | BigInt res = *this; 1078 | res.f *= res.f; 1079 | return res; 1080 | } 1081 | 1082 | long long long_value() const { 1083 | long long res = 0; 1084 | for (int i = z.w - 1; i >= 0; i--) { 1085 | res = res * base + z[i]; 1086 | } 1087 | return res * f; 1088 | } 1089 | 1090 | friend BigInt gcd(const BigInt& a, const BigInt& b) { return b.is_zero() ? a : gcd(b, a % b); } 1091 | friend BigInt lcm(const BigInt& a, const BigInt& b) { return a / gcd(a, b) * b; } 1092 | 1093 | friend istream& operator>>(istream& is, BigInt& v) { 1094 | string s; 1095 | is >> s; 1096 | v.read(s); 1097 | return is; 1098 | } 1099 | 1100 | friend ostream& operator<<(ostream& os, const BigInt& v) { 1101 | if (v.f == -1) { 1102 | os << '-'; 1103 | } 1104 | os << (v.z.empty() ? 0 : v.z.back()); 1105 | for (int i = v.z.w - 2; i >= 0; --i) { 1106 | os << setw(base_digits) << setfill('0') << v.z[i]; 1107 | } 1108 | return os; 1109 | } 1110 | 1111 | BigInt operator*(const BigInt& v) const { 1112 | vi a6 = convert_base(this->z, base_digits, 6); 1113 | vi b6 = convert_base(v.z, base_digits, 6); 1114 | vll a(a6.begin(), a6.end()); 1115 | vll b(b6.begin(), b6.end()); 1116 | while (a.w < b.w) { 1117 | a.push_back(0); 1118 | } 1119 | while (b.w < a.w) { 1120 | b.push_back(0); 1121 | } 1122 | while (a.w & (a.w - 1)) { 1123 | a.push_back(0); 1124 | b.push_back(0); 1125 | } 1126 | vll c = karatsuba(a, b); 1127 | BigInt res; 1128 | res.f = f * v.f; 1129 | for (int i = 0, carry = 0; i < (int)c.w; i++) { 1130 | long long cur = c[i] + carry; 1131 | res.z.push_back(cur % 1000000); 1132 | carry = cur / 1000000; 1133 | } 1134 | res.z = convert_base(res.z, 6, base_digits); 1135 | res.trim(); 1136 | return res; 1137 | } 1138 | 1139 | #undef w 1140 | }; 1141 | ``` 1142 | 1143 | 1144 | ### Java 1145 | 1146 | + Main 1147 | 1148 | ```java 1149 | import java.io.*; 1150 | import java.util.*; 1151 | 1152 | public class Main { 1153 | public static void main(String[] args) { 1154 | Scanner in = new Scanner(System.in); 1155 | PrintStream out = System.out; 1156 | 1157 | } 1158 | } 1159 | ``` 1160 | 1161 | + Petr's ultimate fast input 1162 | 1163 | ```java 1164 | public class Main { 1165 | public static void main(String[] args) { 1166 | InputStream inputStream = System.in; 1167 | OutputStream outputStream = System.out; 1168 | InputReader in = new InputReader(inputStream); 1169 | PrintWriter out = new PrintWriter(outputStream); 1170 | 1171 | out.close(); 1172 | } 1173 | 1174 | static class InputReader { 1175 | public BufferedReader reader; 1176 | public StringTokenizer tokenizer; 1177 | 1178 | public InputReader(InputStream stream) { 1179 | reader = new BufferedReader(new InputStreamReader(stream), 32768); 1180 | tokenizer = null; 1181 | } 1182 | 1183 | public String next() { 1184 | while (tokenizer == null || !tokenizer.hasMoreTokens()) { 1185 | try { 1186 | tokenizer = new StringTokenizer(reader.readLine()); 1187 | } catch (IOException e) { 1188 | throw new RuntimeException(e); 1189 | } 1190 | } 1191 | return tokenizer.nextToken(); 1192 | } 1193 | 1194 | public int nextInt() { 1195 | return Integer.parseInt(next()); 1196 | } 1197 | } 1198 | } 1199 | ``` 1200 | 1201 | + BigInteger 1202 | 1203 | ```java 1204 | import java.math.BigInteger; 1205 | 1206 | BigInteger.ZERO 1207 | BigInteger.ONE 1208 | BigInteger.TWO // since Java 9 1209 | BigInteger.TEN 1210 | BigInteger.valueOf(2) 1211 | 1212 | BigInteger abs() 1213 | BigInteger negate() // -this 1214 | 1215 | BigInteger add​(BigInteger x) 1216 | BigInteger subtract​(BigInteger x) 1217 | BigInteger multiply​(BigInteger x) 1218 | BigInteger divide​(BigInteger x) 1219 | 1220 | BigInteger pow​(int exp) 1221 | BigInteger sqrt() // since Java 9 1222 | 1223 | BigInteger mod​(BigInteger m) 1224 | BigInteger modPow​(BigInteger exp, BigInteger m) 1225 | BigInteger modInverse​(BigInteger m) 1226 | 1227 | boolean isProbablePrime​(int certainty) // probability: 1 - (1/2) ^ (certainty) 1228 | 1229 | BigInteger gcd​(BigInteger x) 1230 | 1231 | BigInteger not() // ~this 1232 | BigInteger and​(BigInteger x) 1233 | BigInteger or​(BigInteger x) 1234 | BigInteger xor​(BigInteger x) 1235 | BigInteger shiftLeft​(int n) 1236 | BigInteger shiftRight​(int n) 1237 | 1238 | int compareTo​(BigInteger x) // -1, 0, 1 1239 | BigInteger max​(BigInteger x) 1240 | BigInteger min​(BigInteger x) 1241 | 1242 | int intValue() 1243 | long longValue() 1244 | String toString() 1245 | 1246 | public static BigInteger getsqrt(BigInteger n) { 1247 | if (n.compareTo(BigInteger.ZERO) <= 0) return n; 1248 | BigInteger x, xx, txx; 1249 | xx = x = BigInteger.ZERO; 1250 | for (int t = n.bitLength() / 2; t >= 0; t--) { 1251 | txx = xx.add(x.shiftLeft(t + 1)).add(BigInteger.ONE.shiftLeft(t + t)); 1252 | if (txx.compareTo(n) <= 0) { 1253 | x = x.add(BigInteger.ONE.shiftLeft(t)); 1254 | xx = txx; 1255 | } 1256 | } 1257 | return x; 1258 | } 1259 | ``` 1260 | 1261 | + DecimalFormat 1262 | 1263 | ```java 1264 | import java.text.DecimalFormat; 1265 | 1266 | DecimalFormat fmt; 1267 | 1268 | // String s = fmt.format(...) 1269 | 1270 | // round to at most 2 digits, leave of digits if not needed 1271 | fmt = new DecimalFormat("#.##"); 1272 | // 12345.6789 -> "12345.68" 1273 | // 12345.0 -> "12345" 1274 | // 0.0 -> "0" 1275 | // 0.01 -> ".1" 1276 | 1277 | // round to precisely 2 digits 1278 | fmt = new DecimalFormat("#.00"); 1279 | // 12345.6789 -> "12345.68" 1280 | // 12345.0 -> "12345.00" 1281 | // 0.0 -> ".00" 1282 | 1283 | // round to precisely 2 digits, force leading zero 1284 | fmt = new DecimalFormat("0.00"); 1285 | // 12345.6789 -> "12345.68" 1286 | // 12345.0 -> "12345.00" 1287 | // 0.0 -> "0.00" 1288 | 1289 | // round to precisely 2 digits, force leading zeros 1290 | fmt = new DecimalFormat("000000000.00"); 1291 | // 12345.6789 -> "000012345.68" 1292 | // 12345.0 -> "000012345.00" 1293 | // 0.0 -> "000000000.00" 1294 | ``` 1295 | -------------------------------------------------------------------------------- /9-Unverified.md: -------------------------------------------------------------------------------- 1 | ## Unverified 2 | 3 | **Copyright belongs to the original author. Some code has style adjustments. Not guaranteed to be correct.** 4 | 5 | ### Segment Tree Beats 6 | 7 | ```cpp 8 | // Nyaan 9 | struct AngelBeats { 10 | static constexpr i64 INF = numeric_limits::max() / 2.1; 11 | 12 | struct alignas(32) Node { 13 | i64 sum = 0, g1 = 0, l1 = 0; 14 | i64 g2 = -INF, gc = 1, l2 = INF, lc = 1, add = 0; 15 | }; 16 | 17 | vector v; 18 | i64 n, log; 19 | 20 | AngelBeats() {} 21 | AngelBeats(int _n) : AngelBeats(vector(_n)) {} 22 | AngelBeats(const vector& vc) { 23 | n = 1, log = 0; 24 | while (n < (int)vc.size()) n <<= 1, log++; 25 | v.resize(2 * n); 26 | for (i64 i = 0; i < (int)vc.size(); ++i) { 27 | v[i + n].sum = v[i + n].g1 = v[i + n].l1 = vc[i]; 28 | } 29 | for (i64 i = n - 1; i; --i) update(i); 30 | } 31 | 32 | void range_chmin(int l, int r, i64 x) { inner_apply<1>(l, r, x); } 33 | void range_chmax(int l, int r, i64 x) { inner_apply<2>(l, r, x); } 34 | void range_add(int l, int r, i64 x) { inner_apply<3>(l, r, x); } 35 | void range_update(int l, int r, i64 x) { inner_apply<4>(l, r, x); } 36 | i64 range_min(int l, int r) { return inner_fold<1>(l, r); } 37 | i64 range_max(int l, int r) { return inner_fold<2>(l, r); } 38 | i64 range_sum(int l, int r) { return inner_fold<3>(l, r); } 39 | 40 | private: 41 | void update(int k) { 42 | Node& p = v[k]; 43 | Node& l = v[k * 2 + 0]; 44 | Node& r = v[k * 2 + 1]; 45 | 46 | p.sum = l.sum + r.sum; 47 | 48 | if (l.g1 == r.g1) { 49 | p.g1 = l.g1; 50 | p.g2 = max(l.g2, r.g2); 51 | p.gc = l.gc + r.gc; 52 | } else { 53 | bool f = l.g1 > r.g1; 54 | p.g1 = f ? l.g1 : r.g1; 55 | p.gc = f ? l.gc : r.gc; 56 | p.g2 = max(f ? r.g1 : l.g1, f ? l.g2 : r.g2); 57 | } 58 | 59 | if (l.l1 == r.l1) { 60 | p.l1 = l.l1; 61 | p.l2 = min(l.l2, r.l2); 62 | p.lc = l.lc + r.lc; 63 | } else { 64 | bool f = l.l1 < r.l1; 65 | p.l1 = f ? l.l1 : r.l1; 66 | p.lc = f ? l.lc : r.lc; 67 | p.l2 = min(f ? r.l1 : l.l1, f ? l.l2 : r.l2); 68 | } 69 | } 70 | 71 | void push_add(int k, i64 x) { 72 | Node& p = v[k]; 73 | p.sum += x << (log + __builtin_clz(k) - 31); 74 | p.g1 += x; 75 | p.l1 += x; 76 | if (p.g2 != -INF) p.g2 += x; 77 | if (p.l2 != INF) p.l2 += x; 78 | p.add += x; 79 | } 80 | void push_min(int k, i64 x) { 81 | Node& p = v[k]; 82 | p.sum += (x - p.g1) * p.gc; 83 | if (p.l1 == p.g1) p.l1 = x; 84 | if (p.l2 == p.g1) p.l2 = x; 85 | p.g1 = x; 86 | } 87 | void push_max(int k, i64 x) { 88 | Node& p = v[k]; 89 | p.sum += (x - p.l1) * p.lc; 90 | if (p.g1 == p.l1) p.g1 = x; 91 | if (p.g2 == p.l1) p.g2 = x; 92 | p.l1 = x; 93 | } 94 | void push(int k) { 95 | Node& p = v[k]; 96 | if (p.add != 0) { 97 | push_add(k * 2 + 0, p.add); 98 | push_add(k * 2 + 1, p.add); 99 | p.add = 0; 100 | } 101 | if (p.g1 < v[k * 2 + 0].g1) push_min(k * 2 + 0, p.g1); 102 | if (p.l1 > v[k * 2 + 0].l1) push_max(k * 2 + 0, p.l1); 103 | 104 | if (p.g1 < v[k * 2 + 1].g1) push_min(k * 2 + 1, p.g1); 105 | if (p.l1 > v[k * 2 + 1].l1) push_max(k * 2 + 1, p.l1); 106 | } 107 | 108 | void subtree_chmin(int k, i64 x) { 109 | if (v[k].g1 <= x) return; 110 | if (v[k].g2 < x) { 111 | push_min(k, x); 112 | return; 113 | } 114 | push(k); 115 | subtree_chmin(k * 2 + 0, x); 116 | subtree_chmin(k * 2 + 1, x); 117 | update(k); 118 | } 119 | 120 | void subtree_chmax(int k, i64 x) { 121 | if (x <= v[k].l1) return; 122 | if (x < v[k].l2) { 123 | push_max(k, x); 124 | return; 125 | } 126 | push(k); 127 | subtree_chmax(k * 2 + 0, x); 128 | subtree_chmax(k * 2 + 1, x); 129 | update(k); 130 | } 131 | 132 | template 133 | inline void _apply(int k, i64 x) { 134 | if constexpr (cmd == 1) subtree_chmin(k, x); 135 | if constexpr (cmd == 2) subtree_chmax(k, x); 136 | if constexpr (cmd == 3) push_add(k, x); 137 | if constexpr (cmd == 4) subtree_chmin(k, x), subtree_chmax(k, x); 138 | } 139 | 140 | template 141 | void inner_apply(int l, int r, i64 x) { 142 | if (l == r) return; 143 | l += n, r += n; 144 | for (int i = log; i >= 1; i--) { 145 | if (((l >> i) << i) != l) push(l >> i); 146 | if (((r >> i) << i) != r) push((r - 1) >> i); 147 | } 148 | { 149 | int l2 = l, r2 = r; 150 | while (l < r) { 151 | if (l & 1) _apply(l++, x); 152 | if (r & 1) _apply(--r, x); 153 | l >>= 1; 154 | r >>= 1; 155 | } 156 | l = l2; 157 | r = r2; 158 | } 159 | for (int i = 1; i <= log; i++) { 160 | if (((l >> i) << i) != l) update(l >> i); 161 | if (((r >> i) << i) != r) update((r - 1) >> i); 162 | } 163 | } 164 | 165 | template 166 | inline i64 e() { 167 | if constexpr (cmd == 1) return INF; 168 | if constexpr (cmd == 2) return -INF; 169 | return 0; 170 | } 171 | 172 | template 173 | inline void op(i64& a, const Node& b) { 174 | if constexpr (cmd == 1) a = min(a, b.l1); 175 | if constexpr (cmd == 2) a = max(a, b.g1); 176 | if constexpr (cmd == 3) a += b.sum; 177 | } 178 | 179 | template 180 | i64 inner_fold(int l, int r) { 181 | if (l == r) return e(); 182 | l += n, r += n; 183 | for (int i = log; i >= 1; i--) { 184 | if (((l >> i) << i) != l) push(l >> i); 185 | if (((r >> i) << i) != r) push((r - 1) >> i); 186 | } 187 | i64 lx = e(), rx = e(); 188 | while (l < r) { 189 | if (l & 1) op(lx, v[l++]); 190 | if (r & 1) op(rx, v[--r]); 191 | l >>= 1; 192 | r >>= 1; 193 | } 194 | if constexpr (cmd == 1) lx = min(lx, rx); 195 | if constexpr (cmd == 2) lx = max(lx, rx); 196 | if constexpr (cmd == 3) lx += rx; 197 | return lx; 198 | } 199 | }; 200 | ``` 201 | 202 | ### Josephus Problem 203 | 204 | ```cpp 205 | // n people, count from 1 to m, asking for the number of the last person remaining 206 | // Formula: f(n,m)=(f(n−1,m)+m)%n, f(0,m)=0; 207 | // O(n) 208 | i64 calc(int n, i64 m) { 209 | i64 p = 0; 210 | for (int i = 2; i <= n; i++) { 211 | p = (p + m) % i; 212 | } 213 | return p + 1; 214 | } 215 | 216 | // n people, count from 1 to m, asking for the number of the k-th person eliminated 217 | // Formula: f(n,k)=(f(n−1,k−1)+m−1)%n+1 218 | // f(n−k+1,1)=m%(n−k+1) 219 | // if (f==0) f=n−k+1 220 | // O(k) 221 | i64 cal1(i64 n, i64 m, i64 k) { // (k == n) equal(calc) 222 | i64 p = m % (n - k + 1); 223 | if (p == 0) p = n - k + 1; 224 | for (i64 i = 2; i <= k; i++) { 225 | p = (p + m - 1) % (n - k + i) + 1; 226 | } 227 | return p; 228 | } 229 | 230 | // n people, count from 1 to m, asking for the number of the k-th person eliminated 231 | // O(m*log(m)) 232 | i64 cal2(i64 n, i64 m, i64 k) { 233 | if (m == 1) 234 | return k; 235 | else { 236 | i64 a = n - k + 1, b = 1; 237 | i64 c = m % a, x = 0; 238 | if (c == 0) c = a; 239 | while (b + x <= k) { 240 | a += x, b += x, c += m * x; 241 | c %= a; 242 | if (c == 0) c = a; 243 | x = (a - c) / (m - 1) + 1; 244 | } 245 | c += (k - b) * m; 246 | c %= n; 247 | if (c == 0) c = n; 248 | return c; 249 | } 250 | } 251 | 252 | // n people, count from 1 to m, asking for the number of the person with index k eliminated 253 | // O(n) 254 | i64 n, k; // n <= 4e7, number of queries <= 100, index range [0,n-1] 255 | i64 dieInXturn(int n, int k, int x) { // n people, count k, the X-th person dies with index X 256 | i64 tmp = 0; 257 | while (n) { 258 | x = (x + n) % n; 259 | if (k > n) x += (k - x - 1 + n - 1) / n * n; 260 | if ((x + 1) % k == 0) { 261 | tmp += (x + 1) / k; 262 | break; 263 | } else { 264 | if (k > n) { 265 | tmp += x / k; 266 | i64 ttmp = x; 267 | x = x - (x / n + 1) * (x / k) + (x + n) / n * n - k; 268 | n -= ttmp / k; 269 | } else { 270 | tmp += n / k; 271 | x = x - x / k; 272 | x += n - n / k * k; 273 | n -= n / k; 274 | } 275 | } 276 | } 277 | return tmp; 278 | } 279 | ``` 280 | 281 | ### Weighted Bipartite Matching (KM Algorithm) 282 | 283 | ```cpp 284 | // ECNU 285 | namespace R { 286 | int n; 287 | int w[N][N], kx[N], ky[N], py[N], vy[N], slk[N], pre[N]; 288 | 289 | i64 go() { 290 | for (int i = 1; i <= n; i++) 291 | for (int j = 1; j <= n; j++) 292 | kx[i] = max(kx[i], w[i][j]); 293 | for (int i = 1; i <= n; i++) { 294 | fill(vy, vy + n + 1, 0); 295 | fill(slk, slk + n + 1, INF); 296 | fill(pre, pre + n + 1, 0); 297 | int k = 0, p = -1; 298 | for (py[k = 0] = i; py[k]; k = p) { 299 | int d = INF; 300 | vy[k] = 1; 301 | int x = py[k]; 302 | for (int j = 1; j <= n; j++) { 303 | if (!vy[j]) { 304 | int t = kx[x] + ky[j] - w[x][j]; 305 | if (t < slk[j]) { slk[j] = t; pre[j] = k; } 306 | if (slk[j] < d) { d = slk[j]; p = j; } 307 | } 308 | } 309 | for (int j = 0; j <= n; j++) { 310 | if (vy[j]) { kx[py[j]] -= d; ky[j] += d; } 311 | else slk[j] -= d; 312 | } 313 | } 314 | for (; k; k = pre[k]) py[k] = py[pre[k]]; 315 | } 316 | i64 ans = 0; 317 | for (int i = 1; i <= n; i++) ans += kx[i] + ky[i]; 318 | return ans; 319 | } 320 | } 321 | ``` 322 | 323 | ### Flow 324 | 325 | ```cpp 326 | namespace atcoder { 327 | namespace internal { 328 | 329 | template 330 | struct csr { 331 | std::vector start; 332 | std::vector elist; 333 | explicit csr(int n, const std::vector>& edges) : start(n + 1), elist(edges.size()) { 334 | for (auto e : edges) { 335 | start[e.first + 1]++; 336 | } 337 | for (int i = 1; i <= n; i++) { 338 | start[i] += start[i - 1]; 339 | } 340 | auto counter = start; 341 | for (auto e : edges) { 342 | elist[counter[e.first]++] = e.second; 343 | } 344 | } 345 | }; 346 | 347 | template 348 | struct simple_queue { 349 | std::vector payload; 350 | int pos = 0; 351 | void reserve(int n) { payload.reserve(n); } 352 | int size() const { return int(payload.size()) - pos; } 353 | bool empty() const { return pos == int(payload.size()); } 354 | void push(const T& t) { payload.push_back(t); } 355 | T& front() { return payload[pos]; } 356 | void clear() { 357 | payload.clear(); 358 | pos = 0; 359 | } 360 | void pop() { pos++; } 361 | }; 362 | 363 | } // namespace internal 364 | } // namespace atcoder 365 | 366 | namespace atcoder { 367 | 368 | template 369 | struct mf_graph { 370 | public: 371 | mf_graph() : _n(0) {} 372 | explicit mf_graph(int n) : _n(n), g(n) {} 373 | 374 | int add_edge(int from, int to, Cap cap) { 375 | assert(0 <= from && from < _n); 376 | assert(0 <= to && to < _n); 377 | assert(0 <= cap); 378 | int m = int(pos.size()); 379 | pos.push_back({from, int(g[from].size())}); 380 | int from_id = int(g[from].size()); 381 | int to_id = int(g[to].size()); 382 | if (from == to) to_id++; 383 | g[from].push_back(_edge{to, to_id, cap}); 384 | g[to].push_back(_edge{from, from_id, 0}); 385 | return m; 386 | } 387 | 388 | struct edge { 389 | int from, to; 390 | Cap cap, flow; 391 | }; 392 | 393 | edge get_edge(int i) { 394 | int m = int(pos.size()); 395 | assert(0 <= i && i < m); 396 | auto _e = g[pos[i].first][pos[i].second]; 397 | auto _re = g[_e.to][_e.rev]; 398 | return edge{pos[i].first, _e.to, _e.cap + _re.cap, _re.cap}; 399 | } 400 | std::vector edges() { 401 | int m = int(pos.size()); 402 | std::vector result; 403 | for (int i = 0; i < m; i++) { 404 | result.push_back(get_edge(i)); 405 | } 406 | return result; 407 | } 408 | void change_edge(int i, Cap new_cap, Cap new_flow) { 409 | int m = int(pos.size()); 410 | assert(0 <= i && i < m); 411 | assert(0 <= new_flow && new_flow <= new_cap); 412 | auto& _e = g[pos[i].first][pos[i].second]; 413 | auto& _re = g[_e.to][_e.rev]; 414 | _e.cap = new_cap - new_flow; 415 | _re.cap = new_flow; 416 | } 417 | 418 | Cap flow(int s, int t) { return flow(s, t, std::numeric_limits::max()); } 419 | Cap flow(int s, int t, Cap flow_limit) { 420 | assert(0 <= s && s < _n); 421 | assert(0 <= t && t < _n); 422 | assert(s != t); 423 | 424 | std::vector level(_n), iter(_n); 425 | internal::simple_queue que; 426 | 427 | auto bfs = [&]() { 428 | std::fill(level.begin(), level.end(), -1); 429 | level[s] = 0; 430 | que.clear(); 431 | que.push(s); 432 | while (!que.empty()) { 433 | int v = que.front(); 434 | que.pop(); 435 | for (auto e : g[v]) { 436 | if (e.cap == 0 || level[e.to] >= 0) continue; 437 | level[e.to] = level[v] + 1; 438 | if (e.to == t) return; 439 | que.push(e.to); 440 | } 441 | } 442 | }; 443 | auto dfs = [&](auto self, int v, Cap up) { 444 | if (v == s) return up; 445 | Cap res = 0; 446 | int level_v = level[v]; 447 | for (int& i = iter[v]; i < int(g[v].size()); i++) { 448 | _edge& e = g[v][i]; 449 | if (level_v <= level[e.to] || g[e.to][e.rev].cap == 0) continue; 450 | Cap d = self(self, e.to, std::min(up - res, g[e.to][e.rev].cap)); 451 | if (d <= 0) continue; 452 | g[v][i].cap += d; 453 | g[e.to][e.rev].cap -= d; 454 | res += d; 455 | if (res == up) return res; 456 | } 457 | level[v] = _n; 458 | return res; 459 | }; 460 | 461 | Cap flow = 0; 462 | while (flow < flow_limit) { 463 | bfs(); 464 | if (level[t] == -1) break; 465 | std::fill(iter.begin(), iter.end(), 0); 466 | Cap f = dfs(dfs, t, flow_limit - flow); 467 | if (!f) break; 468 | flow += f; 469 | } 470 | return flow; 471 | } 472 | 473 | std::vector min_cut(int s) { 474 | std::vector visited(_n); 475 | internal::simple_queue que; 476 | que.push(s); 477 | while (!que.empty()) { 478 | int p = que.front(); 479 | que.pop(); 480 | visited[p] = true; 481 | for (auto e : g[p]) { 482 | if (e.cap && !visited[e.to]) { 483 | visited[e.to] = true; 484 | que.push(e.to); 485 | } 486 | } 487 | } 488 | return visited; 489 | } 490 | 491 | private: 492 | int _n; 493 | struct _edge { 494 | int to, rev; 495 | Cap cap; 496 | }; 497 | std::vector> pos; 498 | std::vector> g; 499 | }; 500 | 501 | } // namespace atcoder 502 | 503 | namespace atcoder { 504 | 505 | template 506 | struct mcf_graph { 507 | public: 508 | mcf_graph() {} 509 | explicit mcf_graph(int n) : _n(n) {} 510 | 511 | int add_edge(int from, int to, Cap cap, Cost cost) { 512 | assert(0 <= from && from < _n); 513 | assert(0 <= to && to < _n); 514 | assert(0 <= cap); 515 | assert(0 <= cost); 516 | int m = int(_edges.size()); 517 | _edges.push_back({from, to, cap, 0, cost}); 518 | return m; 519 | } 520 | 521 | struct edge { 522 | int from, to; 523 | Cap cap, flow; 524 | Cost cost; 525 | }; 526 | 527 | edge get_edge(int i) { 528 | int m = int(_edges.size()); 529 | assert(0 <= i && i < m); 530 | return _edges[i]; 531 | } 532 | std::vector edges() { return _edges; } 533 | 534 | std::pair flow(int s, int t) { return flow(s, t, std::numeric_limits::max()); } 535 | std::pair flow(int s, int t, Cap flow_limit) { return slope(s, t, flow_limit).back(); } 536 | std::vector> slope(int s, int t) { return slope(s, t, std::numeric_limits::max()); } 537 | std::vector> slope(int s, int t, Cap flow_limit) { 538 | assert(0 <= s && s < _n); 539 | assert(0 <= t && t < _n); 540 | assert(s != t); 541 | 542 | int m = int(_edges.size()); 543 | std::vector edge_idx(m); 544 | 545 | auto g = [&]() { 546 | std::vector degree(_n), redge_idx(m); 547 | std::vector> elist; 548 | elist.reserve(2 * m); 549 | for (int i = 0; i < m; i++) { 550 | auto e = _edges[i]; 551 | edge_idx[i] = degree[e.from]++; 552 | redge_idx[i] = degree[e.to]++; 553 | elist.push_back({e.from, {e.to, -1, e.cap - e.flow, e.cost}}); 554 | elist.push_back({e.to, {e.from, -1, e.flow, -e.cost}}); 555 | } 556 | auto _g = internal::csr<_edge>(_n, elist); 557 | for (int i = 0; i < m; i++) { 558 | auto e = _edges[i]; 559 | edge_idx[i] += _g.start[e.from]; 560 | redge_idx[i] += _g.start[e.to]; 561 | _g.elist[edge_idx[i]].rev = redge_idx[i]; 562 | _g.elist[redge_idx[i]].rev = edge_idx[i]; 563 | } 564 | return _g; 565 | }(); 566 | 567 | auto result = slope(g, s, t, flow_limit); 568 | 569 | for (int i = 0; i < m; i++) { 570 | auto e = g.elist[edge_idx[i]]; 571 | _edges[i].flow = _edges[i].cap - e.cap; 572 | } 573 | 574 | return result; 575 | } 576 | 577 | private: 578 | int _n; 579 | std::vector _edges; 580 | 581 | // inside edge 582 | struct _edge { 583 | int to, rev; 584 | Cap cap; 585 | Cost cost; 586 | }; 587 | 588 | std::vector> slope(internal::csr<_edge>& g, int s, int t, Cap flow_limit) { 589 | // variants (C = maxcost): 590 | // -(n-1)C <= dual[s] <= dual[i] <= dual[t] = 0 591 | // reduced cost (= e.cost + dual[e.from] - dual[e.to]) >= 0 for all edge 592 | 593 | // dual_dist[i] = (dual[i], dist[i]) 594 | std::vector> dual_dist(_n); 595 | std::vector prev_e(_n); 596 | std::vector vis(_n); 597 | struct Q { 598 | Cost key; 599 | int to; 600 | bool operator<(Q r) const { return key > r.key; } 601 | }; 602 | std::vector que_min; 603 | std::vector que; 604 | auto dual_ref = [&]() { 605 | for (int i = 0; i < _n; i++) { 606 | dual_dist[i].second = std::numeric_limits::max(); 607 | } 608 | std::fill(vis.begin(), vis.end(), false); 609 | que_min.clear(); 610 | que.clear(); 611 | 612 | // que[0..heap_r) was heapified 613 | size_t heap_r = 0; 614 | 615 | dual_dist[s].second = 0; 616 | que_min.push_back(s); 617 | while (!que_min.empty() || !que.empty()) { 618 | int v; 619 | if (!que_min.empty()) { 620 | v = que_min.back(); 621 | que_min.pop_back(); 622 | } else { 623 | while (heap_r < que.size()) { 624 | heap_r++; 625 | std::push_heap(que.begin(), que.begin() + heap_r); 626 | } 627 | v = que.front().to; 628 | std::pop_heap(que.begin(), que.end()); 629 | que.pop_back(); 630 | heap_r--; 631 | } 632 | if (vis[v]) continue; 633 | vis[v] = true; 634 | if (v == t) break; 635 | // dist[v] = shortest(s, v) + dual[s] - dual[v] 636 | // dist[v] >= 0 (all reduced cost are positive) 637 | // dist[v] <= (n-1)C 638 | Cost dual_v = dual_dist[v].first, dist_v = dual_dist[v].second; 639 | for (int i = g.start[v]; i < g.start[v + 1]; i++) { 640 | auto e = g.elist[i]; 641 | if (!e.cap) continue; 642 | // |-dual[e.to] + dual[v]| <= (n-1)C 643 | // cost <= C - -(n-1)C + 0 = nC 644 | Cost cost = e.cost - dual_dist[e.to].first + dual_v; 645 | if (dual_dist[e.to].second - dist_v > cost) { 646 | Cost dist_to = dist_v + cost; 647 | dual_dist[e.to].second = dist_to; 648 | prev_e[e.to] = e.rev; 649 | if (dist_to == dist_v) { 650 | que_min.push_back(e.to); 651 | } else { 652 | que.push_back(Q{dist_to, e.to}); 653 | } 654 | } 655 | } 656 | } 657 | if (!vis[t]) { 658 | return false; 659 | } 660 | 661 | for (int v = 0; v < _n; v++) { 662 | if (!vis[v]) continue; 663 | // dual[v] = dual[v] - dist[t] + dist[v] 664 | // = dual[v] - (shortest(s, t) + dual[s] - dual[t]) + 665 | // (shortest(s, v) + dual[s] - dual[v]) = - shortest(s, 666 | // t) + dual[t] + shortest(s, v) = shortest(s, v) - 667 | // shortest(s, t) >= 0 - (n-1)C 668 | dual_dist[v].first -= dual_dist[t].second - dual_dist[v].second; 669 | } 670 | return true; 671 | }; 672 | Cap flow = 0; 673 | Cost cost = 0, prev_cost_per_flow = -1; 674 | std::vector> result = {{Cap(0), Cost(0)}}; 675 | while (flow < flow_limit) { 676 | if (!dual_ref()) break; 677 | Cap c = flow_limit - flow; 678 | for (int v = t; v != s; v = g.elist[prev_e[v]].to) { 679 | c = std::min(c, g.elist[g.elist[prev_e[v]].rev].cap); 680 | } 681 | for (int v = t; v != s; v = g.elist[prev_e[v]].to) { 682 | auto& e = g.elist[prev_e[v]]; 683 | e.cap += c; 684 | g.elist[e.rev].cap -= c; 685 | } 686 | Cost d = -dual_dist[s].first; 687 | flow += c; 688 | cost += c * d; 689 | if (prev_cost_per_flow == d) { 690 | result.pop_back(); 691 | } 692 | result.push_back({flow, cost}); 693 | prev_cost_per_flow = d; 694 | } 695 | return result; 696 | } 697 | }; 698 | 699 | } // namespace atcoder 700 | ``` 701 | 702 | ### Flow with Lower Bounds 703 | 704 | ```cpp 705 | const int INF = 0x3f3f3f3f; 706 | 707 | struct edge { 708 | int to, cap, rev; 709 | }; 710 | 711 | const int N = 60003; 712 | const int M = 400003; 713 | 714 | struct graph { 715 | int n, m; 716 | edge w[M]; 717 | int fr[M]; 718 | int num[N], cur[N], first[N]; 719 | edge e[M]; 720 | 721 | void init(int n) { 722 | this->n = n; 723 | m = 0; 724 | } 725 | 726 | void add_edge(int from, int to, int cap) { 727 | w[++m] = (edge){to, cap}; 728 | num[from]++, fr[m] = from; 729 | w[++m] = (edge){from, 0}; 730 | num[to]++, fr[m] = to; 731 | } 732 | 733 | void prepare() { 734 | first[1] = 1; 735 | for (int i = 2; i <= n; i++) first[i] = first[i - 1] + num[i - 1]; 736 | for (int i = 1; i < n; i++) num[i] = first[i + 1] - 1; 737 | num[n] = m; 738 | for (int i = 1; i <= m; i++) { 739 | e[first[fr[i]] + (cur[fr[i]]++)] = w[i]; 740 | 741 | if (!(i % 2)) { 742 | e[first[fr[i]] + cur[fr[i]] - 1].rev = 743 | first[w[i].to] + cur[w[i].to] - 1; 744 | e[first[w[i].to] + cur[w[i].to] - 1].rev = 745 | first[fr[i]] + cur[fr[i]] - 1; 746 | } 747 | } 748 | } 749 | 750 | int q[N]; 751 | int dist[N]; 752 | int t; 753 | 754 | bool bfs(int s) { 755 | int l = 1, r = 1; 756 | q[1] = s; 757 | memset(dist, -1, (n + 1) * 4); 758 | dist[s] = 0; 759 | while (l <= r) { 760 | int u = q[l++]; 761 | for (int i = first[u]; i <= num[u]; i++) { 762 | int v = e[i].to; 763 | if ((dist[v] != -1) || (!e[i].cap)) continue; 764 | dist[v] = dist[u] + 1; 765 | if (v == t) return true; 766 | q[++r] = v; 767 | } 768 | } 769 | return dist[t] != -1; 770 | } 771 | 772 | int dfs(int u, int flow) { 773 | if (u == t) return flow; 774 | for (int& i = cur[u]; i <= num[u]; i++) { 775 | int v = e[i].to; 776 | if (!e[i].cap || dist[v] != dist[u] + 1) continue; 777 | int t = dfs(v, min(flow, e[i].cap)); 778 | if (t) { 779 | e[i].cap -= t; 780 | e[e[i].rev].cap += t; 781 | return t; 782 | } 783 | } 784 | return 0; 785 | } 786 | 787 | i64 dinic(int s, int t) { 788 | i64 ans = 0; 789 | this->t = t; 790 | while (bfs(s)) { 791 | int flow; 792 | for (int i = 1; i <= n; i++) cur[i] = first[i]; 793 | while (flow = dfs(s, INF)) ans += (i64)flow; 794 | } 795 | return ans; 796 | } 797 | }; 798 | 799 | struct graph_bounds { 800 | int in[N]; 801 | int S, T, sum, cur; 802 | graph g; 803 | int n; 804 | 805 | void init(int n) { 806 | this->n = n; 807 | S = n + 1; 808 | T = n + 2; 809 | sum = 0; 810 | g.init(n + 2); 811 | } 812 | 813 | void add_edge(int from, int to, int low, int up) { 814 | g.add_edge(from, to, up - low); 815 | in[to] += low; 816 | in[from] -= low; 817 | } 818 | 819 | void build() { 820 | for (int i = 1; i <= n; i++) 821 | if (in[i] > 0) 822 | g.add_edge(S, i, in[i]), sum += in[i]; 823 | else if (in[i]) 824 | g.add_edge(i, T, -in[i]); 825 | g.prepare(); 826 | } 827 | 828 | bool canflow() { 829 | build(); 830 | int flow = g.dinic(S, T); 831 | return flow >= sum; 832 | } 833 | 834 | bool canflow(int s, int t) { 835 | g.add_edge(t, s, INF); 836 | build(); 837 | for (int i = 1; i <= g.m; i++) { 838 | edge& e = g.e[i]; 839 | if (e.to == s && e.cap == INF) { 840 | cur = i; 841 | break; 842 | } 843 | } 844 | int flow = g.dinic(S, T); 845 | return flow >= sum; 846 | } 847 | 848 | int maxflow(int s, int t) { 849 | if (!canflow(s, t)) return -1; 850 | return g.dinic(s, t); 851 | } 852 | 853 | int minflow(int s, int t) { 854 | if (!canflow(s, t)) return -1; 855 | edge& e = g.e[cur]; 856 | int flow = INF - e.cap; 857 | e.cap = g.e[e.rev].cap = 0; 858 | return flow - g.dinic(t, s); 859 | } 860 | } g; 861 | 862 | void solve() { 863 | int n = read(), m = read(), s = read(), t = read(); 864 | g.init(n); 865 | while (m--) { 866 | int u = read(), v = read(), low = read(), up = read(); 867 | g.add_edge(u, v, low, up); 868 | } 869 | } 870 | ``` 871 | 872 | ### Matching on General Graph 873 | 874 | ```cpp 875 | // jiangly 876 | struct Blossom { 877 | int n; 878 | vector> g; 879 | 880 | Blossom(int n) : n(n), g(n) {} 881 | 882 | void add_edge(int u, int v) { 883 | g[u].push_back(v); 884 | g[v].push_back(u); 885 | } 886 | 887 | vector solve() { 888 | vector match(n, -1), vis(n), link(n), f(n), dep(n); 889 | 890 | // disjoint set union 891 | auto find = [&](int u) { 892 | while (f[u] != u) u = f[u] = f[f[u]]; 893 | return u; 894 | }; 895 | 896 | auto lca = [&](int u, int v) { 897 | u = find(u); 898 | v = find(v); 899 | while (u != v) { 900 | if (dep[u] < dep[v]) swap(u, v); 901 | u = find(link[match[u]]); 902 | } 903 | return u; 904 | }; 905 | 906 | queue que; 907 | auto blossom = [&](int u, int v, int p) { 908 | while (find(u) != p) { 909 | link[u] = v; 910 | v = match[u]; 911 | if (vis[v] == 0) { 912 | vis[v] = 1; 913 | que.push(v); 914 | } 915 | f[u] = f[v] = p; 916 | u = link[v]; 917 | } 918 | }; 919 | 920 | // find an augmenting path starting from u and augment (if exist) 921 | auto augment = [&](int u) { 922 | while (!que.empty()) que.pop(); 923 | 924 | iota(f.begin(), f.end(), 0); 925 | 926 | // vis = 0 corresponds to inner vertices, vis = 1 corresponds to outer vertices 927 | fill(vis.begin(), vis.end(), -1); 928 | 929 | que.push(u); 930 | vis[u] = 1; 931 | dep[u] = 0; 932 | 933 | while (!que.empty()) { 934 | int u = que.front(); 935 | que.pop(); 936 | for (auto v : g[u]) { 937 | if (vis[v] == -1) { 938 | vis[v] = 0; 939 | link[v] = u; 940 | dep[v] = dep[u] + 1; 941 | 942 | // found an augmenting path 943 | if (match[v] == -1) { 944 | for (int x = v, y = u, temp; y != -1; x = temp, y = x == -1 ? -1 : link[x]) { 945 | temp = match[y]; 946 | match[x] = y; 947 | match[y] = x; 948 | } 949 | return; 950 | } 951 | 952 | vis[match[v]] = 1; 953 | dep[match[v]] = dep[u] + 2; 954 | que.push(match[v]); 955 | 956 | } else if (vis[v] == 1 && find(v) != find(u)) { 957 | // found a blossom 958 | int p = lca(u, v); 959 | blossom(u, v, p); 960 | blossom(v, u, p); 961 | } 962 | } 963 | } 964 | }; 965 | 966 | // find a maximal matching greedily (decrease constant) 967 | auto greedy = [&]() { 968 | for (int u = 0; u < n; ++u) { 969 | if (match[u] != -1) continue; 970 | for (auto v : g[u]) { 971 | if (match[v] == -1) { 972 | match[u] = v; 973 | match[v] = u; 974 | break; 975 | } 976 | } 977 | } 978 | }; 979 | 980 | greedy(); 981 | 982 | for (int u = 0; u < n; ++u) 983 | if (match[u] == -1) augment(u); 984 | 985 | return match; 986 | } 987 | }; 988 | ``` 989 | 990 | ### Link-Cut Tree 991 | 992 | ```cpp 993 | // Chestnut 994 | const int N = 50005; 995 | 996 | #define lc son[x][0] 997 | #define rc son[x][1] 998 | 999 | struct Splay { 1000 | int fa[N], son[N][2]; 1001 | int st[N]; 1002 | bool rev[N]; 1003 | inline int which(int x) { 1004 | for (int i = 0; i < 2; i++) 1005 | if (son[fa[x]][i] == x) return i; 1006 | return -1; 1007 | } 1008 | 1009 | inline void pushdown(int x) { 1010 | if (rev[x]) { 1011 | rev[x] ^= 1; 1012 | rev[lc] ^= 1; 1013 | rev[rc] ^= 1; 1014 | swap(lc, rc); 1015 | } 1016 | } 1017 | 1018 | inline void rotate(int x) { 1019 | int f = fa[x], w = which(x) ^ 1, c = son[x][w]; 1020 | fa[x] = fa[f]; 1021 | if (which(f) != -1) son[fa[f]][which(f)] = x; 1022 | fa[c] = f; 1023 | son[f][w ^ 1] = c; 1024 | fa[f] = x; 1025 | son[x][w] = f; 1026 | } 1027 | 1028 | inline void splay(int x) { 1029 | int top = 0; 1030 | st[++top] = x; 1031 | for (int i = x; which(i) != -1; i = fa[i]) { 1032 | st[++top] = fa[i]; 1033 | } 1034 | for (int i = top; i; i--) pushdown(st[i]); 1035 | while (which(x) != -1) { 1036 | int f = fa[x]; 1037 | if (which(f) != -1) { 1038 | if (which(x) ^ which(f)) rotate(x); 1039 | else rotate(f); 1040 | } 1041 | rotate(x); 1042 | } 1043 | } 1044 | 1045 | void access(int x) { 1046 | int t = 0; 1047 | while (x) { 1048 | splay(x); 1049 | rc = t; 1050 | t = x; 1051 | x = fa[x]; 1052 | } 1053 | } 1054 | 1055 | void rever(int x) { 1056 | access(x); 1057 | splay(x); 1058 | rev[x] ^= 1; 1059 | } 1060 | 1061 | void link(int x, int y) { 1062 | rever(x); 1063 | fa[x] = y; 1064 | splay(x); 1065 | } 1066 | 1067 | void cut(int x, int y) { 1068 | rever(x); 1069 | access(y); 1070 | splay(y); 1071 | son[y][0] = fa[x] = 0; 1072 | } 1073 | 1074 | int find(int x) { 1075 | access(x); 1076 | splay(x); 1077 | int y = x; 1078 | while (son[y][0]) y = son[y][0]; 1079 | return y; 1080 | } 1081 | } T; 1082 | 1083 | int n, m; 1084 | 1085 | int main() { 1086 | char ch[10]; 1087 | int x, y; 1088 | scanf("%d%d", &n, &m); 1089 | for (int i = 1; i <= m; i++) { 1090 | scanf("%s", ch); 1091 | scanf("%d%d", &x, &y); 1092 | if (ch[0] == 'C') T.link(x, y); 1093 | else if (ch[0] == 'D') T.cut(x, y); 1094 | else { 1095 | if (T.find(x) == T.find(y)) printf("Yes\n"); 1096 | else printf("No\n"); 1097 | } 1098 | } 1099 | } 1100 | ``` 1101 | 1102 | ### NTT for NTT-unfriendly Modulus 1103 | 1104 | ```cpp 1105 | // memset0 1106 | const int N = 4e5 + 10, G = 3, P[3] = {469762049, 998244353, 1004535809}; 1107 | int n1, n2, k, n, p, p1, p2, M2; 1108 | int a[N], b[N], f[3][N], g[N], rev[N], ans[N]; 1109 | 1110 | void ntt(int *a, int g, int p) { 1111 | for (int i = 0; i < n; i++) if (i < rev[i]) swap(a[i], a[rev[i]]); 1112 | for (int len = 1; len < n; len <<= 1) { 1113 | int wn = qk(g, (p - 1) / (len << 1), p); 1114 | for (int i = 0; i < n; i += (len << 1)) { 1115 | int w = 1; 1116 | for (int j = 0; j < len; j++, w = (i64)w * wn % p) { 1117 | int x = a[i + j], y = (i64)w * a[i + j + len] % p; 1118 | a[i + j] = (x + y) % p, a[i + j + len] = (x - y + p) % p; 1119 | } 1120 | } 1121 | } 1122 | } 1123 | 1124 | int merge(int a1, int a2, int A2) { 1125 | i64 M1 = (i64)p1 * p2; 1126 | i64 A1 = ((i64)inv(p2, p1) * a1 % p1 * p2 + (i64)inv(p1, p2) * a2 % p2 * p1) % M1; 1127 | i64 K = ((A2 - A1) % M2 + M2) % M2 * inv(M1 % M2, M2) % M2; 1128 | int ans = (A1 + M1 % p * K) % p; 1129 | return ans; 1130 | } 1131 | 1132 | void go() { 1133 | read(n1), read(n2), read(p); 1134 | p1 = P[0], p2 = P[1], M2 = P[2]; 1135 | for (int i = 0; i <= n1; i++) read(a[i]); 1136 | for (int i = 0; i <= n2; i++) read(b[i]); 1137 | n = 1; while (n <= (n1 + n2)) n <<= 1, ++k; 1138 | for (int i = 0; i < n; i++) { 1139 | rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (k - 1)); 1140 | } 1141 | for (int k = 0; k < 3; k++) { 1142 | for (int i = 0; i < n; i++) f[k][i] = a[i] % P[k]; 1143 | for (int i = 0; i < n; i++) g[i] = b[i] % P[k]; 1144 | ntt(f[k], G, P[k]), ntt(g, G, P[k]); 1145 | for (int i = 0; i < n; i++) f[k][i] = (i64)f[k][i] * g[i] % P[k]; 1146 | ntt(f[k], inv(G, P[k]), P[k]); 1147 | for (int i = 0; i < n; i++) f[k][i] = (i64)f[k][i] * inv(n, P[k]) % P[k]; 1148 | } 1149 | for (int i = 0; i <= n1 + n2; i++) ans[i] = merge(f[0][i], f[1][i], f[2][i]); 1150 | } 1151 | ``` 1152 | 1153 | ### Geometry 1154 | 1155 | ```cpp 1156 | // Great-circle distance on the sphere 1157 | // Voleking 1158 | ld Dist(ld la1, ld lo1, ld la2, ld lo2, ld R) { 1159 | la1 *= PI / 180, lo1 *= PI / 180, la2 *= PI / 180, lo2 *= PI / 180; 1160 | ld x1 = cos(la1) * sin(lo1), y1 = cos(la1) * cos(lo1), z1 = sin(la1); 1161 | ld x2 = cos(la2) * sin(lo2), y2 = cos(la2) * cos(lo2), z1 = sin(la2); 1162 | return R * acos(x1 * x2 + y1 * y2 + z1 * z2); 1163 | } 1164 | 1165 | // jiry_2 1166 | int cmp(ld k1, ld k2) { 1167 | return sgn(k1 - k2); 1168 | } 1169 | V proj(V k1, V k2, V q) { // Projection of point q onto line k1,k2 1170 | V k = k2 - k1; 1171 | return k1 + k * (dot(q - k1, k) / k.abs2()); 1172 | } 1173 | V reflect(V k1, V k2, V q) { 1174 | return proj(k1, k2, q) * 2 - q; 1175 | } 1176 | int clockwise(V k1, V k2, V k3) { // k1 k2 k3 counterclockwise 1 clockwise -1 otherwise 0 1177 | return sgn(det(k2 - k1, k3 - k1)); 1178 | } 1179 | int checkLL(V k1, V k2, V k3, V k4) { // Check the intersection point of line (L) and segment (S) k1,k2 and k3,k4 1180 | return cmp(det(k3 - k1, k4 - k1), det(k3 - k2, k4 - k2)) != 0; 1181 | } 1182 | V getLL(V k1, V k2, V k3, V k4) { 1183 | ld w1 = det(k1 - k3, k4 - k3), w2 = det(k4 - k3, k2 - k3); 1184 | return (k1 * w2 + k2 * w1) / (w1 + w2); 1185 | } 1186 | vector getHL(vector& L) { // Get the half-plane intersection, the half-plane is counterclockwise, and the output is counterclockwise 1187 | sort(L.begin(), L.end()); 1188 | deque q; 1189 | for (int i = 0; i < (int) L.size(); i++) { 1190 | if (i && sameDir(L[i], L[i - 1])) continue; 1191 | while (q.size() > 1 && !checkpos(q[q.size() - 2], q[q.size() - 1], L[i])) q.pop_back(); 1192 | while (q.size() > 1 && !checkpos(q[1], q[0], L[i])) q.pop_front(); 1193 | q.push_back(L[i]); 1194 | } 1195 | while (q.size() > 2 && !checkpos(q[q.size() - 2], q[q.size() - 1], q[0])) q.pop_back(); 1196 | while (q.size() > 2 && !checkpos(q[1], q[0], q[q.size() - 1])) q.pop_front(); 1197 | vector ans; 1198 | for (int i = 0; i < q.size(); i++) ans.push_back(q[i]); 1199 | return ans; 1200 | } 1201 | int checkposCC(circle k1, circle k2) { // Return the number of common tangent lines of two circles 1202 | if (cmp(k1.r, k2.r) == -1) swap(k1, k2); 1203 | ld dis = k1.o.dis(k2.o); 1204 | int w1 = cmp(dis, k1.r + k2.r), w2 = cmp(dis, k1.r - k2.r); 1205 | if (w1 > 0) return 4; 1206 | else if (w1 == 0) return 3; 1207 | else if (w2 > 0) return 2; 1208 | else if (w2 == 0) return 1; 1209 | else return 0; 1210 | } 1211 | vector getCL(circle k1, V k2, V k3) { // Given k2->k3 direction, give out p, the two tangent points 1212 | V k = proj(k2, k3, k1.o); 1213 | ld d = k1.r * k1.r - (k - k1.o).abs2(); 1214 | if (sgn(d) == -1) return {}; 1215 | V del = (k3 - k2).unit() * sqrt(max((ld) 0.0, d)); 1216 | return {k - del, k + del}; 1217 | } 1218 | vector TangentoutCC(circle k1, circle k2) { 1219 | int pd = checkposCC(k1, k2); 1220 | if (pd == 0) return {}; 1221 | if (pd == 1) { 1222 | V k = getCC(k1, k2)[0]; 1223 | return { (line){k, k} }; 1224 | } 1225 | if (cmp(k1.r, k2.r) == 0) { 1226 | V del = (k2.o - k1.o).unit().turn90().getdel(); 1227 | return { 1228 | (line){k1.o - del * k1.r, k2.o - del * k2.r}, 1229 | (line){k1.o + del * k1.r, k2.o + del * k2.r} 1230 | }; 1231 | } else { 1232 | V p = (k2.o * k1.r - k1.o * k2.r) / (k1.r - k2.r); 1233 | vector A = TangentCP(k1, p), B = TangentCP(k2, p); 1234 | vector ans; 1235 | for (int i = 0; i < A.size(); i++) ans.push_back((line){A[i], B[i]}); 1236 | return ans; 1237 | } 1238 | } 1239 | vector TangentinCC(circle k1, circle k2) { 1240 | int pd = checkposCC(k1, k2); 1241 | if (pd <= 2) return {}; 1242 | if (pd == 3) { 1243 | V k = getCC(k1, k2)[0]; 1244 | return { (line){k, k} }; 1245 | } 1246 | V p = (k2.o * k1.r + k1.o * k2.r) / (k1.r + k2.r); 1247 | vector A = TangentCP(k1, p), B = TangentCP(k2, p); 1248 | vector ans; 1249 | for (int i = 0; i < A.size(); i++) ans.push_back((line){A[i], B[i]}); 1250 | return ans; 1251 | } 1252 | vector TangentCC(circle k1, circle k2) { 1253 | int flag = 0; 1254 | if (k1.r < k2.r) swap(k1, k2), flag = 1; 1255 | vector A = TangentoutCC(k1, k2), B = TangentinCC(k1, k2); 1256 | for (line k: B) A.push_back(k); 1257 | if (flag) for (line& k: A) swap(k[0], k[1]); 1258 | return A; 1259 | } 1260 | ld convexDiameter(vector A) { 1261 | int now = 0, n = A.size(); 1262 | ld ans = 0; 1263 | for (int i = 0; i < A.size(); i++) { 1264 | now = max(now, i); 1265 | while (1) { 1266 | ld k1 = A[i].dis(A[now % n]), k2 = A[i].dis(A[(now + 1) % n]); 1267 | ans = max(ans, max(k1, k2)); 1268 | if (k2 > k1) now++; 1269 | else break; 1270 | } 1271 | } 1272 | return ans; 1273 | } 1274 | vector convexcut(vector A, V k1, V k2) { // Keep points k1,k2,p counterclockwise 1275 | int n = A.size(); 1276 | A.push_back(A[0]); 1277 | vector ans; 1278 | for (int i = 0; i < n; i++) { 1279 | int w1 = clockwise(k1, k2, A[i]), w2 = clockwise(k1, k2, A[i + 1]); 1280 | if (w1 >= 0) ans.push_back(A[i]); 1281 | if (w1 * w2 < 0) ans.push_back(getLL(k1, k2, A[i], A[i + 1])); 1282 | } 1283 | return ans; 1284 | } 1285 | ``` 1286 | 1287 | ### References 1288 | 1289 | [Nyaan's Library](https://nyaannyaan.github.io/library/) 1290 | [F0RE1GNERS](https://github.com/F0RE1GNERS/template) 1291 | [YouKn0wWho](https://github.com/ShahjalalShohag/code-library) 1292 | [OI Wiki](https://oi-wiki.org/) 1293 | [cp-algorithms](https://cp-algorithms.com/) 1294 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Yiyuan Luo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Algorithmic code snippets, mainly for programming contests -------------------------------------------------------------------------------- /header/Header-Book.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ICPC template 3 | author: [qdd,Chestnut,WindJ0Y,dongshunyao] 4 | titlepage: true 5 | geometry: "a4paper, top=1.6cm, bottom=2cm, left=1.8cm, right=1.8cm" 6 | fontsize: 9pt 7 | linestretch: 1.0 8 | mainfont: Noto Sans Light 9 | sansfont: Noto Sans Light 10 | monofont: DejaVu Sans Mono 11 | CJKmainfont: Noto Sans CJK SC Light 12 | toc: true 13 | book: true 14 | ... 15 | 16 | \newpage 17 | -------------------------------------------------------------------------------- /header/Header-non-Book.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ICPC template 3 | author: [qdd,Chestnut,WindJ0Y,dongshunyao] 4 | titlepage: true 5 | geometry: "a4paper, top=1.6cm, bottom=2cm, left=1.8cm, right=1.8cm" 6 | fontsize: 9pt 7 | linestretch: 1.0 8 | mainfont: Noto Sans Light 9 | sansfont: Noto Sans Light 10 | monofont: DejaVu Sans Mono 11 | CJKmainfont: Noto Sans CJK SC Light 12 | toc: true 13 | ... 14 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | # Contents 2 | nav: 3 | - 输入 & 输出: 0-IO.md 4 | - 数据结构: 1-Structure.md 5 | - 图论: 2-Graph.md 6 | - 字符串: 3-String.md 7 | - 数学: 4-Math.md 8 | - 计算几何: 5-Geometry.md 9 | - 杂项: 6-Other.md 10 | --------------------------------------------------------------------------------