├── 2d_fenwick_tree.cpp ├── 2sat.cpp ├── aho_corasick.cpp ├── bigint32.cpp ├── binomod.cpp ├── binsearch.cpp ├── convex_hull ├── descasc.cpp └── dynamic.cpp ├── fast_io.cpp ├── fenwick_tree.cpp ├── gauss.cpp ├── geometry.cpp ├── kmp.cpp ├── lca.cpp ├── math_stuff.cpp ├── max_matching.cpp ├── min_cost_max_flow └── solution.cpp ├── mincostflow.cpp ├── monotonic_queue.cpp ├── mst ├── kruskal.cpp └── prim.cpp ├── number_theory.cpp ├── numerical_integration.cpp ├── optimization.cpp ├── quadtree.cpp ├── radix_sort.cpp ├── range_tree.cpp ├── segment_tree.cpp ├── segment_tree_skeleton.cpp ├── shortest_path └── dijkstra.cpp ├── skiplist.cpp ├── splay_tree.cpp ├── stl_splay_tree.cpp ├── suffix_automaton.cpp ├── suffixarray_lcp_based.cpp ├── tests └── test_num_theory.cpp ├── treap.cpp ├── treap_multi.cpp ├── treap_simple.cpp ├── treap_supersimple.cpp ├── tree_aggregation.cpp └── weight_balanced_tree.cpp /2d_fenwick_tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | typedef long long ll; 4 | 5 | const int maxn = 111; 6 | int max_x = 100, max_y = 100; 7 | int tree[maxn][maxn]; 8 | 9 | // 2D point-update prefix-query 10 | void update_idx(int x, int y, int val) { 11 | for (int i = x; i <= max_x; i += i & -i) 12 | for (int j = y; j <= max_y; j += j & -j) 13 | tree[i][j] += val; 14 | } 15 | int read_prefix(int x, int y) { 16 | int res = 0; 17 | for (int i = x; i > 0; i -= i & -i) 18 | for (int j = y; j > 0; j -= j & -j) 19 | res += tree[i][j]; 20 | return res; 21 | } 22 | 23 | // 2D range-update range-query 24 | // uses additively written, abelian group structure of T 25 | // redefine T + T, T - T, T * int, -T to your needs 26 | typedef ll T; 27 | typedef T Tree[maxn][maxn]; 28 | Tree A, B, C, D; 29 | void update_idx(Tree t, int x, int y, T val) { 30 | for (int i = x; i <= max_x; i += i & -i) 31 | for (int j = y; j <= max_y; j += j & -j) 32 | t[i][j] = t[i][j] + val; 33 | } 34 | void update_prefix(int x, int y, T val) { 35 | update_idx(A, 1, 1, val); 36 | 37 | update_idx(A, 1, y + 1, -val); 38 | update_idx(B, 1, y + 1, val * y); 39 | 40 | update_idx(A, x + 1, 1, -val); 41 | update_idx(C, x + 1, 1, val * x); 42 | 43 | update_idx(A, x + 1, y + 1, val); 44 | update_idx(B, x + 1, y + 1, -val * y); 45 | update_idx(C, x + 1, y + 1, -val * x); 46 | update_idx(D, x + 1, y + 1, val * x * y); 47 | } 48 | T read_prefix(int x, int y) { 49 | T a, b, c, d; 50 | a = b = c = d = 0; 51 | for (int i = x; i > 0; i -= i & -i) 52 | for (int j = y; j > 0; j -= j & -j) { 53 | a = a + A[i][j]; b = b + B[i][j]; c = c + C[i][j]; d = d + D[i][j]; 54 | } 55 | return a * x * y + b * x + c * y + d; 56 | } 57 | // helpers 58 | void update_range(int x1, int y1, int x2, int y2, T val) { 59 | update_prefix(x2, y2, val); 60 | update_prefix(x1 - 1, y2, -val); 61 | update_prefix(x2, y1 - 1, -val); 62 | update_prefix(x1 - 1, y1 - 1, val); 63 | } 64 | T read_range(int x1, int y1, int x2, int y2) { 65 | return read_prefix(x2, y2) 66 | - read_prefix(x1 - 1, y2) - read_prefix(x2, y1 - 1) 67 | + read_prefix(x1 - 1, y1 - 1); 68 | } 69 | T read_idx(int x, int y) { 70 | return read_range(x,y,x,y); 71 | } 72 | 73 | // reference 74 | ll naive[maxn][maxn]; 75 | void update_idx_ref(int x, int y, ll val) { 76 | naive[x][y] += val; 77 | } 78 | void update_prefix_ref(int x, int y, ll val) { 79 | for (int i = 1; i <= x; ++i) 80 | for (int j = 1; j <= y; ++j) 81 | naive[i][j] += val; 82 | } 83 | ll read_prefix_ref(int x, int y) { 84 | ll res = 0; 85 | for (int i = 1; i <= x; ++i) 86 | for (int j = 1; j <= y; ++j) 87 | res += naive[i][j]; 88 | return res; 89 | } 90 | 91 | int main() { 92 | update_range(3, 2, 4, 4, 2); 93 | update_range(2, 4, 5, 5, 3); 94 | for (int i = 1; i <= 6; ++i) { 95 | for (int j = 1; j <= 6; ++j) 96 | cout << read_idx(i, j) << " "; 97 | cout << endl; 98 | } 99 | return 0; 100 | srand(time(NULL)); 101 | for (int i = 1; i <= 100000; ++i) { 102 | int x = 1 + (rand() % max_x); 103 | int y = 1 + (rand() % max_y); 104 | int ty = rand() % 2; 105 | if (ty == 0) { 106 | int val = rand() % 10000; 107 | update_prefix(x, y, val); 108 | update_prefix_ref(x, y, val); 109 | } else if (ty == 1) { 110 | assert(read_prefix_ref(x,y) == read_prefix(x,y)); 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /2sat.cpp: -------------------------------------------------------------------------------- 1 | const int maxn = 10010; // 2-sat: maxn = 2*maxvars 2 | bool vis[maxn]; 3 | int col, color[maxn]; 4 | vector adj[maxn], radj[maxn], bycol[maxn+1], st; 5 | 6 | void init() { rep(i,0,maxn) adj[i].clear(), radj[i].clear(); } 7 | void dfs(int u, vector adj[]) { 8 | if (vis[u]) return; 9 | vis[u] = 1; 10 | foreach(it,adj[u]) dfs(*it, adj); 11 | if (col) { 12 | color[u] = col; 13 | bycol[col].pb(u); 14 | } else st.pb(u); 15 | } 16 | // this computes SCCs, outputs them in bycol, in topological order 17 | void kosaraju(int n) { // n = number of nodes 18 | st.clear(); 19 | clr(vis,0); 20 | col=0; 21 | rep(i,0,n) dfs(i,adj); 22 | clr(vis,0); 23 | clr(color,0); 24 | while(!st.empty()) { 25 | bycol[++col].clear(); 26 | int x = st.back(); st.pop_back(); 27 | if(color[x]) continue; 28 | dfs(x, radj); 29 | } 30 | } 31 | // 2-SAT 32 | int assign[maxn]; // for 2-sat only 33 | int var(int x) { return x<<1; } 34 | bool solvable(int vars) { 35 | kosaraju(2*vars); 36 | rep(i,0,vars) if (color[var(i)] == color[1^var(i)]) return 0; 37 | return 1; 38 | } 39 | void assign_vars() { 40 | clr(assign,0); 41 | rep(c,1,col+1) { 42 | foreach(it,bycol[c]) { 43 | int v = *it >> 1; 44 | bool neg = *it&1; 45 | if (assign[v]) continue; 46 | assign[v] = neg?1:-1; 47 | } 48 | } 49 | } 50 | void add_impl(int v1, int v2) { adj[v1].push_back(v2); radj[v2].push_back(v1); } 51 | void add_equiv(int v1, int v2) { add_impl(v1, v2); add_impl(v2, v1); } 52 | void add_or(int v1, int v2) { add_impl(1^v1, v2); add_impl(1^v2, v1); } 53 | void add_xor(int v1, int v2) { add_or(v1, v2); add_or(1^v1, 1^v2); } 54 | void add_true(int v1) { add_impl(1^v1, v1); } 55 | void add_and(int v1, int v2) { add_true(v1); add_true(v2); } 56 | 57 | int parse(int i) { 58 | if (i>0) return var(i-1); 59 | else return 1^var(-i-1); 60 | } 61 | int main() { 62 | int n, m; cin >> n >> m; // m = number of clauses to follow 63 | while (m--) { 64 | string op; int x, y; cin >> op >> x >> y; 65 | x = parse(x); 66 | y = parse(y); 67 | if (op == "or") add_or(x, y); 68 | if (op == "and") add_and(x, y); 69 | if (op == "xor") add_xor(x, y); 70 | if (op == "imp") add_impl(x, y); 71 | if (op == "equiv") add_equiv(x, y); 72 | } 73 | if (!solvable(n)) { 74 | cout << "Impossible" << endl; return 0; 75 | } 76 | assign_vars(); 77 | rep(i,0,n) cout << ((assign[i]>0)?(i+1):-i-1) << endl; 78 | } 79 | -------------------------------------------------------------------------------- /aho_corasick.cpp: -------------------------------------------------------------------------------- 1 | const int K = 20; 2 | struct vertex { 3 | vertex *next[K], *go[K], *link, *p; 4 | int pch; 5 | bool leaf; 6 | int is_accepting = -1; 7 | }; 8 | 9 | vertex *create() { 10 | vertex *root = new vertex(); 11 | root->link = root; 12 | return root; 13 | } 14 | 15 | void add_string (vertex *v, const vector& s) { 16 | for (int a: s) { 17 | if (!v->next[a]) { 18 | vertex *w = new vertex(); 19 | w->p = v; 20 | w->pch = a; 21 | v->next[a] = w; 22 | } 23 | v = v->next[a]; 24 | } 25 | v->leaf = 1; 26 | } 27 | 28 | vertex* go(vertex* v, int c); 29 | 30 | vertex* get_link(vertex *v) { 31 | if (!v->link) 32 | v->link = v->p->p ? go(get_link(v->p), v->pch) : v->p; 33 | return v->link; 34 | } 35 | 36 | vertex* go(vertex* v, int c) { 37 | if (!v->go[c]) { 38 | if (v->next[c]) 39 | v->go[c] = v->next[c]; 40 | else 41 | v->go[c] = v->p ? go(get_link(v), c) : v; 42 | } 43 | return v->go[c]; 44 | } 45 | 46 | bool is_accepting(vertex *v) { 47 | if (v->is_acceping == -1) 48 | v->is_accepting = get_link(v) == v ? false : (v->leaf || is_accepting(get_link(v))); 49 | return v->is_accepting; 50 | } 51 | -------------------------------------------------------------------------------- /bigint32.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int basesz=32; 5 | const uint64_t base=1ull< 0 || x) { 10 | res += '0' + (x&1); 11 | x>>=1; 12 | } 13 | reverse(res.begin(), res.end()); 14 | return res; 15 | } 16 | 17 | struct BigInt { 18 | vector digs; 19 | BigInt(uint64_t x=0) { while (x) digs.push_back(x%base), x /= base; } 20 | BigInt(const BigInt& other) : digs(other.digs) {} 21 | void operator=(const BigInt& other) { digs = other.digs; } 22 | 23 | void normalize() { 24 | while (digs.size() && !digs.back()) digs.pop_back(); 25 | } 26 | 27 | bool zero() { return digs.empty(); } 28 | 29 | uint64_t value() { 30 | uint64_t res = 0; 31 | for (auto it = digs.rbegin(); it != digs.rend(); ++it) 32 | res = res * base + *it; 33 | return res; 34 | } 35 | 36 | void add(int i, uint64_t x) { 37 | if (!x) return; 38 | if (i >= (int)digs.size()) 39 | digs.resize(i + 1); 40 | uint64_t y = uint64_t{digs[i]} + x; 41 | if (y < base) { digs[i] = y; return; } 42 | digs[i] = y % base; 43 | assert(digs[i] < base); 44 | add(i + 1, y / base); 45 | } 46 | 47 | BigInt operator++() { 48 | BigInt old(*this); 49 | add(0,1); 50 | return old; 51 | } 52 | 53 | BigInt operator+(const BigInt& other) const { 54 | BigInt res(other); 55 | for (size_t i = 0; i < digs.size(); ++i) 56 | res.add(i, digs[i]); 57 | res.normalize(); 58 | return res; 59 | } 60 | 61 | BigInt operator*(const BigInt& other) const { 62 | BigInt res; 63 | for (size_t i = 0; i < digs.size(); ++i) 64 | for (size_t j = 0; j < other.digs.size(); ++j) { 65 | assert(digs[i] < base); 66 | assert(other.digs[j] < base); 67 | res.add(i + j, 1ll * digs[i] * other.digs[j]); 68 | } 69 | res.normalize(); 70 | return res; 71 | } 72 | 73 | BigInt operator>>(int shift) const { 74 | assert(shift < basesz); 75 | BigInt res; 76 | res.digs.resize(digs.size()); 77 | for (size_t i = 0; i < digs.size(); ++i) { 78 | uint32_t& cur = res.digs[i]; 79 | cur = digs[i]>>shift; 80 | if (i + 1 < digs.size()) 81 | cur |= (uint64_t{digs[i+1]} << (basesz - shift)) & (base - 1); 82 | } 83 | res.normalize(); 84 | return res; 85 | } 86 | 87 | bool operator<(const BigInt& other) const { 88 | if (digs.size() != other.digs.size()) 89 | return digs.size() < other.digs.size(); 90 | return lexicographical_compare(digs.rbegin(), digs.rend(), 91 | other.digs.rbegin(), other.digs.rend()); 92 | } 93 | 94 | bool operator==(const BigInt& other) const { 95 | return !(*this < other) && !(other < *this); 96 | } 97 | 98 | pair divmod(const BigInt& other) const { 99 | BigInt lo(0), hi(*this + 1); // here, hi is exclusive 100 | while (lo + 1 < hi) { 101 | BigInt mid = (lo + hi)>>1; 102 | //cout << " lo=" << lo << " hi=" << hi << " mid=" << mid << endl; 103 | //cout << " " << (*this) << " < " << (mid*other) << " = " << (*this>1; 112 | if (tmp + mid < *this) lo = mid + 1; 113 | else hi = mid; 114 | } 115 | return {div, lo}; 116 | } 117 | 118 | BigInt operator/(const BigInt& other) const { return divmod(other).first; } 119 | BigInt operator%(const BigInt& other) const { return divmod(other).second; } 120 | 121 | BigInt powmod(BigInt exp, BigInt mod) const { 122 | BigInt res(1), base(*this); 123 | res = res % mod; 124 | for (auto chunk : exp.digs) 125 | for (int i = 0; i < basesz; ++i) { 126 | if ((chunk >> i) & 1) 127 | res = (res * base) % mod; 128 | base = (base * base) % mod; 129 | } 130 | return res; 131 | } 132 | 133 | string str(int base=10) const { 134 | const char* alph = "0123456789abcdef"; 135 | assert(0 <= base && base <= 16); 136 | 137 | BigInt bigbase(base), tmp(*this); 138 | string res; 139 | while (!tmp.zero()) { 140 | res += alph[(tmp % bigbase).value()]; 141 | tmp = tmp / base; 142 | } 143 | if (res.empty()) res += '0'; 144 | reverse(res.begin(), res.end()); 145 | return res; 146 | } 147 | 148 | string bin() const { return str(2); } 149 | string hex() const { return str(16); } 150 | 151 | static BigInt parse(const string& s, int base=10) { 152 | const char* alph = "0123456789abcdef"; 153 | BigInt res(0), basebig(base); 154 | for (char c: s) { 155 | c = tolower(c); 156 | const char* p = strchr(alph, c); 157 | assert(p); 158 | res = res * basebig + BigInt(p - alph); 159 | } 160 | return res; 161 | } 162 | }; 163 | 164 | ostream& operator<<(ostream& out, const BigInt& x) { 165 | return out << x.str(); 166 | } 167 | 168 | void test(int ax, int bx, int cx) { 169 | BigInt a(ax); 170 | BigInt b(bx); 171 | BigInt c(cx); 172 | 173 | cout << "assert "; 174 | cout << a << " * "; 175 | cout << b << " == "; 176 | cout << a*b << endl; 177 | 178 | cout << "assert "; 179 | cout << a << " + "; 180 | cout << b << " == "; 181 | cout << a+b << endl; 182 | 183 | cout << "assert "; 184 | cout << a << " >> 1 == "; 185 | cout << (a>>1) << endl; 186 | 187 | cout << "assert "; 188 | cout << a << " / "; 189 | cout << b << " == "; 190 | cout << a/b << endl; 191 | 192 | cout << "assert "; 193 | cout << a << " % "; 194 | cout << b << " == "; 195 | cout << a%b << endl; 196 | 197 | cout << "assert "; 198 | cout << "pow(" << a << ", "; 199 | cout << c << ", "; 200 | cout << b << ") == "; 201 | cout << a.powmod(c, b) << endl; 202 | } 203 | 204 | using timer = chrono::high_resolution_clock; 205 | 206 | int main() { 207 | BigInt p = BigInt::parse( 208 | "d65d758b1c9d035fe54550ff437143d633f0284a4551318d79710c5a9230b55f", 16); 209 | BigInt q = BigInt::parse( 210 | "1630b16242196ebaf50ebcd4a7da00eb6c49b6f69c6d11e5af4e13c48d0b9891", 16); 211 | BigInt n = p*q; 212 | 213 | assert(n.hex() == 214 | "1294ce28e3f06deb70b2c67b6475a4524822b58aba45c62eb97b8bcc17e370af" 215 | "3f74266f653251c1f42d9a931bce67270db72780b0711ee61179cbd2d75c22cf"); 216 | 217 | BigInt d = BigInt::parse( 218 | "b59e4678e77fe6e6a368c922cd8c13d92dbc153b25f95a64da16fd18a76630bd" 219 | "b90adfa5cc3a7e9891d21a25a9c8192bcc46032baaf00e8bdcbebc0aaa6a781", 16); 220 | BigInt e(0x010001); 221 | 222 | BigInt m = BigInt::parse("666f6f626172", 16); 223 | BigInt c = m.powmod(e, n); 224 | 225 | auto start = timer::now(); 226 | 227 | assert(m == c.powmod(d, n)); 228 | 229 | uint64_t msecs = chrono::duration_cast( 230 | timer::now() - start).count(); 231 | cout << "powmod time = " << setprecision(2) << fixed << 1.*msecs/1e6 << endl; 232 | 233 | /* 234 | for (int ax = 0; ax <= 100; ++ax) { 235 | for (int bx = 1; bx <= 100; ++bx) { 236 | for (int cx = 0; bx <= 100; ++bx) { 237 | test(ax, bx, cx); 238 | } 239 | } 240 | } 241 | */ 242 | } 243 | -------------------------------------------------------------------------------- /binomod.cpp: -------------------------------------------------------------------------------- 1 | // compute (n!)_p = product_{i=1, i%p!=0}^n {i} mod p^q 2 | // implementation based on 3 | // http://www.cse.sc.edu/~maxal/gpscripts/binomod.gp 4 | // (function factorialmodp1) 5 | ll partial_fac_mod_pq(ll n, ll p, ll q) { 6 | if (n <= 1) return 1; 7 | ll pq = 1; 8 | for (int i = 0; i < q; ++i) pq *= p; 9 | ll r = ((n/pq) % 2) ? -1 : 1; 10 | for (int i = 2; i <= n % pq; ++i) 11 | if (i % p) 12 | r = (r * i) % pq; 13 | while (r < 0) r += pq; 14 | return r; 15 | } 16 | 17 | // compute C(n,m) modulo p^q using the Theorem 1 outlined in 18 | // http://www.dms.umontreal.ca/~andrew/Binomial/genlucas.html 19 | // Implementation based on 20 | // http://www.cse.sc.edu/~maxal/gpscripts/binomod.gp 21 | const int binomod_maxdigs = 100;// max number of digits of n in base p 22 | ll binomod(ll n, ll m, ll p, ll q) { 23 | static int ndigs[binomod_maxdigs], mdigs[binomod_maxdigs], 24 | rdigs[binomod_maxdigs], N[binomod_maxdigs], 25 | M[binomod_maxdigs], R[binomod_maxdigs], e[binomod_maxdigs]; 26 | memset(ndigs, 0, sizeof ndigs); 27 | memset(mdigs, 0, sizeof mdigs); 28 | memset(mdigs, 0, sizeof rdigs); 29 | memset(N, 0, sizeof N); 30 | memset(M, 0, sizeof M); 31 | memset(M, 0, sizeof R); 32 | memset(e, 0, sizeof e); 33 | int d = 0; 34 | ll n1 = n, m1 = m, r1 = n-m; 35 | while (n1) { 36 | ndigs[d] = n1 % p; mdigs[d] = m1 % p; rdigs[d] = r1 % p; 37 | n1 /= p; m1 /= p; r1 /= p; 38 | ++d; 39 | } 40 | for (int i = 0; i < d; i++) 41 | e[i] = (ndigs[i] < (mdigs[i] + ((i > 0) ? e[i-1] : 0))); 42 | for (int i = d - 2; i >= 0; i--) 43 | e[i] += e[i+1]; 44 | 45 | if (e[0] >= q) return 0; 46 | ll pq = 1; 47 | for (int i = 0; i < q; ++i) 48 | pq *= p; 49 | q -= e[0]; 50 | 51 | n1 = n; m1 = m; r1 = n-m; 52 | ll pq1 = 1; 53 | for (int i = 0; i < q; ++i) pq1 *= p; 54 | d = 0; 55 | while (n1) { 56 | N[d] = n1 % pq1; M[d] = m1 % pq1; R[d] = r1 % pq1; 57 | n1 /= p; m1 /= p; r1 /= p; 58 | ++d; 59 | } 60 | 61 | ll res = ((p > 2 || q < 3) && q < d && e[q-1] % 2) ? -1 : 1; 62 | for (int i = 0; i < e[0]; i++) 63 | res = (res * p) % pq; 64 | for (int i = 0; i < d; i++) { 65 | ll x = partial_fac_mod_pq(N[i], p, q) % pq; 66 | x = (x * modinv(partial_fac_mod_pq(M[i], p, q), pq)) % pq; 67 | x = (x * modinv(partial_fac_mod_pq(R[i], p, q), pq)) % pq; 68 | res = (res * x) % pq; 69 | } 70 | while (res < 0) res += pq; 71 | return res; 72 | } 73 | 74 | // calculates (product_{i=1,i%p!=0}^n i) % p^e 75 | // cnt is the exponent of p in n! 76 | // Time: p^e + log(p, n) 77 | int get_part_of_fac_n_mod_pe(int n, int p, int mod, int *upto, int &cnt) { 78 | if (n < p) { 79 | cnt = 0; 80 | return upto[n]; 81 | } else { 82 | int res = powmod(upto[mod], n / mod, mod); 83 | res = (ll) res * upto[n % mod] % mod; 84 | res = (ll) res * get_part_of_fac_n_mod_pe(n / p, p, mod, upto, cnt) 85 | % mod; 86 | cnt += n / p; 87 | return res; 88 | } 89 | } 90 | 91 | // C(n,k) % p^e where mod == p^e. Sometimes Granville is faster, sometimes 92 | // this one 93 | int binomod2(int n, int k, int p, int mod) { 94 | static int upto[maxm + 1]; 95 | upto[0] = 1 % mod; 96 | for (int i = 1; i <= mod; ++i) 97 | upto[i] = i % p ? (ll) upto[i - 1] * i % mod : upto[i - 1]; 98 | int cnt1, cnt2, cnt3; 99 | int a = get_part_of_fac_n_mod_pe(n, p, mod, upto, cnt1); 100 | int b = get_part_of_fac_n_mod_pe(k, p, mod, upto, cnt2); 101 | int c = get_part_of_fac_n_mod_pe(n - k, p, mod, upto, cnt3); 102 | int res = (ll) a * modinv(b, mod) % mod * modinv(c, mod) % mod 103 | * powmod(p, cnt1 - cnt2 - cnt3, mod) % mod; 104 | return res; 105 | } 106 | 107 | const int crt_maxlen = 500; 108 | int binomod_gen(int n, int k, int m) { 109 | static ll partp[crt_maxlen], partq[crt_maxlen], partmod[crt_maxlen]; 110 | int partn = 0, tm = m; 111 | for (int i = 2; i * i <= tm; ++i) 112 | if (tm % i == 0) { 113 | partq[partn] = 0; 114 | partp[partn] = i; 115 | partmod[partn] = 1; 116 | while (tm % i == 0) { 117 | tm /= i; 118 | partq[partn] += 1; 119 | partmod[partn] *= i; 120 | } 121 | ++partn; 122 | } 123 | if (tm > 1) { 124 | partq[partn] = 1; 125 | partp[partn] = tm; 126 | partmod[partn] = tm; 127 | ++partn; 128 | } 129 | 130 | ll coef[partn], res[partn]; 131 | for (int i = 0; i < partn; ++i) { 132 | coef[i] = 1; 133 | // choose whichever is faster ;) 134 | res[i] = binomod2(n, k, partp[i], partmod[i]); 135 | //res[i] = binomod(n, k, partp[i], partq[i]); 136 | } 137 | ll sol, mod; 138 | crt(partn, coef, res, partmod, sol, mod); 139 | return sol; 140 | } 141 | -------------------------------------------------------------------------------- /binsearch.cpp: -------------------------------------------------------------------------------- 1 | // return first i in [l,r-1] with pred(i) 2 | // or r otherwise 3 | template 4 | T first(T l, T r, F pred) { 5 | T lo = l, hi = r; 6 | while (lo < hi) { 7 | T mid = (lo + hi) >> 1; 8 | if (pred(mid)) hi = mid; 9 | else lo = mid + 1; 10 | } 11 | return lo; 12 | } 13 | -------------------------------------------------------------------------------- /convex_hull/descasc.cpp: -------------------------------------------------------------------------------- 1 | // convex hull, minimum 2 | vector M, B; 3 | int ptr; 4 | bool bad(int a,int b,int c) { 5 | // use deterministic comuputation with long long if sufficient 6 | return (long double)(B[c]-B[a])*(M[a]-M[b])<(long double)(B[b]-B[a])*(M[a]-M[c]); 7 | } 8 | // insert with non-increasing m 9 | void insert(ll m, ll b) { 10 | M.push_back(m); 11 | B.push_back(b); 12 | while (M.size() >= 3 && bad(M.size()-3, M.size()-2, M.size()-1)) { 13 | M.erase(M.end()-2); 14 | B.erase(B.end()-2); 15 | } 16 | } 17 | ll get(int i, ll x) { 18 | return M[i]*x + B[i]; 19 | } 20 | // query with non-decreasing x 21 | ll query(ll x) { 22 | ptr=min((int)M.size()-1,ptr); 23 | while (ptr succ; 5 | bool operator<(const Line& rhs) const { 6 | if (rhs.b != is_query) return m < rhs.m; 7 | const Line* s = succ(); 8 | if (!s) return 0; 9 | ll x = rhs.m; 10 | return b - s->b < (s->m - m) * x; 11 | } 12 | }; 13 | struct HullDynamic : public multiset { // will maintain upper hull for maximum 14 | bool bad(iterator y) { 15 | auto z = next(y); 16 | if (y == begin()) { 17 | if (z == end()) return 0; 18 | return y->m == z->m && y->b <= z->b; 19 | } 20 | auto x = prev(y); 21 | if (z == end()) return y->m == x->m && y->b <= x->b; 22 | return (x->b - y->b)*(z->m - y->m) >= (y->b - z->b)*(y->m - x->m); 23 | } 24 | void insert_line(ll m, ll b) { 25 | auto y = insert({ m, b }); 26 | y->succ = [=] { return next(y) == end() ? 0 : &*next(y); }; 27 | if (bad(y)) { erase(y); return; } 28 | while (next(y) != end() && bad(next(y))) erase(next(y)); 29 | while (y != begin() && bad(prev(y))) erase(prev(y)); 30 | } 31 | ll eval(ll x) { 32 | auto l = *lower_bound((Line) { x, is_query }); 33 | return l.m * x + l.b; 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /fast_io.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | // some damn fast I/O 7 | #define GETCHAR getchar_unlocked 8 | #define FWRITE fwrite_unlocked 9 | const int BUFSIZE = 1<<16; 10 | 11 | static char outbuf[BUFSIZE]; 12 | int outbuf_size = 0; 13 | 14 | void init_io() { 15 | ios_base::sync_with_stdio(false); 16 | } 17 | 18 | void flush() { 19 | FWRITE(outbuf, outbuf_size, 1, stdout); 20 | outbuf_size = 0; 21 | } 22 | 23 | template 24 | bool read_num(T &x) { 25 | register int c = GETCHAR(); 26 | x = 0; 27 | bool neg = false; 28 | while (!isdigit(c) && c != '-' && c != EOF) 29 | c = GETCHAR(); 30 | if (c == EOF) return false; 31 | if (c == '-') { neg = true; c = GETCHAR(); } 32 | while (isdigit(c)) { 33 | x = x * 10 + c - '0'; 34 | c = GETCHAR(); 35 | } 36 | if (neg) x = -x; 37 | return true; 38 | } 39 | 40 | void write_char(char c) { 41 | if (outbuf_size == BUFSIZE) 42 | flush(); 43 | outbuf[outbuf_size++] = c; 44 | } 45 | 46 | void write_str(const char *c) { 47 | while (*c) write_char(*(c++)); 48 | } 49 | 50 | // because we only flush when trying to write, we always have 51 | // at least one byte in the buffer after every write operation 52 | bool unwrite() { 53 | if (!outbuf_size) 54 | return false; 55 | outbuf_size--; 56 | return true; 57 | } 58 | 59 | template 60 | void write_num(T x) { 61 | if (x < 0) { write_char('-'); x = -x; } 62 | static int digs[25]; 63 | register int i = 0; 64 | while (x) { 65 | digs[i++] = x % 10; x /= 10; 66 | } 67 | if (i) { 68 | while (i) { 69 | write_char(digs[i-1] + '0'); --i; 70 | } 71 | } else write_char('0'); 72 | } 73 | -------------------------------------------------------------------------------- /fenwick_tree.cpp: -------------------------------------------------------------------------------- 1 | const int n = 10000; // ALL INDICES START AT 1 WITH THIS CODE!! 2 | 3 | // mode 1: update indices, read prefixes 4 | void update_idx(int tree[], int i, int val) { // v[i] += val 5 | for (; i <= n; i += i & -i) tree[i] += val; 6 | } 7 | int read_prefix(int tree[], int i) { // get sum v[1..i] 8 | int sum = 0; 9 | for (; i > 0; i -= i & -i) sum += tree[i]; 10 | return sum; 11 | } 12 | int kth(int k) { // find kth element in tree (1-based index) 13 | int ans = 0; 14 | for (int i = maxl; i >= 0; --i) // maxl = largest i s.t. (1< 0; i -= i & -i) tree[i] += val; 25 | } 26 | int read_idx(int tree[], int i) { // get v[i] 27 | int sum = 0; 28 | for (; i <= n; i += i & -i) sum += tree[i]; 29 | return sum; 30 | } 31 | 32 | // mode 3: range-update range-query (using point-wise of linear functions) 33 | const int maxn = 100100; 34 | int n; 35 | ll mul[maxn], add[maxn]; 36 | 37 | void update_idx(ll tree[], int x, ll val) { 38 | for (int i = x; i <= n; i += i & -i) tree[i] += val; 39 | } 40 | void update_prefix(int x, ll val) { // v[x] += val 41 | update_idx(mul, 1, val); 42 | update_idx(mul, x + 1, -val); 43 | update_idx(add, x + 1, x * val); 44 | } 45 | ll read_prefix(int x) { // get sum v[1..x] 46 | ll a = 0, b = 0; 47 | for (int i = x; i > 0; i -= i & -i) a += mul[i], b += add[i]; 48 | return a * x + b; 49 | } 50 | void update_range(int l, int r, ll val) { // v[l..r] += val 51 | update_prefix(l - 1, -val); 52 | update_prefix(r, val); 53 | } 54 | ll read_range(int l, int r) { // get sum v[l..r] 55 | return read_prefix(r) - read_prefix(l - 1); 56 | } 57 | -------------------------------------------------------------------------------- /gauss.cpp: -------------------------------------------------------------------------------- 1 | int n, m, piv; // rows, columns 2 | long double M[222][222], eps=1e-3; 3 | bool used[222]; 4 | //... 5 | int rank = 0; 6 | for(int col = 0; col < m; ++col) { 7 | for (piv = 0; piv < n; ++piv) if (!used[piv] && abs(M[piv][col]) > eps) break; 8 | if (piv == n) continue; 9 | rank++; 10 | used[piv] = 1; 11 | for (int i = 0; i < n; ++i) if (i != piv) { 12 | long double t = M[i][col] / M[piv][col]; 13 | for (int j = 0; j < m; ++j) M[i][j] -= t * M[piv][j]; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /geometry.cpp: -------------------------------------------------------------------------------- 1 | using D=long double; 2 | using P=complex; 3 | using L=vector

; 4 | using G=vector

; 5 | const D eps=1e-12, inf=1e15, pi=acos(-1), e=exp(1.); 6 | 7 | D sq(D x) { return x*x; } 8 | D rem(D x, D y) { return fmod(fmod(x,y)+y,y); } 9 | D rtod(D rad) { return rad*180/pi; } 10 | D dtor(D deg) { return deg*pi/180; } 11 | int sgn(D x) { return (x > eps) - (x < -eps); } 12 | // when doing printf("%.Xf", x), fix '-0' output to '0'. 13 | D fixzero(D x, int d) { return (x>0 || x<=-5/pow(10,d+1)) ? x:0; } 14 | 15 | namespace std { 16 | bool operator<(const P& a, const P& b) { 17 | return mk(real(a), imag(a)) < mk(real(b), imag(b)); 18 | } 19 | } 20 | 21 | D cross(P a, P b) { return imag(conj(a) * b); } 22 | D cross(P a, P b, P c) { return cross(b-a, c-a); } 23 | D dot(P a, P b) { return real(conj(a) * b); } 24 | P scale(P a, D len) { return a * (len/abs(a)); } 25 | P rotate(P p, D ang) { return p * polar(D(1), ang); } 26 | D angle(P a, P b) { return arg(b) - arg(a); } 27 | D angle_unsigned(P a, P b) { return min(rem(arg(a)-arg(b),2*pi), rem(arg(b)-arg(a),2*pi)); } 28 | 29 | int ccw(P a, P b, P c) { 30 | b -= a; c -= a; 31 | if (cross(b, c) > eps) return +1; // counter clockwise 32 | if (cross(b, c) < -eps) return -1; // clockwise 33 | if (dot(b, c) < 0) return +2; // c--a--b on line 34 | if (norm(b) < norm(c)) return -2; // a--b--c on line 35 | return 0; 36 | } 37 | 38 | G dummy; 39 | L line(P a, P b) { 40 | L res; res.pb(a); res.pb(b); return res; 41 | } 42 | P dir(const L& l) { return l[1]-l[0]; } 43 | 44 | D project(P e, P x) { return dot(e,x) / norm(e); } 45 | P pedal(const L& l, P p) { return l[1] + dir(l) * project(dir(l), p-l[1]); } 46 | P reflect(P e, P x) { return P(2)*e*project(e, x) - x; } // reflect vector x along normal e 47 | P reflect(const L& l, P p) { return l[0] + reflect(dir(l), p-l[0]); } 48 | int intersectLL(const L &l, const L &m) { 49 | if (abs(cross(l[1]-l[0], m[1]-m[0])) > eps) return 1; // non-parallel 50 | if (abs(cross(l[1]-l[0], m[0]-l[0])) < eps) return -1; // same line 51 | return 0; 52 | } 53 | bool intersectLS(const L& l, const L& s) { 54 | return cross(dir(l), s[0]-l[0])* // s[0] is left of l 55 | cross(dir(l), s[1]-l[0]) < eps; // s[1] is right of l 56 | } 57 | bool intersectLP(const L& l, const P& p) { 58 | return abs(cross(l[1]-p, l[0]-p)) < eps; 59 | } 60 | bool intersectSS(const L& s, const L& t) { 61 | return sgn(ccw(s[0],s[1],t[0]) * ccw(s[0],s[1],t[1])) <= 0 && 62 | sgn(ccw(t[0],t[1],s[0]) * ccw(t[0],t[1],s[1])) <= 0; 63 | } 64 | bool intersectSP(const L& s, const P& p) { 65 | return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < eps; // triangle inequality 66 | } 67 | D distanceLP(const L& l, P p) { 68 | return abs(p - pedal(l, p)); 69 | } 70 | D distanceLL(const L& l, const L& m) { 71 | return intersectLL(l, m) ? 0 : distanceLP(l, m[0]); 72 | } 73 | D distanceLS(const L& l, const L& s) { 74 | if (intersectLS(l, s)) return 0; 75 | return min(distanceLP(l, s[0]), distanceLP(l, s[1])); 76 | } 77 | D distanceSP(const L& s, P p) { 78 | P r = pedal(s, p); 79 | if (intersectSP(s, r)) return abs(r - p); 80 | return min(abs(s[0] - p), abs(s[1] - p)); 81 | } 82 | D distanceSS(const L& s, const L& t) { 83 | if (intersectSS(s, t)) return 0; 84 | return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])), 85 | min(distanceSP(t, s[0]), distanceSP(t, s[1]))); 86 | } 87 | P crosspoint(const L& l, const L& m) { // return intersection point 88 | D A = cross(dir(l), dir(m)); 89 | D B = cross(dir(l), l[1] - m[0]); 90 | return m[0] + B / A * dir(m); 91 | } 92 | L bisector(P a, P b) { 93 | P A = (a+b)*P(0.5,0); 94 | return line(A, A+(b-a)*P(0,1)); 95 | } 96 | 97 | #define next(g,i) g[(i+1)%g.size()] 98 | #define prev(g,i) g[(i+g.size()-1)%g.size()] 99 | L edge(const G& g, int i) { return line(g[i], next(g,i)); } 100 | D area(const G& g) { 101 | D A = 0; 102 | rep(i,0,g.size()) 103 | A += cross(g[i], next(g,i)); 104 | return abs(A/2); 105 | } 106 | 107 | // intersect with half-plane left of l[0] -> l[1] 108 | G convex_cut(const G& g, const L& l) { 109 | G Q; 110 | rep(i,0,g.size()) { 111 | P A = g[i], B = next(g,i); 112 | if (ccw(l[0], l[1], A) != -1) Q.pb(A); 113 | if (ccw(l[0], l[1], A)*ccw(l[0], l[1], B) < 0) 114 | Q.pb(crosspoint(line(A, B), l)); 115 | } 116 | return Q; 117 | } 118 | bool convex_contain(const G& g, P p) { // check if point is inside convex polygon 119 | rep(i,0,g.size()) 120 | if (ccw(g[i], next(g, i), p) == -1) return 0; 121 | return 1; 122 | } 123 | G convex_intersect(G a, G b) { // intersect two convex polygons 124 | rep(i,0,b.size()) 125 | a = convex_cut(a, edge(b, i)); 126 | return a; 127 | } 128 | void triangulate(G g, vector& res) { // triangulate a simple polygon 129 | while (g.size() > 3) { 130 | bool found = 0; 131 | rep(i,0,g.size()) { 132 | if (ccw(prev(g,i), g[i], next(g,i)) != +1) continue; 133 | G tri; 134 | tri.pb(prev(g,i)); 135 | tri.pb(g[i]); 136 | tri.pb(next(g,i)); 137 | bool valid = 1; 138 | rep(j,0,g.size()) { 139 | if ((j+1)%g.size() == i || j == i || j == (i+1)%g.size()) continue; 140 | if (convex_contain(tri, g[j])) { 141 | valid = 0; 142 | break; 143 | } 144 | } 145 | if (!valid) continue; 146 | res.pb(tri); 147 | g.erase(g.begin() + i); 148 | found = 1; break; 149 | } 150 | assert(found); 151 | } 152 | res.pb(g); 153 | } 154 | void graham_step(G& a, G& st, int i, int bot) { 155 | while (st.size()>bot && sgn(cross(*(st.end()-2), st.back(), a[i]))<=0) 156 | st.pop_back(); 157 | st.pb(a[i]); 158 | } 159 | bool cmpY(P a, P b) { return mk(imag(a),real(a)) < mk(imag(b),real(b)); } 160 | G graham_scan(const G& points) { // will return points in ccw order 161 | // special case: all points coincide, algo might return point twice 162 | G a = points; sort(all(a),cmpY); 163 | int n = a.size(); 164 | if (n<=1) return a; 165 | G st; st.pb(a[0]); st.pb(a[1]); 166 | for (int i = 2; i < n; i++) graham_step(a,st,i,1); 167 | int mid = st.size(); 168 | for (int i = n - 2; i >= 0; i--) graham_step(a,st,i,mid); 169 | while (st.size() > 1 && !sgn(abs(st.back() - st.front()))) st.pop_back(); 170 | return st; 171 | } 172 | G gift_wrap(const G& points) { // will return points in clockwise order 173 | // special case: duplicate points, not sure what happens then 174 | int n = points.size(); 175 | if (n<=2) return points; 176 | G res; 177 | P nxt, p = *min_element(all(points), [](const P& a, const P& b){ 178 | return real(a) < real(b); 179 | }); 180 | do { 181 | res.pb(p); 182 | nxt = points[0]; 183 | for (auto& q: points) 184 | if (abs(p - q) > eps && (abs(p - nxt) < eps || ccw(p, nxt, q) == 1)) 185 | nxt = q; 186 | p = nxt; 187 | } while (nxt != *begin(res)); 188 | return res; 189 | } 190 | G voronoi_cell(G g, const vector

&v, int s) { 191 | rep(i,0,v.size()) 192 | if (i!=s) 193 | g = convex_cut(g, bisector(v[s], v[i])); 194 | return g; 195 | } 196 | const int ray_iters = 20; 197 | bool simple_contain(const G& g, P p) { // check if point is inside simple polygon 198 | int yes = 0; 199 | rep(_,0,ray_iters) { 200 | D angle = 2*pi * (D)rand() / RAND_MAX; 201 | P dir = rotate(P(inf,inf), angle); 202 | L s = line(p, p + dir); 203 | int cnt = 0; 204 | rep(i,0,g.size()) { 205 | if (intersectSS(edge(g, i), s)) cnt++; 206 | } 207 | yes += cnt%2; 208 | } 209 | return yes > ray_iters/2; 210 | } 211 | bool intersectGG(const G& g1, const G& g2) { 212 | if (convex_contain(g1, g2[0])) return 1; 213 | if (convex_contain(g2, g1[0])) return 1; 214 | rep(i,0,g1.size()) rep(j,0,g2.size()) { 215 | if (intersectSS(edge(g1, i), edge(g2, j))) return 1; 216 | } 217 | return 0; 218 | } 219 | D distanceGP(const G& g, P p) { 220 | if (convex_contain(g, p)) return 0; 221 | D res = inf; 222 | rep(i,0,g.size()) 223 | res = min(res, distanceSP(edge(g, i), p)); 224 | return res; 225 | } 226 | P centroid(const G& v) { // v must have no self-intersections 227 | D S = 0; 228 | P res; 229 | rep(i,0,v.size()) { 230 | D tmp = cross(v[i], next(v,i)); 231 | S += tmp; 232 | res += (v[i] + next(v,i)) * tmp; 233 | } 234 | S /= 2; 235 | res /= 6*S; 236 | return res; 237 | } 238 | 239 | struct C { 240 | P p; D r; 241 | C(P p, D r) : p(p),r(r) {} 242 | C(){} 243 | }; 244 | // intersect circle with line through (c.p + v * dst/abs(v)) "orthogonal" to the circle 245 | // dst can be negative 246 | G intersectCL2(const C& c, D dst, P v) { 247 | G res; 248 | P mid = c.p + v * (dst/abs(v)); 249 | if (sgn(abs(dst)-c.r) == 0) { res.pb(mid); return res; } 250 | D h = sqrt(sq(c.r) - sq(dst)); 251 | P hi = scale(v * P(0,1), h); 252 | res.pb(mid + hi); res.pb(mid - hi); 253 | return res; 254 | } 255 | G intersectCL(const C& c, const L& l) { 256 | if (intersectLP(l, c.p)) { 257 | P h = scale(dir(l), c.r); 258 | G res; res.pb(c.p + h); res.pb(c.p - h); return res; 259 | } 260 | P v = pedal(l, c.p) - c.p; 261 | return intersectCL2(c, abs(v), v); 262 | } 263 | G intersectCS(const C& c, const L& s) { 264 | G res1 = intersectCL(c,s), res2; 265 | for(auto it: res1) if (intersectSP(s, it)) res2.pb(it); 266 | return res2; 267 | } 268 | int intersectCC(const C& a, const C& b, G& res=dummy) { 269 | D sum = a.r + b.r, diff = abs(a.r - b.r), dst = abs(a.p - b.p); 270 | if (dst > sum + eps || dst < diff - eps) return 0; 271 | if (max(dst, diff) < eps) { // same circle 272 | if (a.r < eps) { res.pb(a.p); return 1; } // degenerate 273 | return -1; // infinitely many 274 | } 275 | D p = (sq(a.r) - sq(b.r) + sq(dst))/(2*dst); 276 | P ab = b.p - a.p; 277 | res = intersectCL2(a, p, ab); 278 | return res.size(); 279 | } 280 | 281 | using P3 = valarray; 282 | P3 p3(D x=0, D y=0, D z=0) { 283 | P3 res(3); 284 | res[0]=x;res[1]=y;res[2]=z; 285 | return res; 286 | } 287 | ostream& operator<<(ostream& out, const P3& x) { 288 | return out << "(" << x[0]<<","< struct Matrix { 307 | T data[N][N]; 308 | Matrix(T d=0) { rep(i,0,N) rep(j,0,N) data[i][j] = i==j?d:0; } 309 | Matrix operator+(const Matrix& other) const { 310 | Matrix res; rep(i,0,N) rep(j,0,N) res[i][j] = data[i][j] + other[i][j]; return res; 311 | } 312 | Matrix operator*(const Matrix& other) const { 313 | Matrix res; rep(i,0,N) rep(k,0,N) rep(j,0,N) res[i][j] += data[i][k] * other[k][j]; return res; 314 | } 315 | Matrix transpose() const { 316 | Matrix res; rep(i,0,N) rep(j,0,N) res[i][j] = data[j][i]; return res; 317 | } 318 | array operator*(const array& v) const { 319 | array res; 320 | rep(i,0,N) rep(j,0,N) res[i] += data[i][j] * v[j]; 321 | return res; 322 | } 323 | const T* operator[](int i) const { return data[i]; } 324 | T* operator[](int i) { return data[i]; } 325 | }; 326 | template ostream& operator<<(ostream& out, Matrix mat) { 327 | rep(i,0,N) { rep(j,0,N) out << mat[i][j] << " "; cout << endl; } return out; 328 | } // creates a rotation matrix around axis x (must be normalized). Rotation is 329 | // counter-clockwise if you look in the inverse direction of x onto the origin 330 | template void create_rot_matrix(M& m, double x[3], double a) { 331 | rep(i,0,3) rep(j,0,3) { 332 | m[i][j] = x[i]*x[j]*(1-cos(a)); 333 | if (i == j) m[i][j] += cos(a); 334 | else m[i][j] += x[(6-i-j)%3] * ((i == (2+j) % 3) ? -1 : 1) * sin(a); 335 | } 336 | } 337 | -------------------------------------------------------------------------------- /kmp.cpp: -------------------------------------------------------------------------------- 1 | // f[i] = maximum length of suffix of s[1..i] that is prefix of s 2 | void kmp(const char *s, int *f, int n) { 3 | int t = -1; 4 | for (int i = 0; i < n; ++i) { 5 | while (t >= 0 && s[t] != s[i]) t = t>=1 ? f[t-1] : -1; 6 | f[i] = ++t; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /lca.cpp: -------------------------------------------------------------------------------- 1 | const int N = 100100; 2 | const int H = 17; // height <= 2**H 3 | int par[N][H+1], lvl[N]; 4 | 5 | void dfs(int x, int from) { // from == x for root 6 | lvl[x] = from==x ? 0 : lvl[from] + 1; 7 | par[x][0] = from; 8 | for (int i = 1; i <= H; ++i) 9 | par[x][i] = par[par[x][i-1]][i-1]; 10 | } 11 | 12 | // n log n space with "sparse table" 13 | int lca(int x, int y) { 14 | if (lvl[x] < lvl[y]) 15 | swap(x, y); 16 | for (int i = H; i >= 0; i--) 17 | if (lvl[x] - (1<= lvl[y]) 18 | x = par[x][i]; 19 | assert(lvl[x] == lvl[y]); 20 | if (x == y) return x; 21 | for (int i = H; i >= 0; i--) 22 | if (par[x][i] != par[y][i]) 23 | x = par[x][i], y = par[y][i]; 24 | assert(par[x][0] == par[y][0]); 25 | return par[x][0]; 26 | } 27 | -------------------------------------------------------------------------------- /math_stuff.cpp: -------------------------------------------------------------------------------- 1 | typedef long long LL; 2 | 3 | // compute nth fibonacci number modulo m in O(log n) 4 | LL fib(LL n, LL m) { 5 | if (!n) return 0; 6 | LL a=1,b=0,c=0,d=1; 7 | LL a1=1,b1=1,c1=1,d1=0; 8 | LL a2,b2,c2,d2; 9 | n -= 1; 10 | while (n) { 11 | if (n & 1) { 12 | a2=(a*a1%m + b*c1%m)%m; 13 | b2=(a*b1%m + b*d1%m)%m; 14 | c2=(c*a1%m + d*c1%m)%m; 15 | d2=(c*b1%m + d*d1%m)%m; 16 | a=a2;b=b2;c=c2;d=d2; 17 | } 18 | n >>= 1; 19 | a2=(a1*a1%m + b1*c1%m)%m; 20 | b2=(a1*b1%m + b1*d1%m)%m; 21 | c2=(c1*a1%m + d1*c1%m)%m; 22 | d2=(c1*b1%m + d1*d1%m)%m; 23 | a1=a2;b1=b2;c1=c2;d1=d2; 24 | } 25 | return a; 26 | } 27 | 28 | ll p; 29 | ll powmod(ll x, ll e) { 30 | if (e == 0) return 1; 31 | if (e & 1) return x * powmod(x, e - 1) % p; 32 | ll y = powmod(x, e / 2); 33 | return y * y % p; 34 | } 35 | 36 | // factors_p1 = prime factors of (p - 1) 37 | bool is_primitive(ll g) { 38 | for (auto q : factors_p1) { 39 | if (1 == powmod(g, (p-1)/q)) return 0; 40 | } 41 | return 1; 42 | } 43 | ll g; // g = primitive root of p 44 | void find_prim() { 45 | for (;;) { 46 | g = (((ll)rand() << 15) | (ll)rand()) % p; 47 | if (g < 2) continue; 48 | if (is_primitive(g)) return; 49 | } 50 | } 51 | bool have_powers = 0; 52 | unordered_map powers; 53 | ll dlog(ll b) { // find x such that g^x = b (mod p) 54 | ll m = (ll)(ceil(sqrt(p-1))+0.5); // better use binary search here... 55 | if (!have_powers) rep(j,0,m) powers[powmod(g, j)] = j; 56 | have_powers = 1; 57 | ll gm = powmod(g, -m + 2*(p-1)); 58 | rep(i,0,m) { 59 | if (contains(powers, b)) return i*m + powers[b]; 60 | b = b * gm % p; 61 | } 62 | assert(0); 63 | return -1; 64 | } 65 | -------------------------------------------------------------------------------- /max_matching.cpp: -------------------------------------------------------------------------------- 1 | const int N=200, MOD=1000000007, I=10; 2 | int n, adj[N][N], a[N][N]; 3 | int rank() { 4 | int r = 0; 5 | rep(j,0,n) { 6 | int k = r; 7 | while (k < n && !a[k][j]) ++k; 8 | if (k == n) continue; 9 | swap(a[r], a[k]); 10 | int inv = powmod(a[r][j], MOD - 2); 11 | rep(i,j,n) 12 | a[r][i] = 1LL * a[r][i] * inv % MOD; 13 | rep(u,r+1,n) rep(v,j,n) 14 | a[u][v] = (a[u][v] - 1LL * a[r][v] * a[u][j] % MOD + MOD) % MOD; 15 | ++r; 16 | } 17 | return r; 18 | } 19 | // failure probability = (n / MOD)^I 20 | int max_matching() { 21 | int ans = 0; 22 | rep(_,0,I) { 23 | rep(i,0,n) rep(j,0,i) 24 | if (adj[i][j]) { 25 | a[i][j] = rand() % (MOD - 1) + 1; 26 | a[j][i] = MOD - a[i][j]; 27 | } 28 | ans = max(ans, rank()/2); 29 | } 30 | return ans; 31 | } 32 | -------------------------------------------------------------------------------- /min_cost_max_flow/solution.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | using namespace std; 20 | using namespace std::tr1; 21 | 22 | typedef long long llong; 23 | typedef pair int2; 24 | typedef pair llong2; 25 | #define foreach(v,c) for (typeof((c).begin()) v = (c).begin(); v != (c).end(); ++v) 26 | #define rep(i,n) for (int i = 0; i < (n); ++i) 27 | 28 | struct MinCostFlow { 29 | static const int maxn = 300; 30 | static const int maxm = 4000; 31 | typedef int Captype; 32 | typedef int Valtype; 33 | static const Captype flowlimit = 100000; 34 | struct edge { 35 | int node, next; Captype flow; Valtype value; 36 | } edges[maxm<<1]; 37 | int graph[maxn], queue[maxn], pre[maxn], con[maxn], n, m, source, target, top; 38 | bool inq[maxn]; 39 | Captype maxflow; 40 | Valtype mincost, dis[maxn]; 41 | MinCostFlow() { memset(graph, -1, sizeof(graph)); top=0;} 42 | inline int inverse(int x) { return 1 + ((x>>1)<<2)-x; } 43 | inline void addedge(int u, int v, Captype c, Valtype w) { 44 | if (c == 0) return; 45 | //cout << u << " -> " << v << ": " << c << "/" << w << endl; 46 | edges[top].value = w; edges[top].flow = c; edges[top].node = v; 47 | edges[top].next = graph[u]; graph[u] = top++; 48 | edges[top].value = -w; edges[top].flow = 0; edges[top].node = u; 49 | edges[top].next = graph[v]; graph[v] = top++; 50 | } 51 | bool SPFA() { 52 | int point, nod, now, head = 0, tail = 1; 53 | memset(pre, -1, sizeof pre); 54 | memset(inq, 0, sizeof inq); 55 | memset(dis, 0x7f, sizeof dis); 56 | dis[source] = 0; queue[0] = source; pre[source] = source; inq[source] = true; 57 | while (head != tail) { 58 | now = queue[head++]; point = graph[now]; inq[now] = false; head %= maxn; 59 | while (point != -1) { 60 | nod = edges[point].node; 61 | if (edges[point].flow > 0 && dis[nod]>dis[now]+edges[point].value) { 62 | dis[nod] = dis[now] + edges[point].value; 63 | pre[nod] = now; 64 | con[nod] = point; 65 | if (!inq[nod]) { 66 | inq[nod] = true; 67 | queue[tail++] = nod; 68 | tail %= maxn; 69 | } 70 | } 71 | point = edges[point].next; 72 | } 73 | } 74 | return pre[target]!=-1; 75 | } 76 | void extend() { 77 | Captype w = flowlimit; 78 | for (int u = target; pre[u] != u; u = pre[u]) 79 | w = min(w, edges[con[u]].flow); 80 | maxflow += w; 81 | mincost += dis[target]*w; 82 | for (int u = target; pre[u] != u; u = pre[u]) { 83 | edges[con[u]].flow -= w; 84 | edges[inverse(con[u])].flow += w; 85 | } 86 | } 87 | void mincostflow() { 88 | maxflow = 0; mincost = 0; 89 | while (SPFA()) extend(); 90 | } 91 | }; 92 | 93 | void count_chars(string& x, int tc[26]) { 94 | memset(tc, 0, 26 * (sizeof *tc)); 95 | foreach(c, x) tc[(int)(*c - 'a')]++; 96 | } 97 | 98 | int tc[26]; 99 | int main() { 100 | ios_base::sync_with_stdio(false); 101 | MinCostFlow* f = new MinCostFlow(); 102 | string t; cin >> t; 103 | count_chars(t, tc); 104 | 105 | f->source = 50; 106 | f->target = 51; 107 | for (int i = 0; i < 26; ++i) 108 | f->addedge(i, f->target, tc[i], 0); 109 | 110 | int n; cin >> n; 111 | for (int i = 0; i < n; ++i) { 112 | int a; 113 | string s; cin >> s >> a; 114 | count_chars(s, tc); 115 | f->addedge(f->source, 100 + i, a, i+1); 116 | for (int c = 0; c < 26; ++c) 117 | f->addedge(100 + i, c, tc[c], 0); 118 | } 119 | f->mincostflow(); 120 | if (f->maxflow == t.size()) 121 | cout << f->mincost << endl; 122 | else 123 | cout << -1 << endl; 124 | } 125 | -------------------------------------------------------------------------------- /mincostflow.cpp: -------------------------------------------------------------------------------- 1 | const int MAXN = 10000, MAXC = 1<<29; 2 | struct edge { int dest, cap, cost, rev; }; 3 | vector adj[MAXN]; 4 | int dis[MAXN], cap[MAXN], source, target, iter, cost; 5 | edge* pre[MAXN]; 6 | 7 | void addedge(int x, int y, int cap, int cost) { 8 | adj[x].push_back(edge {y, cap, cost, (int)adj[y].size()}); 9 | adj[y].push_back(edge {x, 0, -cost, (int)adj[x].size() - 1}); 10 | } 11 | 12 | bool spfa() { // optimization: use dijkstra here and do Johnson reweighting before 13 | memset(dis, 0x3f, sizeof dis); 14 | queue q; 15 | pre[source] = pre[target] = 0; 16 | dis[source] = 0; 17 | cap[source] = MAXC; 18 | q.emplace(source); 19 | while (!q.empty()) { 20 | int x = q.front(), d = dis[x]; 21 | q.pop(); 22 | for (auto& e : adj[x]) { 23 | int y = e.dest, w = d + e.cost; 24 | if (!e.cap || dis[y] <= w) continue; 25 | dis[y] = w; 26 | pre[y] = &e; 27 | cap[y] = min(cap[x], e.cap); 28 | q.push(y); // optimization: only push if not in queue yet 29 | } 30 | } 31 | edge* e = pre[target]; 32 | if (!e) return 0; // to minimize (cost, -flow): return also if dis[target] > 0 33 | while (e) { 34 | edge& rev = adj[e->dest][e->rev]; 35 | e->cap -= cap[target]; 36 | rev.cap += cap[target]; 37 | cost += cap[target] * e->cost; 38 | e = pre[rev.dest]; 39 | } 40 | return 1; 41 | } 42 | 43 | pair mincostflow(int S, int T) { 44 | source = S, target = T, cost = 0; 45 | int flow = 0; 46 | while(spfa()) flow += cap[target]; 47 | return {flow, cost}; 48 | } 49 | -------------------------------------------------------------------------------- /monotonic_queue.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | template 5 | struct MinQueue { 6 | deque > q, mono; 7 | int cnt = 0; 8 | void enqueue(T x) { 9 | while (!mono.empty() && x <= mono.back().second) mono.pop_back(); 10 | mono.push_back(make_pair(cnt,x)); 11 | q.push_back(make_pair(cnt,x)); 12 | cnt++; 13 | } 14 | void dequeue() { 15 | if (mono.front().first == q.front().first) mono.pop_front(); 16 | q.pop_front(); 17 | } 18 | T front() { return q.front().second; } 19 | T min() { return mono.front().second; } 20 | }; 21 | -------------------------------------------------------------------------------- /mst/kruskal.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | typedef long long llong; 20 | typedef pair int2; 21 | #define foreach(v,c) for (typeof((c).begin()) v = (c).begin(); v != (c).end(); ++v) 22 | 23 | #define NMAX 10000 24 | static vector > edges; 25 | static int path[NMAX+1]; 26 | static int root_rank[NMAX+1]; 27 | 28 | void init_set(int x) { 29 | path[x] = x; 30 | root_rank[x] = 0; 31 | } 32 | 33 | int find_set(int x) { 34 | if (path[x] == x) return x; 35 | return (path[x] = find_set(path[x])); 36 | } 37 | 38 | void union_sets(int x, int y) { 39 | path[find_set(x)] = find_set(y); 40 | /* 41 | // rank heuristic 42 | int r1 = find_set(x); 43 | int r2 = find_set(y); 44 | if (root_rank[r1] < root_rank[r2]) { 45 | path[r1] = r2; 46 | } else { 47 | path[r2] = r1; 48 | if (root_rank[r1] == root_rank[r2]) 49 | root_rank[r1]++; 50 | } 51 | */ 52 | } 53 | 54 | llong kruskal() { 55 | for (int i = 1; i <= n; i++) 56 | init_set(i); 57 | sort(edges.begin(), edges.end()); 58 | llong res = 0; 59 | foreach(it, edges) { 60 | llong w = it->first; 61 | int a = it->second.first; 62 | int b = it->second.second; 63 | if (find_set(a) == find_set(b)) continue; 64 | res += w; 65 | union_sets(a, b); 66 | } 67 | return res; 68 | } 69 | 70 | int main() { 71 | ios_base::sync_with_stdio(false); 72 | int m; 73 | scanf("%d %d", &n, &m); 74 | int a, b, w; 75 | for (int i = 0; i < m; i++) { 76 | scanf("%d %d %d", &a, &b, &w); 77 | edges.push_back(make_pair(w, make_pair(a, b))); 78 | } 79 | cout << kruskal() << endl; 80 | } 81 | -------------------------------------------------------------------------------- /mst/prim.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | typedef long long llong; 20 | #define foreach(v,c) for (typeof((c).begin()) v = (c).begin(); v != (c).end(); ++v) 21 | 22 | #define NMAX 10000 23 | int n; 24 | 25 | static vector > adj[NMAX + 1]; 26 | static bool visited[NMAX + 1]; 27 | static int d[NMAX + 1]; 28 | 29 | llong prim(int start) { 30 | fill(d, d + n + 1, INT_MAX); 31 | 32 | priority_queue > q; 33 | d[start] = 0; 34 | q.push(make_pair(0, start)); 35 | llong res = 0; 36 | 37 | while (!q.empty()) { 38 | int dist = -q.top().first; 39 | int a = q.top().second; 40 | q.pop(); 41 | if (dist > d[a]) continue; 42 | res += dist; 43 | visited[a] = true; 44 | 45 | foreach(it, adj[a]) { 46 | int b = it->first; 47 | llong w = it->second; 48 | if (!visited[b] && w < d[b]) { 49 | d[b] = w; 50 | q.push(make_pair(-w, b)); 51 | } 52 | } 53 | } 54 | 55 | return res; 56 | } 57 | 58 | int main() { 59 | ios_base::sync_with_stdio(false); 60 | int m; 61 | scanf("%d %d", &n, &m); 62 | int a, b, w; 63 | for (int i = 0; i < m; i++) { 64 | scanf("%d %d %d", &a, &b, &w); 65 | adj[a].push_back(make_pair(b, w)); 66 | adj[b].push_back(make_pair(a, w)); 67 | } 68 | cout << prim(1) << endl; 69 | } 70 | -------------------------------------------------------------------------------- /number_theory.cpp: -------------------------------------------------------------------------------- 1 | ll multiply_mod(ll a, ll b, ll mod) { 2 | if (b == 0) return 0; 3 | if (b & 1) return ((ull)multiply_mod(a, b-1, mod) + a) % mod; 4 | return multiply_mod(((ull)a + a) % mod, b/2, mod); 5 | } 6 | 7 | ll powmod(ll a, ll n, ll mod) { 8 | if (n == 0) return 1 % mod; 9 | if (n & 1) return multiply_mod(powmod(a, n-1, mod), a, mod); 10 | return powmod(multiply_mod(a, a, mod), n/2, mod); 11 | } 12 | 13 | // simple modinv, returns 0 if inverse doesn't exist 14 | ll modinv(ll a, ll m) { 15 | return a < 2 ? a : ((1 - m * 1ll * modinv(m % a, a)) / a % m + m) % m; 16 | } 17 | ll modinv_prime(ll a, ll p) { return powmod(a, p-2, p); } 18 | 19 | tuple egcd(ll a, ll b) { 20 | if (!a) return make_tuple(b, 0, 1); 21 | ll g, y, x; 22 | tie(g, y, x) = egcd(b % a, a); 23 | return make_tuple(g, x - b/a * y, y); 24 | } 25 | 26 | // solve the linear equation a x == b (mod n) 27 | // returns the number of solutions up to congruence (can be 0) 28 | // sol: the minimal positive solution 29 | // dis: the distance between solutions 30 | ll linear_mod(ll a, ll b, ll n, ll &sol, ll &dis) { 31 | a = (a % n + n) % n, b = (b % n + n) % n; 32 | ll d, x, y; 33 | tie(d, x, y) = egcd(a, n); 34 | if (b % d) 35 | return 0; 36 | x = (x % n + n) % n; 37 | x = b / d * x % n; 38 | dis = n / d; 39 | sol = x % dis; 40 | return d; 41 | } 42 | 43 | bool rabin(ll n) { 44 | // bases chosen to work for all n < 2^64, see https://oeis.org/A014233 45 | set p { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 }; 46 | if (n <= 37) return p.count(n); 47 | ll s = 0, t = n - 1; 48 | while (~t & 1) 49 | t >>= 1, ++s; 50 | for (int x: p) { 51 | ll pt = powmod(x, t, n); 52 | if (pt == 1) continue; 53 | bool ok = 0; 54 | for (int j = 0; j < s && !ok; ++j) { 55 | if (pt == n - 1) ok = 1; 56 | pt = multiply_mod(pt, pt, n); 57 | } 58 | if (!ok) return 0; 59 | } 60 | return 1; 61 | } 62 | 63 | ll rho(ll n) { // will find a factor < n, but not necessarily prime 64 | if (~n & 1) return 2; 65 | ll c = rand() % n, x = rand() % n, y = x, d = 1; 66 | while (d == 1) { 67 | x = (multiply_mod(x, x, n) + c) % n; 68 | y = (multiply_mod(y, y, n) + c) % n; 69 | y = (multiply_mod(y, y, n) + c) % n; 70 | d = __gcd(abs(x - y), n); 71 | } 72 | return d == n ? rho(n) : d; 73 | } 74 | 75 | void factor(ll n, map &facts) { 76 | if (n == 1) return; 77 | if (rabin(n)) { 78 | facts[n]++; 79 | return; 80 | } 81 | ll f = rho(n); 82 | factor(n/f, facts); 83 | factor(f, facts); 84 | } 85 | 86 | // use inclusion-exclusion to get the number of integers <= n 87 | // that are not divisable by any of the given primes. 88 | // This essentially enumerates all the subsequences and adds or subtracts 89 | // their product, depending on the current parity value. 90 | ll count_coprime_rec(int primes[], int len, ll n, int i, ll prod, bool parity) { 91 | if (i >= len || prod * primes[i] > n) return 0; 92 | return (parity ? 1 : (-1)) * (n / (prod*primes[i])) 93 | + count_coprime_rec(primes, len, n, i + 1, prod, parity) 94 | + count_coprime_rec(primes, len, n, i + 1, prod * primes[i], !parity); 95 | } 96 | // use cnt(B) - cnt(A-1) to get matching integers in range [A..B] 97 | ll count_coprime(int primes[], int len, ll n) { 98 | if (n <= 1) return max(0LL, n); 99 | return n - count_coprime_rec(primes, len, n, 0, 1, true); 100 | } 101 | 102 | // find x. a[i] x = b[i] (mod m[i]) 0 <= i < n. m[i] need not be coprime 103 | bool crt(int n, ll *a, ll *b, ll *m, ll &sol, ll &mod) { 104 | ll A = 1, B = 0, ta, tm, tsol, tdis; 105 | for (int i = 0; i < n; ++i) { 106 | if (!linear_mod(a[i], b[i], m[i], tsol, tdis)) return 0; 107 | ta = tsol, tm = tdis; 108 | if (!linear_mod(A, ta - B, tm, tsol, tdis)) return 0; 109 | B = A * tsol + B; 110 | A = A * tdis; 111 | } 112 | sol = B, mod = A; 113 | return 1; 114 | } 115 | 116 | // get number of permutations {P_1, ..., P_n} of size n, 117 | // where no number is at its original position (that is, P_i != i for all i) 118 | // also called subfactorial !n 119 | ll get_derangement_mod_m(ll n, ll m) { 120 | vector res(m * 2); 121 | ll d = 1 % m, p = 1; 122 | res[0] = d; 123 | for (int i = 1; i <= min(n, 2 * m - 1); ++i) { 124 | p *= -1; 125 | d = (1LL * i * d + p + m) % m; 126 | res[i] = d; 127 | if (i == n) return d; 128 | } 129 | // it turns out that !n mod m == !(n mod 2m) mod m 130 | return res[n % (2 * m)]; 131 | } 132 | 133 | // compute totient function for integers <= n 134 | vector compute_phi(int n) { 135 | vector phi(n + 1, 0); 136 | for (int i = 1; i <= n; ++i) { 137 | phi[i] += i; 138 | for (int j = 2 * i; j <= n; j += i) { 139 | phi[j] -= phi[i]; 140 | } 141 | } 142 | return phi; 143 | } 144 | 145 | // checks if g is primitive root mod p. Generate random g's to find primitive root. 146 | bool is_primitive(ll g, ll p) { 147 | map facs; 148 | factor(p - 1, facs); 149 | for (auto& f : facs) 150 | if (1 == powmod(g, (p-1)/f.first, p)) 151 | return 0; 152 | return 1; 153 | } 154 | 155 | ll dlog(ll g, ll b, ll p) { // find x such that g^x = b (mod p) 156 | ll m = (ll)(ceil(sqrt(p-1))+0.5); // better use binary search here... 157 | unordered_map powers; // should compute this only once per g 158 | rep(j,0,m) powers[powmod(g, j, p)] = j; 159 | ll gm = powmod(g, -m + 2*(p-1), p); 160 | rep(i,0,m) { 161 | if (powers.count(b)) return i*m + powers[b]; 162 | b = b * gm % p; 163 | } 164 | assert(0); return -1; 165 | } 166 | 167 | // compute p(n,k), the number of possibilities to write n as a sum of 168 | // k non-zero integers 169 | ll count_partitions(int n, int k) { 170 | if (n==k) return 1; 171 | if (n p(n + 1); 173 | for (int i = 1; i <= n; ++i) p[i] = 1; 174 | for (int l = 2; l <= k; ++l) 175 | for (int m = l+1; m <= n-l+1; ++m) 176 | p[m] = p[m] + p[m-l]; 177 | return p[n-k+1]; 178 | } 179 | -------------------------------------------------------------------------------- /numerical_integration.cpp: -------------------------------------------------------------------------------- 1 | // adaptive Simpson's rule 2 | double f(double x) { return x*x; } 3 | const double eps=1e-12; 4 | 5 | double simps(double a, double b) { 6 | return (f(a) + 4*f((a+b)/2) + f(b))*(b-a)/6; 7 | } 8 | double integrate(double a, double b) { 9 | double m = (a+b)/2; 10 | double l = simps(a,m),r = simps(m,b),tot=simps(a,b); 11 | if (fabs(l+r-tot) < eps) return tot; 12 | return integrate(a,m) + integrate(m,b); 13 | } 14 | 15 | // 4x improvements by avoiding recomputation of function calls: 16 | double simps(double a, double b, double fa, double fm, double fb) { 17 | return (fa + 4*fm + fb)*(b-a)/6; 18 | } 19 | double integr(double a, double b, double fa, double fm, double fb) { 20 | double m = (a+b)/2; 21 | double fam = f((a+m)/2), fmb = f((m+b)/2); 22 | double l = simps(a,m,fa,fam,fm),r = simps(m,b,fm,fmb,fb),tot=simps(a,b,fa,fm,fb); 23 | if (fabs(l+r-tot) < eps) return tot; 24 | return integr(a,m,fa,fam,fm) + integr(m,b,fm,fmb,fb); 25 | } 26 | double integrate(double a, double b) { 27 | return integr(a,b,f(a),f((a+b)/2),f(b)); 28 | } 29 | -------------------------------------------------------------------------------- /optimization.cpp: -------------------------------------------------------------------------------- 1 | const double eps = 1e-10; 2 | 3 | // assume a unimodal or monotonous function 4 | template 5 | double ternary_search(T lt, F f, double l, double r) { 6 | double yl = f(l); 7 | double yr = f(r); 8 | double ym = f((l+r)/2); 9 | if (lt(ym, lt(yl, yr) ? yl : yr)) 10 | return lt(yl, yr) ? yr : yl; 11 | while( (r-l > eps && abs(r/l-1) > eps) 12 | || (abs(yl-yr) > eps && abs(yl/yr-1) > eps)) { 13 | double m1 = (2*l + r) / 3; 14 | double m2 = (l + 2*r) / 3; 15 | double ym1 = f(m1); 16 | double ym2 = f(m2); 17 | if (lt(ym1, ym2)) { 18 | l = m1; 19 | yl = ym1; 20 | } else { 21 | r = m2; 22 | yr = ym2; 23 | } 24 | } 25 | return f((l+r)/2); 26 | } 27 | 28 | template 29 | double ternary_search_max(F f, double l, double r) { 30 | return ternary_search(less(), f, l, r); 31 | } 32 | 33 | template 34 | double ternary_search_min(F f, double l, double r) { 35 | return ternary_search(greater(), f, l, r); 36 | } 37 | -------------------------------------------------------------------------------- /quadtree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | #define REP(i,n) for (int i = 0; i < (n); ++i) 6 | #define SZ(x) ((int)(x).size()) 7 | 8 | // below is a quad tree optimized for range sum queries. using it, 9 | // we can update the value of single cells of a grid and query the sum of 10 | // a 2D range 11 | 12 | struct Point { 13 | int x, y; 14 | int value; 15 | Point(int x_, int y_, int value_) : x(x_), y(y_), value(value_) {} 16 | Point() : x(0), y(0), value(0) {} 17 | }; 18 | 19 | const size_t CAPACITY = 20; 20 | const int CHILDSIZE = 4; 21 | 22 | struct Quadtree { 23 | Quadtree *children[CHILDSIZE]; 24 | vector points; 25 | bool leaf; 26 | int x, y, width, height, w1, h1; 27 | int sum; 28 | Quadtree(int x_, int y_, int width_, int height_) 29 | : points(), leaf(true), x(x_), y(y_), width(width_), height(height_), sum(0) 30 | {} 31 | ~Quadtree() { 32 | if (!leaf) REP(i, CHILDSIZE) delete children[i]; 33 | } 34 | 35 | int range_query(int x1, int x2, int y1, int y2) { 36 | if (x1 <= x && x2 >= x + width && y1 <= y && y2 >= y + height) return sum; 37 | if (x2 <= x || x1 >= x + width || y2 <= y || y1 >= y + height) return 0; 38 | int res = 0; 39 | if (leaf) { 40 | REP(i, SZ(points)) { 41 | Point& p = points[i]; 42 | if (x1 <= p.x && p.x < x2 && y1 <= p.y && p.y < y2) 43 | res += p.value; 44 | } 45 | } else { 46 | REP(i, CHILDSIZE) 47 | res += children[i]->range_query(x1, x2, y1, y2); 48 | } 49 | return res; 50 | } 51 | 52 | void update(int x, int y, int diff) { 53 | sum += diff; 54 | if (leaf) { 55 | bool found = false; 56 | REP(i, SZ(points)) 57 | if (points[i].x == x && points[i].y == y) { 58 | points[i].value += diff; 59 | found = true; 60 | break; 61 | } 62 | if (!found) { 63 | sum -= diff; 64 | insert(Point(x,y,diff)); 65 | } 66 | } else get_child(x, y).update(x, y, diff); 67 | } 68 | 69 | void split() { 70 | if (width == 1 && height == 1) return; 71 | leaf = false; 72 | w1 = width/2, h1 = height/2; 73 | children[0] = new Quadtree(x, y, w1, h1); 74 | children[1] = new Quadtree(x+w1, y, width-w1, h1); 75 | children[2] = new Quadtree(x+w1, y+h1, width-w1, height-h1); 76 | children[3] = new Quadtree(x, y+h1, w1, height-h1); 77 | REP(i, SZ(points)) 78 | get_child(points[i].x, points[i].y).insert(points[i]); 79 | points.clear(); 80 | } 81 | 82 | void insert(const Point& p) { 83 | sum += p.value; 84 | if (leaf && points.size() == CAPACITY) split(); 85 | if (leaf) points.push_back(p); 86 | else get_child(p.x, p.y).insert(p); 87 | } 88 | 89 | Quadtree& get_child(int x, int y) { 90 | for (int i = 0; i < CHILDSIZE-1; ++i) { 91 | Quadtree& c = *children[i]; 92 | if (x >= c.x && y >= c.y && x < c.x + c.width && y < c.y + c.height) 93 | return c; 94 | } 95 | return *children[CHILDSIZE-1]; 96 | } 97 | }; 98 | -------------------------------------------------------------------------------- /radix_sort.cpp: -------------------------------------------------------------------------------- 1 | // works in-place, O(n*d), swap needs to be adapted 2 | // could contain a bug! test against sort first! 3 | // 4 | // len = number of digits 5 | // getdig(x, 0) should get the most significant digit, get(x, len - 1) the lsd etc. 6 | const int max_val=256; 7 | template 8 | void radix_sort_msb(T& seq, F getdig, int len, int l, int r, int base = 0) { 9 | if (r-l <= 20) { 10 | sort(&seq[l],&seq[r]); // even better: use insertion sort 11 | return; 12 | } 13 | if (base == len || r-l <= 1) return; 14 | int start[max_val+1] = {0}, pos[max_val+1] = {0}; 15 | start[0] = l; 16 | rep(i,l,r) start[getdig(seq[i], base)+1]++; 17 | rep(i,1,max_val+1) start[i] += start[i-1], pos[i] = start[i]; 18 | rep(c,0,max_val) { 19 | rep(i,start[c], start[c+1]) { 20 | for(;;) { 21 | int d = getdig(seq[i], base); 22 | if (d==c) break; 23 | int& j = pos[d]; 24 | swap(seq[i], seq[j]); 25 | j++; 26 | } 27 | } 28 | radix_sort_msb(seq,getdig,len,start[c],start[c+1],base+1); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /range_tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | using namespace std; 24 | using namespace std::tr1; 25 | 26 | typedef long long ll; 27 | typedef pair pii; 28 | typedef vector vi; 29 | #define foreach(v,c) for(typeof((c).begin()) v=(c).begin(); v!=(c).end();++v) 30 | #define rep(i,s,e) for (int i=(s);i<(e);++i) 31 | #define pb push_back 32 | #define mk make_pair 33 | #define fst first 34 | #define snd second 35 | #define all(x) (x).begin(),(x).end() 36 | #define clr(x,y) memset(x,y,sizeof x) 37 | #define contains(x,y) (x).find(y)!=(x).end() 38 | #define endl "\n" 39 | 40 | int dx[]={0,0,1,-1,1,-1,1,-1}, dy[]={-1,1,0,0,1,-1,-1,1}; 41 | const int mod = 1e9+7,maxn=100100; 42 | 43 | // space O(n * log n), build O(n * log n), query O(log^2 n + k), k = output 44 | typedef int XX; 45 | typedef int YY; 46 | typedef pair Point; 47 | typedef pair > Node; 48 | const XX inf = 1<<30; 49 | 50 | int N; 51 | Node tree[maxn]; 52 | 53 | int left(int i) { return (i<<1) + 1; } 54 | int right(int i) { return (i<<1) + 2; } 55 | bool leaf(int i) { return i >= N-1; } 56 | bool cmpY(const Point& a, const Point& b) { return a.snd < b.snd; } 57 | 58 | void build_rec(vector& src, int l, int r, int i) { 59 | int m = (l+r)/2; 60 | tree[i] = mk(src[m].fst, vector()); 61 | vector& points = tree[i].snd; 62 | if (l == r) { 63 | points = src[l].snd; 64 | } else { 65 | build_rec(src, l, m, left(i)); 66 | build_rec(src, m+1, r, right(i)); 67 | merge(tree[left(i)].snd.begin(), tree[left(i)].snd.end(), 68 | tree[right(i)].snd.begin(), tree[right(i)].snd.end(), 69 | back_inserter(points), cmpY); 70 | } 71 | } 72 | 73 | int cnt; 74 | void report(int n, int y1, int y2) { 75 | vector& p = tree[n].snd; 76 | vector::iterator 77 | l = lower_bound(all(p), Point(0, y1), cmpY), 78 | r = upper_bound(all(p), Point(0, y2), cmpY); 79 | //for (; l != r; ++l) { cout << p.fst<<" "<= tree[n].fst)) 94 | report(n, y1, y2); 95 | } 96 | 97 | void query(int x1, int x2, int y1, int y2) { 98 | int n = 0; 99 | while (!leaf(n)) { // find split point 100 | if (x1 <= tree[n].fst && x2 <= tree[n].fst) n = left(n); 101 | else if (x1 > tree[n].fst && x2 > tree[n].fst) n = right(n); 102 | else break; 103 | } 104 | if (!leaf(n)) { 105 | walk(left(n), x1, y1, y2, true); 106 | walk(right(n), x2, y1, y2, false); 107 | } else if (x1 <= tree[n].fst && tree[n].fst <= x2) { 108 | report(n, y1, y2); 109 | } 110 | } 111 | 112 | void build(vector& src) { 113 | assert(src.size() > 0); 114 | sort(all(src)); 115 | vector items; 116 | items.pb(mk(src[0].fst, vector())); 117 | rep(i,0,src.size()) { 118 | if (i > 0 && src[i-1].fst != src[i].fst) 119 | items.pb(mk(src[i].fst, vector())); 120 | items.back().snd.pb(src[i]); 121 | } 122 | N = 1; 123 | while (N < items.size()) N <<= 1; 124 | while (items.size() < N) items.pb(mk(inf, vector())); 125 | build_rec(items, 0, N-1, 0); 126 | } 127 | 128 | void debug(int i=0, int indent=0) { 129 | cout << string(indent, ' '); 130 | cout << tree[i].fst << ": "; 131 | foreach(it,tree[i].snd) cout<< it->fst << "," << it->snd << " "; 132 | cout << endl; 133 | if (!leaf(i)) 134 | debug(left(i), indent + 2), debug(right(i), indent + 2); 135 | } 136 | 137 | int n, q; 138 | int main() { 139 | ios::sync_with_stdio(0); 140 | cout << fixed << setprecision(16); 141 | vector ps; 142 | cin>>n>>q; 143 | rep(i,0,n) { 144 | Point p; cin >> p.fst >> p.snd; 145 | ps.pb(p); 146 | } 147 | build(ps); 148 | //debug(); 149 | rep(i,0,q) { 150 | int x1, x2, y1, y2; 151 | cin >> x1 >> x2 >> y1 >> y2; 152 | cnt=0; 153 | query(x1,x2,y1,y2); 154 | cout << cnt << endl; 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /segment_tree.cpp: -------------------------------------------------------------------------------- 1 | const int maxn = 50500; 2 | const int inf = 1 << 29; 3 | const int maxl = 16; // = ceil(log_2(maxn)) 4 | int N = 1 << maxl; 5 | 6 | //============= customize here ================= 7 | 8 | struct Range { 9 | int max_left; 10 | int max_left1; 11 | int max_right; 12 | int max_right1; 13 | int max_mid1; 14 | int sum; 15 | int lo, hi; 16 | int count() const { return hi - lo + 1; } 17 | }; 18 | Range NULL_RANGE = {0, -inf, 0, -inf, -inf, 0, inf, -inf}; 19 | 20 | Range operator+(const Range& l, const Range& r) { 21 | return { 22 | max(l.sum + r.max_left, l.max_left), 23 | max(l.sum + ((l.count() > 0) ? r.max_left : r.max_left1), 24 | l.max_left1), 25 | 26 | max(r.sum + l.max_right, r.max_right), 27 | max(r.sum + ((r.count() > 0) ? l.max_right : l.max_right1), 28 | r.max_right1), 29 | 30 | max( l.max_mid1, 31 | max(r.max_mid1, 32 | max(l.max_right1 + r.max_left, 33 | l.max_right + r.max_left1))), 34 | l.sum + r.sum, 35 | min(l.lo, r.lo), max(l.hi, r.hi), 36 | }; 37 | } 38 | 39 | enum ActionType { ACTION_ID = 0, ACTION_SET }; 40 | struct Action { 41 | ActionType type; 42 | int val; 43 | Range apply(const Range& r) { 44 | if (type == ACTION_ID) return r; 45 | int w = r.count(); 46 | return { 47 | max(0, val * w), 48 | max(val, val * w), 49 | max(0, val * w), 50 | max(val, val * w), 51 | max(val, val * w), 52 | val * w, 53 | r.lo, r.hi, 54 | }; 55 | } 56 | }; 57 | Action NULL_ACTION = { ACTION_ID, 0 }; 58 | Action operator+(const Action& a, const Action& b) { 59 | if (b.type == ACTION_SET) return b; 60 | else return a; 61 | } 62 | 63 | //============= library code ================= 64 | 65 | int left(int i) { return 2 * i; } 66 | int right(int i) { return 2 * i + 1; } 67 | 68 | struct Node { 69 | Range r; 70 | Action action; 71 | Range range() { return action.apply(r); } 72 | } t[1 << (maxl + 1)]; 73 | 74 | void maintain(int i) { 75 | t[i].r = t[left(i)].range() + t[right(i)].range(); 76 | t[i].action = NULL_ACTION; 77 | } 78 | 79 | void update(int x, const Action& a, int ql, int qr); 80 | void push_down(int x) { 81 | update(left(x), t[x].action, -inf, inf); 82 | update(right(x), t[x].action, -inf, inf); 83 | t[x].r = t[x].action.apply(t[x].r); 84 | t[x].action = NULL_ACTION; 85 | } 86 | 87 | void update(int x, const Action& a, int ql, int qr) { 88 | if (t[x].r.hi < ql || t[x].r.lo > qr) return; 89 | if (ql <= t[x].r.lo && t[x].r.hi <= qr) { 90 | t[x].action = t[x].action + a; 91 | return; 92 | } 93 | push_down(x); 94 | update(left(x), a, ql, qr); 95 | update(right(x), a, ql, qr); 96 | maintain(x); 97 | } 98 | 99 | Range query(int x, int ql, int qr) { 100 | if (t[x].r.hi < ql || t[x].r.lo > qr) return NULL_RANGE; 101 | if (ql <= t[x].r.lo && t[x].r.hi <= qr) return t[x].range(); 102 | push_down(x); 103 | return query(left(x), ql, qr) + query(right(x), ql, qr); 104 | } 105 | 106 | // nodes reside in t[N..2N - 1], initialize those first 107 | void init() { 108 | rep(i,0,N) t[N + i].r.lo = t[N + i].r.hi = i; 109 | for (int i = N - 1; i >= 1; --i) 110 | maintain(i); 111 | } 112 | 113 | // ============= example ============== 114 | void run() { 115 | int n; 116 | cin >> n; 117 | N = 1; while (N < n) N <<= 1; 118 | rep(i,0,n) { 119 | int x; cin >> x; 120 | t[N + i].r = NULL_RANGE; 121 | t[N + i].action = { ACTION_SET, x }; 122 | } 123 | rep(i,n,N) t[N + i].r = NULL_RANGE; 124 | init(); 125 | // update 126 | int lo = 2, hi = 5; 127 | update(1, { ACTION_SET, 1 }, lo, hi); 128 | // query 129 | const Range& r = query(1, lo, hi); 130 | } 131 | -------------------------------------------------------------------------------- /segment_tree_skeleton.cpp: -------------------------------------------------------------------------------- 1 | int N, sum[2*maxn], mul[2*maxn], lo[2*maxn], hi[2*maxn]; 2 | void push(int x) { 3 | if (x < N) { 4 | mul[2*x] *= mul[x]; 5 | mul[2*x+1] *= mul[x]; 6 | } 7 | sum[x] *= mul[x]; 8 | mul[x] = 1; 9 | } 10 | void maintain(int x) { 11 | push(2*x); 12 | push(2*x+1); 13 | sum[x] = sum[2*x] + sum[2*x+1]; 14 | mul[x] = id; 15 | } 16 | void init(int n) { 17 | for (N=1; N= 1; --i) { 24 | maintain(i); 25 | lo[i] = lo[2*i]; 26 | hi[i] = hi[2*i+1]; 27 | } 28 | } 29 | void update(int x, int ql, int qr, matrix val) { 30 | if (hi[x] < ql || lo[x] > qr) return; 31 | if (ql <= lo[x] && qr >= hi[x]) { 32 | mul[x] *= val; 33 | return; 34 | } 35 | push(x); 36 | update(2*x, ql, qr, val); 37 | update(2*x+1, ql, qr, val); 38 | maintain(x); 39 | } 40 | int qry(int x, int ql, int qr) { 41 | if (hi[x] < ql || lo[x] > qr) return 0; 42 | push(x); 43 | if (ql <= lo[x] && qr >= hi[x]) return sum[x]; 44 | return qry(2*x, ql, qr) + qry(2*x+1, ql, qr); 45 | } 46 | -------------------------------------------------------------------------------- /shortest_path/dijkstra.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | 19 | typedef long long llong; 20 | typedef pair int2; 21 | #define foreach(v,c) for (typeof((c).begin()) v = (c).begin(); v != (c).end(); ++v) 22 | 23 | #define NM 10000 24 | int n; 25 | // first = other node, second = edge weight 26 | vector adj[NM+1]; 27 | int d[NM+1]; 28 | 29 | llong dijkstra(int a, int b) { 30 | fill(d, d + n + 1, INT_MAX); 31 | 32 | priority_queue > q; 33 | q.push(make_pair(0, a)); 34 | d[a] = 0; 35 | 36 | while (!q.empty()) { 37 | int x = q.top().second; 38 | int dist = -q.top().first; 39 | q.pop(); 40 | if (dist > d[x]) continue; 41 | if (x == b) break; 42 | foreach(it, adj[x]) { 43 | int v = it->first; 44 | llong w = it->second + d[x]; 45 | if (d[v] > w) { 46 | d[v] = w; 47 | q.push(make_pair(-d[v], v)); 48 | } 49 | } 50 | } 51 | return d[b]; 52 | } 53 | -------------------------------------------------------------------------------- /skiplist.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | using namespace std; 16 | 17 | typedef int T; 18 | const int maxh = 15; // should be around log2(n) 19 | 20 | struct Node { 21 | Node* nxt[maxh]; 22 | int h, dst[maxh]; 23 | T val; 24 | Node(T val) : h(0), val(val) { 25 | memset(nxt, 0, sizeof nxt); 26 | fill(dst, dst+maxh, 1); 27 | } 28 | ~Node() { if (nxt[0]) delete nxt[0]; } 29 | } *head=0; 30 | void init() { 31 | if (head) delete head; 32 | head = new Node(T()); 33 | } 34 | 35 | int pos[maxh+1]; 36 | Node* pred[maxh]; 37 | 38 | Node* find(T val) { // find a value and update predecessor info 39 | Node* n = head; 40 | pos[maxh] = 0; 41 | for (int lvl = maxh-1; lvl >= 0; --lvl) { 42 | pos[lvl] = pos[lvl+1]; 43 | while (n->nxt[lvl] && n->nxt[lvl]->val < val) { 44 | pos[lvl] += n->dst[lvl]; 45 | n = n->nxt[lvl]; 46 | } 47 | pred[lvl] = n; 48 | } 49 | return (n && n->val == val) ? n : 0; 50 | } 51 | 52 | Node* insert(T val) { // insert val and return inserted node 53 | find(val); 54 | Node* n = new Node(val); 55 | int lvl = 0; 56 | for (int lvl = 0; lvl < maxh; lvl++) 57 | pred[lvl]->dst[lvl]++; 58 | do { 59 | n->nxt[lvl] = pred[lvl]->nxt[lvl]; 60 | pred[lvl]->nxt[lvl] = n; 61 | n->dst[lvl] = pred[lvl]->dst[lvl] - pos[0] + pos[lvl] - 1; 62 | pred[lvl]->dst[lvl] = pos[0] - pos[lvl] + 1; 63 | lvl++; 64 | } while (lvl < maxh && rand() % 2); 65 | n->h = lvl-1; 66 | return n; 67 | } 68 | 69 | void remove(T val) { // remove val if existing 70 | Node* rem = find(val); 71 | if (!rem) return; 72 | for (int lvl = 0; lvl < maxh; ++lvl) { 73 | if (lvl <= rem->h) { 74 | pred[lvl]->nxt[lvl] = rem->nxt[lvl]; 75 | pred[lvl]->dst[lvl] += rem->dst[lvl] - 1; 76 | } else pred[lvl]->dst[lvl]--; 77 | } 78 | } 79 | 80 | int lessthan(T val) { // return # of elements < val 81 | find(val); 82 | return pos[0]; 83 | } 84 | 85 | Node* kth(int k) { // return k-th element (1 <= k < = n) 86 | Node* n = head; 87 | for (int lvl = maxh-1; lvl >= 0; --lvl) { 88 | while (n->dst[lvl] <= k) { 89 | k -= n->dst[lvl]; 90 | n = n->nxt[lvl]; 91 | } 92 | } 93 | return n; 94 | } 95 | 96 | int main() { 97 | ios_base::sync_with_stdio(false); 98 | srand(0x123123); 99 | int T; cin >> T; 100 | for (int tc = 1; tc <= T; ++tc) { 101 | int tcc, n; cin >> tcc >> n; 102 | init(); 103 | vector res; 104 | for (int i = 0; i < n; ++i) { 105 | int x; cin >> x; 106 | insert(x); 107 | if (i%2 == 0) 108 | res.push_back(kth(i/2 + 1)->val); 109 | } 110 | cout << tcc << " " << res.size() << endl; 111 | for (int i = 0; i < res.size(); ++i) { 112 | if (i > 0 && i % 10 == 0) cout << "\n"; 113 | if (i % 10) cout << " "; 114 | cout << res[i]; 115 | } 116 | cout << endl; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /splay_tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | using namespace std; 24 | using namespace std::tr1; 25 | 26 | typedef long long ll; 27 | typedef pair pii; 28 | typedef vector vi; 29 | #define foreach(v,c) for(typeof((c).begin()) v=(c).begin(); v!=(c).end();++v) 30 | #define rep(i,s,e) for (int i=(s);i<(e);++i) 31 | #define pb push_back 32 | #define mk make_pair 33 | #define fst first 34 | #define snd second 35 | #define all(x) (x).begin(),(x).end() 36 | #define clr(x,y) memset(x,y,sizeof x) 37 | #define contains(x,y) (x).find(y)!=(x).end() 38 | 39 | int dx[]={0,0,1,-1,1,-1,1,-1}, dy[]={-1,1,0,0,1,-1,-1,1}; 40 | const int mod = 1e9+7; 41 | 42 | typedef int T; 43 | T sentinel = -(1<<30); // must compare < to every value 44 | struct Tree { 45 | int sz,cnt; 46 | T val; Tree *child[2]; 47 | Tree(T val=sentinel, int cnt=0, Tree* l=0, Tree* r=0) : cnt(cnt), val(val) { 48 | child[0]=l; child[1]=r;maintain(); 49 | } 50 | void maintain() { sz = cnt + (child[0]?child[0]->sz:0) + (child[1]?child[1]->sz:0); } 51 | void setchild(bool c, Tree* t) { child[c]=t; maintain(); } 52 | }; 53 | void rotate(Tree*& t, bool c) { 54 | Tree *x = t->child[c]; 55 | t->setchild(c, x->child[!c]); 56 | x->setchild(!c, t); 57 | t = x; 58 | } 59 | void splay(Tree*& t, T x) { 60 | Tree N(0,0,0), *lr[2]={&N,&N}; 61 | for(;;) { 62 | bool c = x > t->val; 63 | if (t->val == x || !t->child[c]) break; 64 | if (!c && x < t->child[c]->val) rotate(t, c); 65 | if (c && x > t->child[c]->val) rotate(t, c); 66 | if (!t->child[c]) break; 67 | lr[!c]->setchild(c, t); lr[!c] = t; t = t->child[c]; 68 | } 69 | rep(i,0,2) { 70 | lr[i]->setchild(!i, t->child[i]); 71 | t->setchild(i, N.child[!i]); 72 | } 73 | } 74 | T walk(Tree* t, bool c) { return t->child[c] ? walk(t->child[c], c) : t->val; } 75 | void splaypred(Tree*& t, T x) { // splay max y in the tree with y <= x 76 | splay(t,x); 77 | if (t->val > x) splay(t, walk(t->child[0], 1)); 78 | } 79 | pair split(Tree *t, T x) { // split into subtrees (<= i, >i) 80 | splaypred(t,x); 81 | Tree *r = t->child[1]; 82 | t->setchild(1,0); 83 | return mk(t, r); 84 | } 85 | Tree* merge(Tree *a, Tree *b) { // precondition: max a < min b 86 | if (!a || !b) return a?a:b; 87 | splay(a, walk(a,1)); 88 | splay(b, walk(b,0)); 89 | a->setchild(1,b); 90 | return a; 91 | } 92 | void insert(Tree*& t, T x) { 93 | splay(t,x); 94 | if (t->val == x) t->cnt++, t->sz++; 95 | else { 96 | pair lr = split(t, x); 97 | t = new Tree(x, 1, lr.first, lr.second); 98 | } 99 | } 100 | void remove(Tree*& t, T x) { 101 | splay(t, x); 102 | if (t->val != x) return; 103 | t->cnt--; t->sz--; 104 | if (!t->cnt) { 105 | Tree *old = t; 106 | t = merge(t->child[0], t->child[1]); 107 | delete old; 108 | } 109 | } 110 | T select(Tree* t, int k) { // ranks start at 0 111 | int l = t->child[0] ? t->child[0]->sz : 0; 112 | if (k < l) return select(t->child[0], k); 113 | if (k >= l + t->cnt) return select(t->child[1], k - l - t->cnt); 114 | return t->val; 115 | } 116 | T getrank(Tree*& t, T x) { // find min i with select(t,i) > x } 117 | splaypred(t,x); 118 | return (t->child[0] ? t->child[0]->sz : 0) + t->cnt*(t->val != x); 119 | } 120 | 121 | void print(Tree *t, int indent=0) { 122 | rep(i,0,indent) cout << " "; 123 | if (!t) {cout << "NIL:0:0" << endl;return;} 124 | //if (t->val==sentinel) {cout<<"-oo:0:0"<val << "/" << t->cnt << " "<< t->sz << endl; 126 | rep(i,0,2) print(t->child[i], indent+2); 127 | if(!indent) cout << "=========="< objs; 144 | rep(i,0,100000) objs.pb(i); 145 | random_shuffle(all(objs)); 146 | foreach(it,objs) insert(t,*it); 147 | random_shuffle(all(objs)); 148 | foreach(it,objs) remove(t,*it); 149 | //vector objs; 150 | //init(); 151 | //rep(i,0,100000) objs.pb(i); 152 | //random_shuffle(all(objs)); 153 | //foreach(it,objs) insert(root,*it); 154 | //random_shuffle(all(objs)); 155 | //foreach(it,objs) remove(root,*it); 156 | //cout << select(t,100) << endl; 157 | return 0; 158 | } 159 | -------------------------------------------------------------------------------- /stl_splay_tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace __gnu_pbds; 6 | using namespace std; 7 | 8 | struct Node { int size, maxi; }; 9 | template 10 | #define POL detail::branch_policy 11 | struct tree_policy : private POL { 12 | typedef Node metadata_type; 13 | void operator() (ni it, nci null) const { 14 | auto& n = (Node&)it.get_metadata(); 15 | n.size = 1; 16 | n.maxi = (*it)->second; 17 | for (auto& c : { it.get_l_child(), it.get_r_child() }) { 18 | if (c != null) { 19 | n.size += c.get_metadata().size; 20 | n.maxi = max(n.maxi, c.get_metadata().size); 21 | } 22 | } 23 | } 24 | typename nci::value_type select(size_t k) const { 25 | auto it = node_begin(), null = node_end(); 26 | while (it != null) { 27 | auto l = it.get_l_child(); 28 | auto o = (l == null)? 0 : l.get_metadata().size; 29 | if (k == o) return *it; 30 | else if (k < o) it = l; 31 | else k -= o + 1, it = it.get_r_child(); 32 | } 33 | return POL::end_iterator(); 34 | } 35 | virtual nci node_begin() const = 0; 36 | virtual nci node_end() const = 0; 37 | }; 38 | typedef tree,splay_tree_tag,tree_policy> Tree; 39 | Tree* other; 40 | typedef Tree::iterator ti; 41 | namespace std { 42 | template<> iterator_traits::difference_type distance(ti a, ti b) { 43 | assert(other->begin() == a && other->end() == b); 44 | return other->node_begin().get_metadata().size; 45 | } 46 | } 47 | void split(Tree& a, Tree& b, int x) { other=&b; a.split(x, b); } 48 | Tree::const_iterator select(Tree& a, int k) { 49 | auto it = a.select(k); 50 | a.find(it->first); // splay if necessary 51 | return it; 52 | } 53 | int rank_of(Tree& a, int key) { 54 | auto it = a.find(key); 55 | auto l = (Tree::node_iterator){it.m_p_nd}.get_l_child(); 56 | return l == a.node_end() ? 0 : l.get_metadata().size; 57 | } 58 | 59 | Tree A; 60 | int arr[1000100]; 61 | 62 | int main() { 63 | int n; 64 | scanf("%d", &n); 65 | for (int i = 1; i <= n; i++) { 66 | int t; 67 | scanf("%d", &t); 68 | A.insert(make_pair(i, t)); 69 | arr[i] = t; 70 | } 71 | for (int i = 1; i <= n; ++i) { 72 | assert(select(A,i-1)->second == arr[i]); 73 | assert(rank_of(A,i)==i-1); 74 | } 75 | assert(n==A.node_begin().get_metadata().size); 76 | //return 0; 77 | int m; 78 | scanf("%d", &m); 79 | for (int i = 0; i < m; i++) 80 | { 81 | char t; 82 | int x, y; 83 | scanf(" %c %d %d", &t, &x, &y); 84 | if (t == 'u') 85 | { 86 | A.erase(x); 87 | A.insert(make_pair(x, y)); 88 | } 89 | else 90 | { 91 | Tree B, C; 92 | split(A, C, y); 93 | split(A, B, x-1); 94 | printf("%d\n", B.node_begin().get_metadata().maxi); 95 | A.join(B); 96 | A.join(C); 97 | } 98 | } 99 | } 100 | 101 | -------------------------------------------------------------------------------- /suffix_automaton.cpp: -------------------------------------------------------------------------------- 1 | struct SuffixAutomaton { // can be used for LCS and others 2 | struct State { 3 | int depth, id; 4 | State *go[128], *suffix; 5 | } *root = new State {0}, *sink = root; 6 | void append(const string& str, int offset=0) { // O(|str|) 7 | for (int i = 0; i < str.size(); ++i) { 8 | int a = str[i]; 9 | State *cur = sink, *sufState; 10 | sink = new State { sink->depth + 1, offset + i, {0}, 0 }; 11 | while (cur && !cur->go[a]) { 12 | cur->go[a] = sink; 13 | cur = cur->suffix; 14 | } 15 | if (!cur) sufState = root; 16 | else { 17 | State *q = cur->go[a]; 18 | if (q->depth == cur->depth + 1) 19 | sufState = q; 20 | else { 21 | State *r = new State(*q); 22 | r->depth = cur->depth + 1; 23 | q->suffix = sufState = r; 24 | while (cur && cur->go[a] == q) { 25 | cur->go[a] = r; 26 | cur = cur->suffix; 27 | } 28 | } 29 | } 30 | sink->suffix = sufState; 31 | } 32 | } 33 | int walk(const string& str) { // O(|str|) returns LCS with automaton string 34 | int tmp = 0; 35 | State *cur = root; 36 | int ans = 0; 37 | for (int i = 0; i < str.size(); ++i) { 38 | int a = str[i]; 39 | if (cur->go[a]) { 40 | tmp++; 41 | cur = cur->go[a]; 42 | } else { 43 | while (cur && !cur->go[a]) 44 | cur = cur->suffix; 45 | if (!cur) { 46 | cur = root; 47 | tmp = 0; 48 | } else { 49 | tmp = cur->depth + 1; 50 | cur = cur->go[a]; 51 | } 52 | } 53 | ans = max(ans, tmp); // i - tmp + 1 is start of match 54 | } 55 | return ans; 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /suffixarray_lcp_based.cpp: -------------------------------------------------------------------------------- 1 | const int maxn = 200010, maxlg = 18; // maxlg = ceil(log_2(maxn)) 2 | struct SA { 3 | pair, int> L[maxn]; // O(n * log n) space 4 | int P[maxlg+1][maxn], n, stp, cnt, sa[maxn]; 5 | SA(const string& s) : n(s.size()) { // O(n * log n) 6 | rep(i,0,n) P[0][i] = s[i]; 7 | sa[0] = 0; // in case n == 1 8 | for (stp = 1, cnt = 1; cnt < n; stp++, cnt <<= 1) { 9 | rep(i,0,n) L[i] = {{P[stp-1][i], i + cnt < n ? P[stp-1][i+cnt] : -1}, i}; 10 | std::sort(L, L + n); 11 | rep(i,0,n) 12 | P[stp][L[i].second] = i>0 && L[i].first == L[i-1].first ? P[stp][L[i-1].second] : i; 13 | } 14 | rep(i,0,n) sa[i] = L[i].second; 15 | } 16 | int lcp(int x, int y) { // time log(n); x, y = indices into string, not SA 17 | int k, ret = 0; 18 | if (x == y) return n - x; 19 | for (k = stp - 1; k >= 0 && x < n && y < n; k --) 20 | if (P[k][x] == P[k][y]) 21 | x += 1< 2 | using namespace std; 3 | 4 | using ll=long long; 5 | using ull=unsigned long long; 6 | #define rep(i,s,e) for(int i=(s);i<(e);++i) 7 | #include "../number_theory.cpp" 8 | 9 | int main() { 10 | for (int a = 1; a <= 10000; ++a) { 11 | map facs; 12 | factor(a, facs); 13 | ll x = 1; 14 | for (auto it: facs) { 15 | assert(rabin(it.first)); 16 | x *= powmod(it.first, it.second, a+1); 17 | } 18 | assert(x == a); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /treap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define INVALID -(1<<30) 6 | #define maxn 1000100 7 | struct node { 8 | int data,priority,count,size,child[2]; 9 | } treap[maxn]; 10 | int temp,top,root; 11 | inline void init() { // initialization 12 | srand(time(0)); 13 | treap[0]=(node){0,0,0,0,{0,0}}; 14 | top=0; root=0; 15 | } 16 | inline void maintain(int r) { 17 | treap[r].size=treap[treap[r].child[0]].size+ 18 | treap[treap[r].child[1]].size+treap[r].count; 19 | } // op=0 right rotate, otherwise left rotate 20 | inline void rotate(int &r, int op) { 21 | temp=treap[r].child[op]; 22 | treap[r].child[op]=treap[temp].child[!op]; 23 | treap[temp].child[!op]=r; 24 | maintain(r); maintain(temp); r=temp; 25 | } // insert an element 26 | void insert(int &r,int d) { 27 | if (r==0) 28 | treap[r=++top]=(node){d,rand(),1,1,{0,0}}; 29 | else if (d==treap[r].data) 30 | treap[r].count++,treap[r].size++; 31 | else { 32 | int dir = d>treap[r].data; 33 | insert(treap[r].child[dir],d); 34 | treap[r].size++; 35 | if (treap[treap[r].child[dir]].prioritytreap[r].data],d); 45 | else { 46 | if ((res = (treap[r].count>0))) 47 | treap[r].count--; 48 | } 49 | maintain(r); //when r == 0 , maintain does nothing 50 | return res; 51 | } // count how many duplications does the given element have 52 | int find(int r,int d) { 53 | while (r!=0 && treap[r].data!=d) 54 | r = treap[r].child[d>treap[r].data]; 55 | return treap[r].count; 56 | } // count how many elements <= the given element 57 | int lessequal(int r, int d) { 58 | int res = 0; 59 | while (r!=0 && treap[r].data!=d) { 60 | if (d>treap[r].data) 61 | res+=treap[r].count+treap[treap[r].child[0]].size; 62 | r = treap[r].child[d>treap[r].data]; 63 | } 64 | return res+treap[r].count+treap[treap[r].child[0]].size; 65 | }// return the k-th smallest element 66 | int kth(int r,int d) { 67 | if (d>treap[r].size || d<1) 68 | return INVALID; 69 | while (true) 70 | if (d>treap[treap[r].child[0]].size) { 71 | d-=treap[treap[r].child[0]].size; 72 | if (d<=treap[r].count) 73 | return treap[r].data; 74 | else 75 | d-=treap[r].count,r=treap[r].child[1]; 76 | } else r=treap[r].child[0]; 77 | } 78 | 79 | int main() { 80 | init(); 81 | for (int i = 1; i <= 1000000; ++i) 82 | insert(root, i); 83 | } 84 | -------------------------------------------------------------------------------- /treap_multi.cpp: -------------------------------------------------------------------------------- 1 | // Treap with multiset functionality 2 | struct Node { 3 | ll val, cnt, prio, size; 4 | Node* child[2]; 5 | void apply() { // apply lazy actions and push them down 6 | } 7 | void maintain() { 8 | size = cnt; 9 | rep(i,0,2) size += child[i] ? child[i]->size : 0; 10 | } 11 | }; 12 | pair split(Node* n, ll val) { // returns (< val, >= val) 13 | if (!n) return {0,0}; 14 | n->apply(); 15 | Node*& c = n->child[val > n->val]; 16 | auto sub = split(c, val); 17 | if (val > n->val) { c = sub.fst; n->maintain(); return mk(n, sub.snd); } 18 | else { c = sub.snd; n->maintain(); return mk(sub.fst, n); } 19 | } 20 | Node* merge(Node* l, Node* r) { 21 | if (!l || !r) return l ? l : r; 22 | if (l->prio > r->prio) { 23 | l->apply(); 24 | l->child[1] = merge(l->child[1], r); 25 | l->maintain(); 26 | return l; 27 | } else { 28 | r->apply(); 29 | r->child[0] = merge(l, r->child[0]); 30 | r->maintain(); 31 | return r; 32 | } 33 | } 34 | Node* insert(Node* n, ll val, ll num=1) { 35 | auto l = split(n, val); 36 | auto r = split(l.second, val + 1); 37 | if (r.first) { 38 | r.first->apply(); 39 | r.first->cnt += num; 40 | } 41 | else { 42 | r.first = new Node { val, num, rand(), num }; 43 | } 44 | r.first->maintain(); 45 | return merge(merge(l.fst, r.fst), r.second); 46 | } 47 | Node* remove(Node* n, ll val, ll num=1) { // DANGER UNTESTED SO FAR 48 | if (!n) return 0; 49 | n->apply(); 50 | if (val == n->val) { 51 | if (num == n->cnt) 52 | return merge(n->child[0], n->child[1]); 53 | else { 54 | n->apply(); 55 | n->cnt -= num; 56 | n->maintain(); 57 | return n; 58 | } 59 | } 60 | Node*& c = n->child[val > n->val]; 61 | c = remove(c, val, num); 62 | n->maintain(); 63 | return n; 64 | } 65 | 66 | void debug(Node* n, int ind=0) { 67 | if (!n) { 68 | rep(_,0,ind) cout << " "; 69 | cout << "NIL" << endl; 70 | return; 71 | } 72 | rep(_,0,ind) cout << " "; cout << n->val << "*" << n->cnt << " : " << n->size << endl; 73 | debug(n->child[0], ind+1); 74 | debug(n->child[1], ind+1); 75 | } 76 | 77 | Node* copy(Node* from, Node* to) { // insert everything from one treap into another 78 | if (!from) return to; 79 | return copy(from->child[0], copy(from->child[1], insert(to, from->val, from->cnt))); 80 | } 81 | -------------------------------------------------------------------------------- /treap_simple.cpp: -------------------------------------------------------------------------------- 1 | struct Node { 2 | int val, prio, size; 3 | Node* child[2]; 4 | void apply() { // apply lazy actions and push them down 5 | } 6 | void maintain() { 7 | size = 1; 8 | rep(i,0,2) size += child[i] ? child[i]->size : 0; 9 | } 10 | }; 11 | pair split(Node* n, int val) { // returns (< val, >= val) 12 | if (!n) return {0,0}; 13 | n->apply(); 14 | Node*& c = n->child[val > n->val]; 15 | auto sub = split(c, val); 16 | if (val > n->val) { c = sub.fst; n->maintain(); return mk(n, sub.snd); } 17 | else { c = sub.snd; n->maintain(); return mk(sub.fst, n); } 18 | } 19 | Node* merge(Node* l, Node* r) { 20 | if (!l || !r) return l ? l : r; 21 | if (l->prio > r->prio) { 22 | l->apply(); 23 | l->child[1] = merge(l->child[1], r); 24 | l->maintain(); 25 | return l; 26 | } else { 27 | r->apply(); 28 | r->child[0] = merge(l, r->child[0]); 29 | r->maintain(); 30 | return r; 31 | } 32 | } 33 | Node* insert(Node* n, int val) { 34 | auto sub = split(n, val); 35 | Node* x = new Node { val, rand(), 1 }; 36 | return merge(merge(sub.fst, x), sub.snd); 37 | } 38 | Node* remove(Node* n, int val) { 39 | if (!n) return 0; 40 | n->apply(); 41 | if (val == n->val) 42 | return merge(n->child[0], n->child[1]); 43 | Node*& c = n->child[val > n->val]; 44 | c = remove(c, val); 45 | n->maintain(); 46 | return n; 47 | } 48 | -------------------------------------------------------------------------------- /treap_supersimple.cpp: -------------------------------------------------------------------------------- 1 | struct Node { 2 | int val, prio, size; 3 | Node* child[2]; 4 | Node* maintain() { 5 | size = 1 + (child[0] ? child[i]->size : 0) + (child[1] ? child[1]->size : 0); 6 | return this; 7 | } 8 | }; 9 | pair split(Node* n, int val) { // returns subtrees (< val, >= val) 10 | if (!n) return {0,0}; 11 | Node*& c = n->child[val > n->val]; 12 | auto sub = split(c, val); 13 | if (val > n->val) { c = sub.fst; n->maintain(); return mk(n, sub.snd); } 14 | else { c = sub.snd; n->maintain(); return mk(sub.fst, n); } 15 | } 16 | Node* merge(Node* l, Node* r) { 17 | if (!l || !r) return l ? l : r; 18 | if (l->prio > r->prio) { 19 | l->child[1] = merge(l->child[1], r); 20 | return l->maintain(); 21 | } else { 22 | r->child[0] = merge(l, r->child[0]); 23 | return r->maintain(); 24 | } 25 | } 26 | Node* insert(Node* n, int val) { 27 | auto sub = split(n, val); 28 | Node* x = new Node { val, rand(), 1 }; 29 | return merge(merge(sub.fst, x), sub.snd); 30 | } 31 | Node* remove(Node* n, int val) { 32 | if (!n) return 0; 33 | if (val == n->val) return merge(n->child[0], n->child[1]); 34 | Node*& c = n->child[val > n->val]; 35 | c = remove(c, val); 36 | return n->maintain(); 37 | } 38 | Node* kth(Node* n, int k) { 39 | int leftsz = n->child[0].size; 40 | if (k == leftsz) return n; 41 | if (k < leftsz) return kth(n->child[0], k); 42 | else return kth(n->child[1], k - leftsz - 1); 43 | } 44 | 45 | int main() { 46 | } 47 | -------------------------------------------------------------------------------- /tree_aggregation.cpp: -------------------------------------------------------------------------------- 1 | // This is O(n*d) where d is the maximum vertex degree. We can also use DP on 2 | // (x, from) instead in dfs1. 3 | void maintain(int x, int exclude) { 4 | g[x] = 1; 5 | for (int y: adj[x]) { 6 | if (y == exclude) continue; 7 | g[x] += g[y]; 8 | } 9 | } 10 | // build initial data structures with fixed root 11 | void dfs1(int x, int from) { 12 | for (int y: adj[x]) if (y != from) 13 | dfs1(y, x); 14 | maintain(x, from); 15 | } 16 | // inspect data structures with x as root 17 | void dfs2(int x, int from) { 18 | for (int y: adj[x]) if (y != from) { 19 | maintain(x, y); 20 | maintain(y, -1); 21 | dfs2(y, x); 22 | } 23 | maintain(x, from); 24 | } 25 | -------------------------------------------------------------------------------- /weight_balanced_tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | typedef long long ll; typedef long double ld; 5 | #define rep(i,s,e) for (int i=(s);i<(e);++i) 6 | #define all(x) begin(x),end(x) 7 | #define clr(x,y) memset(x,y,sizeof x) 8 | #define contains(x,y) ((x).find(y)!=end(x)) 9 | #define pb push_back 10 | #define Tu tuple 11 | #define mk make_pair 12 | #define mkt make_tuple 13 | #define fst first 14 | #define snd second 15 | #define _1 get<0> 16 | #define _2 get<1> 17 | #define _3 get<2> 18 | #define _4 get<3> 19 | #define sz(x) ((int)(x).size()) 20 | 21 | // a BB[alpha] tree implementation that rebuilds entire subtrees if they get 22 | // unbalanced 23 | #include 24 | #include 25 | #include 26 | #include 27 | using namespace std; 28 | 29 | double alpha = 0.25; 30 | 31 | #define treesz(n) ((n) ? (n)->treesize : 0) 32 | #define valsz(n) ((n) ? (n)->valsize : 0) 33 | struct Node { 34 | int val, count, valsize, treesize; 35 | Node *l, *r; 36 | Node(int val, int count, Node* l, Node* r) : val(val), count(count), l(l), r(r) { 37 | maintain(); 38 | } 39 | void maintain() { 40 | valsize = count + valsz(l) + valsz(r); 41 | treesize = 1 + treesz(l) + treesz(r); 42 | } 43 | bool balanced() { 44 | return min(treesz(l), treesz(r)) >= alpha * (treesz(l) + treesz(r)) - 1; 45 | } 46 | }; 47 | vector nodes; 48 | void dfs(Node *n) { 49 | if (!n) return; 50 | dfs(n->l); 51 | nodes.pb(n); 52 | dfs(n->r); 53 | } 54 | Node* build(int l, int r) { 55 | if (r < l) return 0; 56 | int m = (l + r) / 2; 57 | Node* res = new Node(nodes[m]->val, nodes[m]->count, build(l, m - 1), build(m + 1, r)); 58 | delete nodes[m]; 59 | return res; 60 | } 61 | int tot = 0; 62 | Node* maintain(Node* n) { 63 | n->maintain(); 64 | if (n->balanced()) return n; 65 | nodes.clear(); 66 | dfs(n); 67 | tot += nodes.size(); 68 | n = build(0, nodes.size() - 1); 69 | assert(n->balanced()); 70 | return n; 71 | } 72 | void insert(Node*& n, int x, bool rem=0) { 73 | if (!n && rem) return; 74 | else if (!n) n = new Node(x, 1, 0, 0); 75 | else if (x == n->val) n->count += rem ? -1 : 1, n->maintain(); 76 | else { 77 | insert(x < n->val ? n->l : n->r, x, rem); 78 | n = maintain(n); 79 | } 80 | } 81 | void remove(Node*& n, int x) { return insert(n, x, 1); } 82 | 83 | Node *root = 0; 84 | 85 | // test helpers 86 | int height(Node *n) { 87 | if (!n) return 0; 88 | return 1 + max(height(n->l), height(n->r)); 89 | } 90 | bool is_consistent(Node *n) { 91 | if (!n) return 1; 92 | if (treesz(n->l) + treesz(n->r) + 1 != n->treesize) return 0; 93 | if (valsz(n->l) + valsz(n->r) + n->count != n->valsize) return 0; 94 | if (!n->balanced()) return 0; 95 | return is_consistent(n->l) && is_consistent(n->r); 96 | } 97 | void debug(Node* n, int ind = 0) { 98 | rep(_,0,ind) cout << " "; 99 | if(!n) {cout << "NIL:0" << endl;return;} 100 | cout << n->val << ":" << n->count <<" " << valsz(n) <<" " << is_consistent(n) << endl; 101 | debug(n->l, ind + 1); 102 | debug(n->r, ind + 1); 103 | } 104 | 105 | int N = 1000000; 106 | int main() { 107 | for (int i = 1; i <= N; ++i) insert(root, i); 108 | for (int i = 1; i <= N; ++i) insert(root, i); 109 | for (int i = 1; i <= N; ++i) remove(root, i); 110 | //debug(root); 111 | cout << "consistent: " << is_consistent(root) << endl; 112 | cout << "heigth: " << height(root) << endl; 113 | cout << "total rebuilt nodes: " << tot << endl; 114 | //vals.clear(); 115 | //dfs(root); 116 | //sort(all(vals)); 117 | //assert(vals.size() == N); 118 | //for (int i = 0; i < N; ++i) assert(vals[i] == mk(i + 1, 1)); 119 | } 120 | --------------------------------------------------------------------------------