├── .gitignore ├── Makefile ├── README.md ├── consola.ttf ├── consolab.ttf ├── consolai.ttf ├── consolaz.ttf ├── src ├── data-structure │ ├── convex-hull-trick-linear.cpp │ ├── fenwick-tree.cpp │ ├── order-statistic-tree.cpp │ ├── persistent-segtree.cpp │ ├── segtree-lazyprop.cpp │ └── splay-tree.cpp ├── geometry │ ├── basic-operations.cpp │ ├── convex-hull.cpp │ ├── point-in-polygon.cpp │ ├── polygon-cut.cpp │ └── rotating-calipers.cpp ├── graph │ ├── bcc.cpp │ ├── bipartite-matching-hopcroft.cpp │ ├── general-mincut-stoer-wagner.cpp │ ├── hld.cpp │ ├── hungarian.cpp │ ├── lca.cpp │ ├── maxflow-dinic.cpp │ ├── maxflow-ed.cpp │ ├── mcmf.cpp │ ├── scc.cpp │ └── spfa.cpp ├── math │ ├── basic-arithmetic.cpp │ ├── chinese-remainder.cpp │ ├── fft.cpp │ ├── gaussian.cpp │ ├── lucas-theorem.cpp │ ├── matrix-operations.cpp │ ├── pollard-rho.cpp │ ├── primality-test.cpp │ ├── rational.cpp │ ├── sieve.cpp │ └── simplex.cpp ├── miscellaneous │ ├── example.java │ └── fastio.cpp ├── setting │ └── vimrc └── string │ ├── aho-corasick.cpp │ ├── kmp.cpp │ ├── manacher.cpp │ ├── suffix-array-lcp.cpp │ └── z.cpp ├── teamnote.pdf └── teamnote.tex /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.aux 3 | *.log 4 | *.toc 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | 3 | all: teamnote.pdf 4 | 5 | SOURCE_TEX=teamnote.tex 6 | SOURCE_CPPS=$(shell find 'src' -name '*.cpp') 7 | 8 | teamnote.pdf: $(SOURCE_TEX) $(SOURCE_CPPS) 9 | xelatex --shell-escape $(SOURCE_TEX) 10 | xelatex --shell-escape $(SOURCE_TEX) 11 | 12 | clean: 13 | rm -rf teamnote.pdf *.log *.aux *.pyg *.toc 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # team note for ACM-ICPC 2 | 3 | ## Requirements 4 | 5 | ``` 6 | sudo apt-get install texlive-xetex 7 | sudo apt-get install texlive-lang-cjk 8 | sudo apt-get install texlive-fonts-recommended 9 | ``` 10 | 11 | ## How to build 12 | 13 | ``` 14 | make 15 | ``` 16 | 17 | ## Reference 18 | 19 | * https://github.com/wookayin/teamnote 20 | * https://github.com/jaehyunp/stanfordacm 21 | * https://github.com/albusmath/acm-icpc-template 22 | * https://github.com/kcm1700/algorithms 23 | * http://codeforces.com/blog/entry/23054 24 | -------------------------------------------------------------------------------- /consola.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntopia/icpc-teamnote/9e4b112a56fff131d3e3dc153c0babcd9976583d/consola.ttf -------------------------------------------------------------------------------- /consolab.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntopia/icpc-teamnote/9e4b112a56fff131d3e3dc153c0babcd9976583d/consolab.ttf -------------------------------------------------------------------------------- /consolai.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntopia/icpc-teamnote/9e4b112a56fff131d3e3dc153c0babcd9976583d/consolai.ttf -------------------------------------------------------------------------------- /consolaz.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntopia/icpc-teamnote/9e4b112a56fff131d3e3dc153c0babcd9976583d/consolaz.ttf -------------------------------------------------------------------------------- /src/data-structure/convex-hull-trick-linear.cpp: -------------------------------------------------------------------------------- 1 | struct CHTLinear { 2 | struct Line { 3 | long long a, b; 4 | long long y(long long x) const { return a * x + b; } 5 | }; 6 | vector stk; 7 | int qpt; 8 | CHTLinear() : qpt(0) { } 9 | // when you need maximum : (previous l).a < (now l).a 10 | // when you need minimum : (previous l).a > (now l).a 11 | void pushLine(const Line& l) { 12 | while (stk.size() > 1) { 13 | Line& l0 = stk[stk.size() - 1]; 14 | Line& l1 = stk[stk.size() - 2]; 15 | if ((l0.b - l.b) * (l0.a - l1.a) > (l1.b - l0.b) * (l.a - l0.a)) break; 16 | stk.pop_back(); 17 | } 18 | stk.push_back(l); 19 | } 20 | // (previous x) <= (current x) 21 | // it calculates max/min at x 22 | long long query(long long x) { 23 | while (qpt + 1 < stk.size()) { 24 | Line& l0 = stk[qpt]; 25 | Line& l1 = stk[qpt + 1]; 26 | if (l1.a - l0.a > 0 && (l0.b - l1.b) > x * (l1.a - l0.a)) break; 27 | if (l1.a - l0.a < 0 && (l0.b - l1.b) < x * (l1.a - l0.a)) break; 28 | ++qpt; 29 | } 30 | return stk[qpt].y(x); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /src/data-structure/fenwick-tree.cpp: -------------------------------------------------------------------------------- 1 | const int TSIZE = 100000; 2 | int tree[TSIZE + 1]; 3 | 4 | // Returns the sum from index 1 to p, inclusive 5 | int query(int p) { 6 | int ret = 0; 7 | for (; p > 0; p -= p & -p) ret += tree[p]; 8 | return ret; 9 | } 10 | 11 | // Adds val to element with index pos 12 | void add(int p, int val) { 13 | for (; p <= TSIZE; p += p & -p) tree[p] += val; 14 | } 15 | -------------------------------------------------------------------------------- /src/data-structure/order-statistic-tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace __gnu_pbds; 7 | using namespace std; 8 | 9 | // tree 10 | using ordered_set = tree, rb_tree_tag, 11 | tree_order_statistics_node_update>; 12 | 13 | int main() 14 | { 15 | ordered_set X; 16 | for (int i = 1; i < 10; i += 2) X.insert(i); // 1 3 5 7 9 17 | cout << boolalpha; 18 | cout << *X.find_by_order(2) << endl; // 5 19 | cout << *X.find_by_order(4) << endl; // 9 20 | cout << (X.end() == X.find_by_order(5)) << endl; // true 21 | 22 | cout << X.order_of_key(-1) << endl; // 0 23 | cout << X.order_of_key(1) << endl; // 0 24 | cout << X.order_of_key(4) << endl; // 2 25 | X.erase(3); 26 | cout << X.order_of_key(4) << endl; // 1 27 | for (int t : X) printf("%d ", t); // 1 5 7 9 28 | } 29 | -------------------------------------------------------------------------------- /src/data-structure/persistent-segtree.cpp: -------------------------------------------------------------------------------- 1 | // persistent segment tree impl: sum tree 2 | // initial tree index is 0 3 | namespace pstree { 4 | typedef int val_t; 5 | const int DEPTH = 18; 6 | const int TSIZE = 1 << 18; 7 | const int MAX_QUERY = 262144; 8 | 9 | struct node { 10 | val_t v; 11 | node *l, *r; 12 | } npoll[TSIZE * 2 + MAX_QUERY * (DEPTH + 1)], *head[MAX_QUERY + 1]; 13 | 14 | int pptr, last_q; 15 | 16 | void init() { 17 | // zero-initialize, can be changed freely 18 | memset(&npoll[TSIZE - 1], 0, sizeof(node) * TSIZE); 19 | 20 | for (int i = TSIZE - 2; i >= 0; i--) { 21 | npoll[i].v = 0; 22 | npoll[i].l = &npoll[i*2+1]; 23 | npoll[i].r = &npoll[i*2+2]; 24 | } 25 | 26 | head[0] = &npoll[0]; 27 | last_q = 0; 28 | pptr = 2 * TSIZE - 1; 29 | } 30 | 31 | // update val to pos 32 | // 0 <= pos < TSIZE 33 | // returns updated tree index 34 | int update(int pos, int val, int prev) { 35 | head[++last_q] = &npoll[pptr++]; 36 | node *old = head[prev], *now = head[last_q]; 37 | 38 | int flag = 1 << DEPTH; 39 | for (;;) { 40 | now->v = old->v + val; 41 | flag >>= 1; 42 | if (flag==0) { 43 | now->l = now->r = nullptr; break; 44 | } 45 | if (flag & pos) { 46 | now->l = old->l; 47 | now->r = &npoll[pptr++]; 48 | now = now->r, old = old->r; 49 | } else { 50 | now->r = old->r; 51 | now->l = &npoll[pptr++]; 52 | now = now->l, old = old->l; 53 | } 54 | } 55 | return last_q; 56 | } 57 | 58 | val_t query(int s, int e, int l, int r, node *n) { 59 | if (s == l && e == r) return n->v; 60 | int m = (l + r) / 2; 61 | if (m >= e) return query(s, e, l, m, n->l); 62 | else if (m < s) return query(s, e, m + 1, r, n->r); 63 | else return query(s, m, l, m, n->l) + query(m + 1, e, m + 1, r, n->r); 64 | } 65 | 66 | // query summation of [s, e] at time t 67 | val_t query(int s, int e, int t) { 68 | s = max(0, s); e = min(TSIZE - 1, e); 69 | if (s > e) return 0; 70 | return query(s, e, 0, TSIZE - 1, head[t]); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/data-structure/segtree-lazyprop.cpp: -------------------------------------------------------------------------------- 1 | // example implementation of sum tree 2 | const int TSIZE = 131072; // always 2^k form && n <= TSIZE 3 | int segtree[TSIZE * 2], prop[TSIZE * 2]; 4 | void seg_init(int nod, int l, int r) { 5 | if (l == r) segtree[nod] = dat[l]; 6 | else { 7 | int m = (l + r) >> 1; 8 | seg_init(nod << 1, l, m); 9 | seg_init(nod << 1 | 1, m + 1, r); 10 | segtree[nod] = segtree[nod << 1] + segtree[nod << 1 | 1]; 11 | } 12 | } 13 | void seg_relax(int nod, int l, int r) { 14 | if (prop[nod] == 0) return; 15 | if (l < r) { 16 | int m = (l + r) >> 1; 17 | segtree[nod << 1] += (m - l + 1) * prop[nod]; 18 | prop[nod << 1] += prop[nod]; 19 | segtree[nod << 1 | 1] += (r - m) * prop[nod]; 20 | prop[nod << 1 | 1] += prop[nod]; 21 | } 22 | prop[nod] = 0; 23 | } 24 | int seg_query(int nod, int l, int r, int s, int e) { 25 | if (r < s || e < l) return 0; 26 | if (s <= l && r <= e) return segtree[nod]; 27 | seg_relax(nod, l, r); 28 | int m = (l + r) >> 1; 29 | return seg_query(nod << 1, l, m, s, e) + seg_query(nod << 1 | 1, m + 1, r, s, e); 30 | } 31 | void seg_update(int nod, int l, int r, int s, int e, int val) { 32 | if (r < s || e < l) return; 33 | if (s <= l && r <= e) { 34 | segtree[nod] += (r - l + 1) * val; 35 | prop[nod] += val; 36 | return; 37 | } 38 | seg_relax(nod, l, r); 39 | int m = (l + r) >> 1; 40 | seg_update(nod << 1, l, m, s, e, val); 41 | seg_update(nod << 1 | 1, m + 1, r, s, e, val); 42 | segtree[nod] = segtree[nod << 1] + segtree[nod << 1 | 1]; 43 | } 44 | // usage: 45 | // seg_update(1, 0, n - 1, qs, qe, val); 46 | // seg_query(1, 0, n - 1, qs, qe); 47 | -------------------------------------------------------------------------------- /src/data-structure/splay-tree.cpp: -------------------------------------------------------------------------------- 1 | // example : https://www.acmicpc.net/problem/13159 2 | struct node { 3 | node* l, * r, * p; 4 | int cnt, min, max, val; 5 | long long sum; 6 | bool inv; 7 | node(int _val) : 8 | cnt(1), sum(_val), min(_val), max(_val), val(_val), inv(false), 9 | l(nullptr), r(nullptr), p(nullptr) { 10 | } 11 | }; 12 | node* root; 13 | 14 | void update(node* x) { 15 | x->cnt = 1; 16 | x->sum = x->min = x->max = x->val; 17 | if (x->l) { 18 | x->cnt += x->l->cnt; 19 | x->sum += x->l->sum; 20 | x->min = min(x->min, x->l->min); 21 | x->max = max(x->max, x->l->max); 22 | } 23 | if (x->r) { 24 | x->cnt += x->r->cnt; 25 | x->sum += x->r->sum; 26 | x->min = min(x->min, x->r->min); 27 | x->max = max(x->max, x->r->max); 28 | } 29 | } 30 | 31 | void rotate(node* x) { 32 | node* p = x->p; 33 | node* b = nullptr; 34 | if (x == p->l) { 35 | p->l = b = x->r; 36 | x->r = p; 37 | } 38 | else { 39 | p->r = b = x->l; 40 | x->l = p; 41 | } 42 | x->p = p->p; 43 | p->p = x; 44 | if (b) b->p = p; 45 | x->p ? (p == x->p->l ? x->p->l : x->p->r) = x : (root = x); 46 | update(p); 47 | update(x); 48 | } 49 | 50 | // make x into root 51 | void splay(node* x) { 52 | while (x->p) { 53 | node* p = x->p; 54 | node* g = p->p; 55 | if (g) rotate((x == p->l) == (p == g->l) ? p : x); 56 | rotate(x); 57 | } 58 | } 59 | 60 | void relax_lazy(node* x) { 61 | if (!x->inv) return; 62 | swap(x->l, x->r); 63 | x->inv = false; 64 | if (x->l) x->l->inv = !x->l->inv; 65 | if (x->r) x->r->inv = !x->r->inv; 66 | } 67 | 68 | // find kth node in splay tree 69 | void find_kth(int k) { 70 | node* x = root; 71 | relax_lazy(x); 72 | while (true) { 73 | while (x->l && x->l->cnt > k) { 74 | x = x->l; 75 | relax_lazy(x); 76 | } 77 | if (x->l) k -= x->l->cnt; 78 | if (!k--) break; 79 | x = x->r; 80 | relax_lazy(x); 81 | } 82 | splay(x); 83 | } 84 | 85 | // collect [l, r] nodes into one subtree and return its root 86 | node* interval(int l, int r) { 87 | find_kth(l - 1); 88 | node* x = root; 89 | root = x->r; 90 | root->p = nullptr; 91 | find_kth(r - l + 1); 92 | x->r = root; 93 | root->p = x; 94 | root = x; 95 | return root->r->l; 96 | } 97 | 98 | void traverse(node* x) { 99 | relax_lazy(x); 100 | if (x->l) { 101 | traverse(x->l); 102 | } 103 | // do something 104 | if (x->r) { 105 | traverse(x->r); 106 | } 107 | } 108 | 109 | void uptree(node* x) { 110 | if (x->p) { 111 | uptree(x->p); 112 | } 113 | relax_lazy(x); 114 | } 115 | -------------------------------------------------------------------------------- /src/geometry/basic-operations.cpp: -------------------------------------------------------------------------------- 1 | const double eps = 1e-9; 2 | 3 | inline int diff(double lhs, double rhs) { 4 | if (lhs - eps < rhs && rhs < lhs + eps) return 0; 5 | return (lhs < rhs) ? -1 : 1; 6 | } 7 | 8 | inline bool is_between(double check, double a, double b) { 9 | if (a < b) 10 | return (a - eps < check && check < b + eps); 11 | else 12 | return (b - eps < check && check < a + eps); 13 | } 14 | 15 | struct Point { 16 | double x, y; 17 | bool operator==(const Point& rhs) const { 18 | return diff(x, rhs.x) == 0 && diff(y, rhs.y) == 0; 19 | } 20 | Point operator+(const Point& rhs) const { 21 | return Point{ x + rhs.x, y + rhs.y }; 22 | } 23 | Point operator-(const Point& rhs) const { 24 | return Point{ x - rhs.x, y - rhs.y }; 25 | } 26 | Point operator*(double t) const { 27 | return Point{ x * t, y * t }; 28 | } 29 | }; 30 | 31 | struct Circle { 32 | Point center; 33 | double r; 34 | }; 35 | 36 | struct Line { 37 | Point pos, dir; 38 | }; 39 | 40 | inline double inner(const Point& a, const Point& b) { 41 | return a.x * b.x + a.y * b.y; 42 | } 43 | 44 | inline double outer(const Point& a, const Point& b) { 45 | return a.x * b.y - a.y * b.x; 46 | } 47 | 48 | inline int ccw_line(const Line& line, const Point& point) { 49 | return diff(outer(line.dir, point - line.pos), 0); 50 | } 51 | 52 | inline int ccw(const Point& a, const Point& b, const Point& c) { 53 | return diff(outer(b - a, c - a), 0); 54 | } 55 | 56 | inline double dist(const Point& a, const Point& b) { 57 | return sqrt(inner(a - b, a - b)); 58 | } 59 | 60 | inline double dist2(const Point &a, const Point &b) { 61 | return inner(a - b, a - b); 62 | } 63 | 64 | inline double dist(const Line& line, const Point& point, bool segment = false) { 65 | double c1 = inner(point - line.pos, line.dir); 66 | if (segment && diff(c1, 0) <= 0) return dist(line.pos, point); 67 | double c2 = inner(line.dir, line.dir); 68 | if (segment && diff(c2, c1) <= 0) return dist(line.pos + line.dir, point); 69 | return dist(line.pos + line.dir * (c1 / c2), point); 70 | } 71 | 72 | bool get_cross(const Line& a, const Line& b, Point& ret) { 73 | double mdet = outer(b.dir, a.dir); 74 | if (diff(mdet, 0) == 0) return false; 75 | double t2 = outer(a.dir, b.pos - a.pos) / mdet; 76 | ret = b.pos + b.dir * t2; 77 | return true; 78 | } 79 | 80 | bool get_segment_cross(const Line& a, const Line& b, Point& ret) { 81 | double mdet = outer(b.dir, a.dir); 82 | if (diff(mdet, 0) == 0) return false; 83 | double t1 = -outer(b.pos - a.pos, b.dir) / mdet; 84 | double t2 = outer(a.dir, b.pos - a.pos) / mdet; 85 | if (!is_between(t1, 0, 1) || !is_between(t2, 0, 1)) return false; 86 | ret = b.pos + b.dir * t2; 87 | return true; 88 | } 89 | 90 | Point inner_center(const Point &a, const Point &b, const Point &c) { 91 | double wa = dist(b, c), wb = dist(c, a), wc = dist(a, b); 92 | double w = wa + wb + wc; 93 | return Point{ (wa * a.x + wb * b.x + wc * c.x) / w, (wa * a.y + wb * b.y + wc * c.y) / w }; 94 | } 95 | 96 | Point outer_center(const Point &a, const Point &b, const Point &c) { 97 | Point d1 = b - a, d2 = c - a; 98 | double area = outer(d1, d2); 99 | double dx = d1.x * d1.x * d2.y - d2.x * d2.x * d1.y 100 | + d1.y * d2.y * (d1.y - d2.y); 101 | double dy = d1.y * d1.y * d2.x - d2.y * d2.y * d1.x 102 | + d1.x * d2.x * (d1.x - d2.y); 103 | return Point{ a.x + dx / area / 2.0, a.y - dy / area / 2.0 }; 104 | } 105 | 106 | vector circle_line(const Circle& circle, const Line& line) { 107 | vector result; 108 | double a = 2 * inner(line.dir, line.dir); 109 | double b = 2 * (line.dir.x * (line.pos.x - circle.center.x) 110 | + line.dir.y * (line.pos.y - circle.center.y)); 111 | double c = inner(line.pos - circle.center, line.pos - circle.center) 112 | - circle.r * circle.r; 113 | double det = b * b - 2 * a * c; 114 | int pred = diff(det, 0); 115 | if (pred == 0) 116 | result.push_back(line.pos + line.dir * (-b / a)); 117 | else if (pred > 0) { 118 | det = sqrt(det); 119 | result.push_back(line.pos + line.dir * ((-b + det) / a)); 120 | result.push_back(line.pos + line.dir * ((-b - det) / a)); 121 | } 122 | return result; 123 | } 124 | 125 | vector circle_circle(const Circle& a, const Circle& b) { 126 | vector result; 127 | int pred = diff(dist(a.center, b.center), a.r + b.r); 128 | if (pred > 0) return result; 129 | if (pred == 0) { 130 | result.push_back((a.center * b.r + b.center * a.r) * (1 / (a.r + b.r))); 131 | return result; 132 | } 133 | double aa = a.center.x * a.center.x + a.center.y * a.center.y - a.r * a.r; 134 | double bb = b.center.x * b.center.x + b.center.y * b.center.y - b.r * b.r; 135 | double tmp = (bb - aa) / 2.0; 136 | Point cdiff = b.center - a.center; 137 | if (diff(cdiff.x, 0) == 0) { 138 | if (diff(cdiff.y, 0) == 0) 139 | return result; // if (diff(a.r, b.r) == 0): same circle 140 | return circle_line(a, Line{ Point{ 0, tmp / cdiff.y }, Point{ 1, 0 } }); 141 | } 142 | return circle_line(a, 143 | Line{ Point{ tmp / cdiff.x, 0 }, Point{ -cdiff.y, cdiff.x } }); 144 | } 145 | 146 | Circle circle_from_3pts(const Point& a, const Point& b, const Point& c) { 147 | Point ba = b - a, cb = c - b; 148 | Line p{ (a + b) * 0.5, Point{ ba.y, -ba.x } }; 149 | Line q{ (b + c) * 0.5, Point{ cb.y, -cb.x } }; 150 | Circle circle; 151 | if (!get_cross(p, q, circle.center)) 152 | circle.r = -1; 153 | else 154 | circle.r = dist(circle.center, a); 155 | return circle; 156 | } 157 | 158 | Circle circle_from_2pts_rad(const Point& a, const Point& b, double r) { 159 | double det = r * r / dist2(a, b) - 0.25; 160 | Circle circle; 161 | if (det < 0) 162 | circle.r = -1; 163 | else { 164 | double h = sqrt(det); 165 | // center is to the left of a->b 166 | circle.center = (a + b) * 0.5 + Point{ a.y - b.y, b.x - a.x } * h; 167 | circle.r = r; 168 | } 169 | return circle; 170 | } 171 | -------------------------------------------------------------------------------- /src/geometry/convex-hull.cpp: -------------------------------------------------------------------------------- 1 | // find convex hull 2 | // O(n*logn) 3 | vector convex_hull(vector& dat) { 4 | if (dat.size() <= 3) return dat; 5 | vector upper, lower; 6 | sort(dat.begin(), dat.end(), [](const Point& a, const Point& b) { 7 | return (a.x == b.x) ? a.y < b.y : a.x < b.x; 8 | }); 9 | for (const auto& p : dat) { 10 | while (upper.size() >= 2 && ccw(*++upper.rbegin(), *upper.rbegin(), p) >= 0) upper.pop_back(); 11 | while (lower.size() >= 2 && ccw(*++lower.rbegin(), *lower.rbegin(), p) <= 0) lower.pop_back(); 12 | upper.emplace_back(p); 13 | lower.emplace_back(p); 14 | } 15 | upper.insert(upper.end(), ++lower.rbegin(), --lower.rend()); 16 | return upper; 17 | } 18 | -------------------------------------------------------------------------------- /src/geometry/point-in-polygon.cpp: -------------------------------------------------------------------------------- 1 | typedef double coord_t; 2 | 3 | inline coord_t is_left(Point p0, Point p1, Point p2) { 4 | return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y); 5 | } 6 | 7 | // point in polygon test 8 | // http://geomalgorithms.com/a03-_inclusion.html 9 | bool is_in_polygon(Point p, vector& poly) { 10 | int wn = 0; 11 | for (int i = 0; i < poly.size(); ++i) { 12 | int ni = (i + 1 == poly.size()) ? 0 : i + 1; 13 | if (poly[i].y <= p.y) { 14 | if (poly[ni].y > p.y) { 15 | if (is_left(poly[i], poly[ni], p) > 0) { 16 | ++wn; 17 | } 18 | } 19 | } 20 | else { 21 | if (poly[ni].y <= p.y) { 22 | if (is_left(poly[i], poly[ni], p) < 0) { 23 | --wn; 24 | } 25 | } 26 | } 27 | } 28 | return wn != 0; 29 | } 30 | -------------------------------------------------------------------------------- /src/geometry/polygon-cut.cpp: -------------------------------------------------------------------------------- 1 | // left side of a->b 2 | vector cut_polygon(const vector& polygon, Line line) { 3 | if (!polygon.size()) return polygon; 4 | typedef vector::const_iterator piter; 5 | piter la, lan, fi, fip, i, j; 6 | la = lan = fi = fip = polygon.end(); 7 | i = polygon.end() - 1; 8 | bool lastin = diff(ccw_line(line, polygon[polygon.size() - 1]), 0) > 0; 9 | for (j = polygon.begin() ; j != polygon.end() ; j++) { 10 | bool thisin = diff(ccw_line(line, *j), 0) > 0; 11 | if (lastin && !thisin) { 12 | la = i; 13 | lan = j; 14 | } 15 | if (!lastin && thisin) { 16 | fi = j; 17 | fip = i; 18 | } 19 | i = j; 20 | lastin = thisin; 21 | } 22 | if (fi == polygon.end()) { 23 | if (!lastin) return vector(); 24 | return polygon; 25 | } 26 | vector result; 27 | for (i = fi ; i != lan ; i++) { 28 | if (i == polygon.end()) { 29 | i = polygon.begin(); 30 | if (i == lan) break; 31 | } 32 | result.push_back(*i); 33 | } 34 | Point lc, fc; 35 | get_cross(Line{ *la, *lan - *la }, line, lc); 36 | get_cross(Line{ *fip, *fi - *fip }, line, fc); 37 | result.push_back(lc); 38 | if (diff(dist2(lc, fc), 0) != 0) result.push_back(fc); 39 | return result; 40 | } 41 | -------------------------------------------------------------------------------- /src/geometry/rotating-calipers.cpp: -------------------------------------------------------------------------------- 1 | // get all antipodal pairs 2 | // O(n) 3 | void antipodal_pairs(vector& pt) { 4 | // calculate convex hull 5 | sort(pt.begin(), pt.end(), [](const Point& a, const Point& b) { 6 | return (a.x == b.x) ? a.y < b.y : a.x < b.x; 7 | }); 8 | vector up, lo; 9 | for (const auto& p : pt) { 10 | while (up.size() >= 2 && ccw(*++up.rbegin(), *up.rbegin(), p) >= 0) up.pop_back(); 11 | while (lo.size() >= 2 && ccw(*++lo.rbegin(), *lo.rbegin(), p) <= 0) lo.pop_back(); 12 | up.emplace_back(p); 13 | lo.emplace_back(p); 14 | } 15 | 16 | for (int i = 0, j = (int)lo.size() - 1; i + 1 < up.size() || j > 0; ) { 17 | get_pair(up[i], lo[j]); // DO WHAT YOU WANT 18 | if (i + 1 == up.size()) { 19 | --j; 20 | } 21 | else if (j == 0) { 22 | ++i; 23 | } 24 | else if ((long long)(up[i + 1].y - up[i].y) * (lo[j].x - lo[j - 1].x) 25 | > (long long)(up[i + 1].x - up[i].x) * (lo[j].y - lo[j - 1].y)) { 26 | ++i; 27 | } 28 | else { 29 | --j; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/graph/bcc.cpp: -------------------------------------------------------------------------------- 1 | const int MAXN = 100; 2 | vector> graph[MAXN]; // { next vertex id, edge id } 3 | int up[MAXN], visit[MAXN], vtime; 4 | vector stk; 5 | 6 | int is_cut[MAXN]; // v is cut vertex if is_cut[v] > 0 7 | vector bridge; // list of edge ids 8 | vector bcc_edges[MAXN]; // list of edge ids in a bcc 9 | int bcc_cnt; 10 | 11 | void dfs(int nod, int par_edge) { 12 | up[nod] = visit[nod] = ++vtime; 13 | int child = 0; 14 | for (const auto& e : graph[nod]) { 15 | int next = e.first, eid = e.second; 16 | if (eid == par_edge) continue; 17 | if (visit[next] == 0) { 18 | stk.push_back(eid); 19 | ++child; 20 | dfs(next, eid); 21 | if (up[next] == visit[next]) bridge.push_back(eid); 22 | if (up[next] >= visit[nod]) { 23 | ++bcc_cnt; 24 | do { 25 | auto lasteid = stk.back(); 26 | stk.pop_back(); 27 | bcc_edges[bcc_cnt].push_back(lasteid); 28 | if (lasteid == eid) break; 29 | } while (!stk.empty()); 30 | is_cut[nod]++; 31 | } 32 | up[nod] = min(up[nod], up[next]); 33 | } 34 | else if (visit[next] < visit[nod]) { 35 | stk.push_back(eid); 36 | up[nod] = min(up[nod], visit[next]); 37 | } 38 | } 39 | if (par_edge == -1 && is_cut[nod] == 1) 40 | is_cut[nod] = 0; 41 | } 42 | 43 | // find BCCs & cut vertexs & bridges in undirected graph 44 | // O(V+E) 45 | void get_bcc() { 46 | vtime = 0; 47 | memset(visit, 0, sizeof(visit)); 48 | memset(is_cut, 0, sizeof(is_cut)); 49 | bridge.clear(); 50 | for (int i = 0; i < n; ++i) bcc_edges[i].clear(); 51 | bcc_cnt = 0; 52 | for (int i = 0; i < n; ++i) { 53 | if (visit[i] == 0) 54 | dfs(i, -1); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/graph/bipartite-matching-hopcroft.cpp: -------------------------------------------------------------------------------- 1 | // in: n, m, graph 2 | // out: match, matched 3 | // vertex cover: (reached[0][left_node] == 0) || (reached[1][right_node] == 1) 4 | // O(E*sqrt(V)) 5 | struct BipartiteMatching { 6 | int n, m; 7 | vector> graph; 8 | vector matched, match, edgeview, level; 9 | vector reached[2]; 10 | BipartiteMatching(int n, int m) : n(n), m(m), graph(n), matched(m, -1), match(n, -1) {} 11 | 12 | bool assignLevel() { 13 | bool reachable = false; 14 | level.assign(n, -1); 15 | reached[0].assign(n, 0); 16 | reached[1].assign(m, 0); 17 | queue q; 18 | for (int i = 0; i < n; i++) { 19 | if (match[i] == -1) { 20 | level[i] = 0; 21 | reached[0][i] = 1; 22 | q.push(i); 23 | } 24 | } 25 | while (!q.empty()) { 26 | auto cur = q.front(); q.pop(); 27 | for (auto adj : graph[cur]) { 28 | reached[1][adj] = 1; 29 | auto next = matched[adj]; 30 | if (next == -1) { 31 | reachable = true; 32 | } 33 | else if (level[next] == -1) { 34 | level[next] = level[cur] + 1; 35 | reached[0][next] = 1; 36 | q.push(next); 37 | } 38 | } 39 | } 40 | return reachable; 41 | } 42 | 43 | int findpath(int nod) { 44 | for (int &i = edgeview[nod]; i < graph[nod].size(); i++) { 45 | int adj = graph[nod][i]; 46 | int next = matched[adj]; 47 | if (next >= 0 && level[next] != level[nod] + 1) continue; 48 | if (next == -1 || findpath(next)) { 49 | match[nod] = adj; 50 | matched[adj] = nod; 51 | return 1; 52 | } 53 | } 54 | return 0; 55 | } 56 | 57 | int solve() { 58 | int ans = 0; 59 | while (assignLevel()) { 60 | edgeview.assign(n, 0); 61 | for (int i = 0; i < n; i++) 62 | if (match[i] == -1) 63 | ans += findpath(i); 64 | } 65 | return ans; 66 | } 67 | }; 68 | -------------------------------------------------------------------------------- /src/graph/general-mincut-stoer-wagner.cpp: -------------------------------------------------------------------------------- 1 | // implementation of Stoer-Wagner algorithm 2 | // O(V^3) 3 | //usage 4 | // MinCut mc; 5 | // mc.init(n); 6 | // for (each edge) mc.addEdge(a,b,weight); 7 | // mincut = mc.solve(); 8 | // mc.cut = {0,1}^n describing which side the vertex belongs to. 9 | struct MinCutMatrix 10 | { 11 | typedef int cap_t; 12 | int n; 13 | vector> graph; 14 | 15 | void init(int _n) { 16 | n = _n; 17 | graph = vector>(n, vector(n, 0)); 18 | } 19 | void addEdge(int a, int b, cap_t w) { 20 | if (a == b) return; 21 | graph[a][b] += w; 22 | graph[b][a] += w; 23 | } 24 | 25 | pair> stMinCut(vector &active) { 26 | vector key(n); 27 | vector v(n); 28 | int s = -1, t = -1; 29 | for (int i = 0; i < active.size(); i++) { 30 | cap_t maxv = -1; 31 | int cur = -1; 32 | for (auto j : active) { 33 | if (v[j] == 0 && maxv < key[j]) { 34 | maxv = key[j]; 35 | cur = j; 36 | } 37 | } 38 | t = s; s = cur; 39 | v[cur] = 1; 40 | for (auto j : active) key[j] += graph[cur][j]; 41 | } 42 | return make_pair(key[s], make_pair(s, t)); 43 | } 44 | 45 | vector cut; 46 | 47 | cap_t solve() { 48 | cap_t res = numeric_limits::max(); 49 | vector> grps; 50 | vector active; 51 | cut.resize(n); 52 | for (int i = 0; i < n; i++) grps.emplace_back(1, i); 53 | for (int i = 0; i < n; i++) active.push_back(i); 54 | while (active.size() >= 2) { 55 | auto stcut = stMinCut(active); 56 | if (stcut.first < res) { 57 | res = stcut.first; 58 | fill(cut.begin(), cut.end(), 0); 59 | for (auto v : grps[stcut.second.first]) cut[v] = 1; 60 | } 61 | 62 | int s = stcut.second.first, t = stcut.second.second; 63 | if (grps[s].size() < grps[t].size()) swap(s, t); 64 | 65 | active.erase(find(active.begin(), active.end(), t)); 66 | grps[s].insert(grps[s].end(), grps[t].begin(), grps[t].end()); 67 | for (int i = 0; i < n; i++) { graph[i][s] += graph[i][t]; graph[i][t] = 0; } 68 | for (int i = 0; i < n; i++) { graph[s][i] += graph[t][i]; graph[t][i] = 0; } 69 | graph[s][s] = 0; 70 | } 71 | return res; 72 | } 73 | }; 74 | -------------------------------------------------------------------------------- /src/graph/hld.cpp: -------------------------------------------------------------------------------- 1 | // heavy-light decomposition 2 | // 3 | // hld h; 4 | // insert edges to tree[0~n-1]; 5 | // h.init(n, root); 6 | // h.decompose(root); 7 | // h.hldquery(u, v); // edges from u to v 8 | struct hld { 9 | static const int MAXLN = 18; 10 | static const int MAXN = 1 << (MAXLN - 1); 11 | vector tree[MAXN]; 12 | int subsize[MAXN], depth[MAXN], pa[MAXLN][MAXN]; 13 | 14 | int chead[MAXN], cidx[MAXN]; 15 | int lchain; 16 | int flatpos[MAXN + 1], fptr; 17 | 18 | void dfs(int u, int par) { 19 | pa[0][u] = par; 20 | subsize[u] = 1; 21 | for (int v : tree[u]) { 22 | if (v == pa[0][u]) continue; 23 | depth[v] = depth[u] + 1; 24 | dfs(v, u); 25 | subsize[u] += subsize[v]; 26 | } 27 | } 28 | 29 | void init(int size, int root) 30 | { 31 | lchain = fptr = 0; 32 | dfs(root, -1); 33 | memset(chead, -1, sizeof(chead)); 34 | 35 | for (int i = 1; i < MAXLN; i++) { 36 | for (int j = 0; j < size; j++) { 37 | if (pa[i - 1][j] != -1) { 38 | pa[i][j] = pa[i - 1][pa[i - 1][j]]; 39 | } 40 | } 41 | } 42 | } 43 | 44 | void decompose(int u) { 45 | if (chead[lchain] == -1) chead[lchain] = u; 46 | cidx[u] = lchain; 47 | flatpos[u] = ++fptr; 48 | 49 | int maxchd = -1; 50 | for (int v : tree[u]) { 51 | if (v == pa[0][u]) continue; 52 | if (maxchd == -1 || subsize[maxchd] < subsize[v]) maxchd = v; 53 | } 54 | if (maxchd != -1) decompose(maxchd); 55 | 56 | for (int v : tree[u]) { 57 | if (v == pa[0][u] || v == maxchd) continue; 58 | ++lchain; decompose(v); 59 | } 60 | } 61 | 62 | int lca(int u, int v) { 63 | if (depth[u] < depth[v]) swap(u, v); 64 | 65 | int logu; 66 | for (logu = 1; 1 << logu <= depth[u]; logu++); 67 | logu--; 68 | 69 | int diff = depth[u] - depth[v]; 70 | for (int i = logu; i >= 0; --i) { 71 | if ((diff >> i) & 1) u = pa[i][u]; 72 | } 73 | if (u == v) return u; 74 | 75 | for (int i = logu; i >= 0; --i) { 76 | if (pa[i][u] != pa[i][v]) { 77 | u = pa[i][u]; 78 | v = pa[i][v]; 79 | } 80 | } 81 | return pa[0][u]; 82 | } 83 | 84 | // TODO: implement query functions 85 | inline int query(int s, int e) { 86 | return 0; 87 | } 88 | 89 | int subquery(int u, int v) { 90 | int uchain, vchain = cidx[v]; 91 | int ret = 0; 92 | for (;;) { 93 | uchain = cidx[u]; 94 | if (uchain == vchain) { 95 | ret += query(flatpos[v], flatpos[u]); 96 | break; 97 | } 98 | 99 | ret += query(flatpos[chead[uchain]], flatpos[u]); 100 | u = pa[0][chead[uchain]]; 101 | } 102 | return ret; 103 | } 104 | 105 | inline int hldquery(int u, int v) { 106 | int p = lca(u, v); 107 | return subquery(u, p) + subquery(v, p) - query(flatpos[p], flatpos[p]); 108 | } 109 | }; 110 | 111 | -------------------------------------------------------------------------------- /src/graph/hungarian.cpp: -------------------------------------------------------------------------------- 1 | int n, m; 2 | int mat[MAX_N + 1][MAX_M + 1]; 3 | 4 | // hungarian method : bipartite min-weighted matching 5 | // O(n^3) or O(m*n^2) 6 | // http://e-maxx.ru/algo/assignment_hungary 7 | // mat[1][1] ~ mat[n][m] 8 | // matched[i] : matched column of row i 9 | int hungarian(vector& matched) { 10 | vector u(n + 1), v(m + 1), p(m + 1), way(m + 1), minv(m + 1); 11 | vector used(m + 1); 12 | for (int i = 1; i <= n; ++i) { 13 | p[0] = i; 14 | int j0 = 0; 15 | fill(minv.begin(), minv.end(), INF); 16 | fill(used.begin(), used.end(), false); 17 | do { 18 | used[j0] = true; 19 | int i0 = p[j0], delta = INF, j1; 20 | for (int j = 1; j <= m; ++j) { 21 | if (!used[j]) { 22 | int cur = mat[i0][j] - u[i0] - v[j]; 23 | if (cur < minv[j]) minv[j] = cur, way[j] = j0; 24 | if (minv[j] < delta) delta = minv[j], j1 = j; 25 | } 26 | } 27 | for (int j = 0; j <= m; ++j) { 28 | if (used[j]) 29 | u[p[j]] += delta, v[j] -= delta; 30 | else 31 | minv[j] -= delta; 32 | } 33 | j0 = j1; 34 | } while (p[j0] != 0); 35 | do { 36 | int j1 = way[j0]; 37 | p[j0] = p[j1]; 38 | j0 = j1; 39 | } while (j0); 40 | } 41 | for (int j = 1; j <= m; ++j) matched[p[j]] = j; 42 | return -v[0]; 43 | } 44 | -------------------------------------------------------------------------------- /src/graph/lca.cpp: -------------------------------------------------------------------------------- 1 | const int MAXN = 100; 2 | const int MAXLN = 9; 3 | vector tree[MAXN]; 4 | int depth[MAXN]; 5 | int par[MAXLN][MAXN]; 6 | 7 | void dfs(int nod, int parent) { 8 | for (int next : tree[nod]) { 9 | if (next == parent) continue; 10 | depth[next] = depth[nod] + 1; 11 | par[0][next] = nod; 12 | dfs(next, nod); 13 | } 14 | } 15 | 16 | void prepare_lca() { 17 | const int root = 0; 18 | dfs(root, -1); 19 | par[0][root] = root; 20 | for (int i = 1; i < MAXLN; ++i) 21 | for (int j = 0; j < n; ++j) 22 | par[i][j] = par[i - 1][par[i - 1][j]]; 23 | } 24 | 25 | // find lowest common ancestor in tree between u & v 26 | // assumption : must call 'prepare_lca' once before call this 27 | // O(logV) 28 | int lca(int u, int v) { 29 | if (depth[u] < depth[v]) swap(u, v); 30 | if (depth[u] > depth[v]) { 31 | for (int i = MAXLN - 1; i >= 0; --i) 32 | if (depth[u] - (1 << i) >= depth[v]) 33 | u = par[i][u]; 34 | } 35 | if (u == v) return u; 36 | for (int i = MAXLN - 1; i >= 0; --i) { 37 | if (par[i][u] != par[i][v]) { 38 | u = par[i][u]; 39 | v = par[i][v]; 40 | } 41 | } 42 | return par[0][u]; 43 | } 44 | -------------------------------------------------------------------------------- /src/graph/maxflow-dinic.cpp: -------------------------------------------------------------------------------- 1 | // usage: 2 | // MaxFlowDinic::init(n); 3 | // MaxFlowDinic::add_edge(0, 1, 100, 100); // for bidirectional edge 4 | // MaxFlowDinic::add_edge(1, 2, 100); // directional edge 5 | // result = MaxFlowDinic::solve(0, 2); // source -> sink 6 | // graph[i][edgeIndex].res -> residual 7 | // 8 | // in order to find out the minimum cut, use `l'. 9 | // if l[i] == 0, i is unrechable. 10 | // 11 | // O(V*V*E) 12 | // with unit capacities, O(min(V^(2/3), E^(1/2)) * E) 13 | struct MaxFlowDinic { 14 | typedef int flow_t; 15 | struct Edge { 16 | int next; 17 | size_t inv; /* inverse edge index */ 18 | flow_t res; /* residual */ 19 | }; 20 | int n; 21 | vector> graph; 22 | vector q, l, start; 23 | 24 | void init(int _n) { 25 | n = _n; 26 | graph.resize(n); 27 | for (int i = 0; i < n; i++) graph[i].clear(); 28 | } 29 | void add_edge(int s, int e, flow_t cap, flow_t caprev = 0) { 30 | Edge forward{ e, graph[e].size(), cap }; 31 | Edge reverse{ s, graph[s].size(), caprev }; 32 | graph[s].push_back(forward); 33 | graph[e].push_back(reverse); 34 | } 35 | bool assign_level(int source, int sink) { 36 | int t = 0; 37 | memset(&l[0], 0, sizeof(l[0]) * l.size()); 38 | l[source] = 1; 39 | q[t++] = source; 40 | for (int h = 0; h < t && !l[sink]; h++) { 41 | int cur = q[h]; 42 | for (const auto& e : graph[cur]) { 43 | if (l[e.next] || e.res == 0) continue; 44 | l[e.next] = l[cur] + 1; 45 | q[t++] = e.next; 46 | } 47 | } 48 | return l[sink] != 0; 49 | } 50 | flow_t block_flow(int cur, int sink, flow_t current) { 51 | if (cur == sink) return current; 52 | for (int& i = start[cur]; i < graph[cur].size(); i++) { 53 | auto& e = graph[cur][i]; 54 | if (e.res == 0 || l[e.next] != l[cur] + 1) continue; 55 | if (flow_t res = block_flow(e.next, sink, min(e.res, current))) { 56 | e.res -= res; 57 | graph[e.next][e.inv].res += res; 58 | return res; 59 | } 60 | } 61 | return 0; 62 | } 63 | flow_t solve(int source, int sink) { 64 | q.resize(n); 65 | l.resize(n); 66 | start.resize(n); 67 | flow_t ans = 0; 68 | while (assign_level(source, sink)) { 69 | memset(&start[0], 0, sizeof(start[0]) * n); 70 | while (flow_t flow = block_flow(source, sink, numeric_limits::max())) 71 | ans += flow; 72 | } 73 | return ans; 74 | } 75 | }; 76 | -------------------------------------------------------------------------------- /src/graph/maxflow-ed.cpp: -------------------------------------------------------------------------------- 1 | struct MaxFlowEdgeDemands 2 | { 3 | MaxFlowDinic mf; 4 | using flow_t = MaxFlowDinic::flow_t; 5 | 6 | vector ind, outd; 7 | flow_t D; int n; 8 | 9 | void init(int _n) { 10 | n = _n; D = 0; mf.init(n + 2); 11 | ind.clear(); outd.clear(); 12 | ind.resize(n, 0); outd.resize(n, 0); 13 | } 14 | 15 | void add_edge(int s, int e, flow_t cap, flow_t demands = 0) { 16 | mf.add_edge(s, e, cap - demands); 17 | D += demands; ind[e] += demands; outd[s] += demands; 18 | } 19 | 20 | // returns { false, 0 } if infeasible 21 | // { true, maxflow } if feasible 22 | pair solve(int source, int sink) { 23 | mf.add_edge(sink, source, numeric_limits::max()); 24 | 25 | for (int i = 0; i < n; i++) { 26 | if (ind[i]) mf.add_edge(n, i, ind[i]); 27 | if (outd[i]) mf.add_edge(i, n + 1, outd[i]); 28 | } 29 | 30 | if (mf.solve(n, n + 1) != D) return{ false, 0 }; 31 | 32 | for (int i = 0; i < n; i++) { 33 | if (ind[i]) mf.graph[i].pop_back(); 34 | if (outd[i]) mf.graph[i].pop_back(); 35 | } 36 | 37 | return{ true, mf.solve(source, sink) }; 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /src/graph/mcmf.cpp: -------------------------------------------------------------------------------- 1 | // precondition: there is no negative cycle. 2 | // usage: 3 | // MinCostFlow mcf(n); 4 | // for(each edges) mcf.addEdge(from, to, cost, capacity); 5 | // mcf.solve(source, sink); // min cost max flow 6 | // mcf.solve(source, sink, 0); // min cost flow 7 | // mcf.solve(source, sink, goal_flow); // min cost flow with total_flow >= goal_flow if possible 8 | struct MinCostFlow { 9 | typedef int cap_t; 10 | typedef int cost_t; 11 | 12 | bool iszerocap(cap_t cap) { return cap == 0; } 13 | 14 | struct edge { 15 | int target; 16 | cost_t cost; 17 | cap_t residual_capacity; 18 | cap_t orig_capacity; 19 | size_t revid; 20 | }; 21 | 22 | int n; 23 | vector> graph; 24 | 25 | MinCostFlow(int n) : graph(n), n(n) {} 26 | 27 | void addEdge(int s, int e, cost_t cost, cap_t cap) { 28 | if (s == e) return; 29 | edge forward{ e, cost, cap, cap, graph[e].size() }; 30 | edge backward{ s, -cost, 0, 0, graph[s].size() }; 31 | graph[s].emplace_back(forward); 32 | graph[e].emplace_back(backward); 33 | } 34 | 35 | pair augmentShortest(int s, int e, cap_t flow_limit) { 36 | auto infinite_cost = numeric_limits::max(); 37 | auto infinite_flow = numeric_limits::max(); 38 | vector> dist(n, make_pair(infinite_cost, 0)); 39 | vector from(n, -1), v(n); 40 | 41 | dist[s] = pair(0, infinite_flow); 42 | queue q; 43 | v[s] = 1; q.push(s); 44 | while(!q.empty()) { 45 | int cur = q.front(); 46 | v[cur] = 0; q.pop(); 47 | for (const auto& e : graph[cur]) { 48 | if (iszerocap(e.residual_capacity)) continue; 49 | auto next = e.target; 50 | auto ncost = dist[cur].first + e.cost; 51 | auto nflow = min(dist[cur].second, e.residual_capacity); 52 | if (dist[next].first > ncost) { 53 | dist[next] = make_pair(ncost, nflow); 54 | from[next] = e.revid; 55 | if (v[next]) continue; 56 | v[next] = 1; q.push(next); 57 | } 58 | } 59 | } 60 | 61 | auto p = e; 62 | auto pathcost = dist[p].first; 63 | auto flow = dist[p].second; 64 | if (iszerocap(flow)|| (flow_limit <= 0 && pathcost >= 0)) return pair(0, 0); 65 | if (flow_limit > 0) flow = min(flow, flow_limit); 66 | 67 | while (from[p] != -1) { 68 | auto nedge = from[p]; 69 | auto np = graph[p][nedge].target; 70 | auto fedge = graph[p][nedge].revid; 71 | graph[p][nedge].residual_capacity += flow; 72 | graph[np][fedge].residual_capacity -= flow; 73 | p = np; 74 | } 75 | return make_pair(pathcost * flow, flow); 76 | } 77 | 78 | pair solve(int s, int e, cap_t flow_minimum = numeric_limits::max()) { 79 | cost_t total_cost = 0; 80 | cap_t total_flow = 0; 81 | for(;;) { 82 | auto res = augmentShortest(s, e, flow_minimum - total_flow); 83 | if (res.second <= 0) break; 84 | total_cost += res.first; 85 | total_flow += res.second; 86 | } 87 | return make_pair(total_cost, total_flow); 88 | } 89 | }; 90 | -------------------------------------------------------------------------------- /src/graph/scc.cpp: -------------------------------------------------------------------------------- 1 | const int MAXN = 100; 2 | vector graph[MAXN]; 3 | int up[MAXN], visit[MAXN], vtime; 4 | vector stk; 5 | int scc_idx[MAXN], scc_cnt; 6 | 7 | void dfs(int nod) { 8 | up[nod] = visit[nod] = ++vtime; 9 | stk.push_back(nod); 10 | for (int next : graph[nod]) { 11 | if (visit[next] == 0) { 12 | dfs(next); 13 | up[nod] = min(up[nod], up[next]); 14 | } 15 | else if (scc_idx[next] == 0) 16 | up[nod] = min(up[nod], visit[next]); 17 | } 18 | if (up[nod] == visit[nod]) { 19 | ++scc_cnt; 20 | int t; 21 | do { 22 | t = stk.back(); 23 | stk.pop_back(); 24 | scc_idx[t] = scc_cnt; 25 | } while (!stk.empty() && t != nod); 26 | } 27 | } 28 | 29 | // find SCCs in given directed graph 30 | // O(V+E) 31 | // the order of scc_idx constitutes a reverse topological sort 32 | void get_scc() { 33 | vtime = 0; 34 | memset(visit, 0, sizeof(visit)); 35 | scc_cnt = 0; 36 | memset(scc_idx, 0, sizeof(scc_idx)); 37 | for (int i = 0; i < n; ++i) 38 | if (visit[i] == 0) dfs(i); 39 | } 40 | -------------------------------------------------------------------------------- /src/graph/spfa.cpp: -------------------------------------------------------------------------------- 1 | // shortest path faster algorithm 2 | // average for random graph : O(E) , worst : O(VE) 3 | 4 | const int MAXN = 20001; 5 | const int INF = 100000000; 6 | int n, m; 7 | vector> graph[MAXN]; 8 | bool inqueue[MAXN]; 9 | int dist[MAXN]; 10 | 11 | void spfa(int st) { 12 | for (int i = 0; i < n; ++i) { 13 | dist[i] = INF; 14 | } 15 | dist[st] = 0; 16 | 17 | queue q; 18 | q.push(st); 19 | inqueue[st] = true; 20 | while (!q.empty()) { 21 | int u = q.front(); 22 | q.pop(); 23 | inqueue[u] = false; 24 | for (auto& e : graph[u]) { 25 | if (dist[u] + e.second < dist[e.first]) { 26 | dist[e.first] = dist[u] + e.second; 27 | if (!inqueue[e.first]) { 28 | q.push(e.first); 29 | inqueue[e.first] = true; 30 | } 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/math/basic-arithmetic.cpp: -------------------------------------------------------------------------------- 1 | typedef long long ll; 2 | typedef unsigned long long ull; 3 | 4 | // calculate lg2(a) 5 | inline int lg2(ll a) { 6 | return 63 - __builtin_clzll(a); 7 | } 8 | 9 | // calculate the number of 1-bits 10 | inline int bitcount(ll a) { 11 | return __builtin_popcountll(a); 12 | } 13 | 14 | // calculate ceil(a/b) 15 | // |a|, |b| <= (2^63)-1 (does not dover -2^63) 16 | ll ceildiv(ll a, ll b) { 17 | if (b < 0) return ceildiv(-a, -b); 18 | if (a < 0) return (-a) / b; 19 | return ((ull)a + (ull)b - 1ull) / b; 20 | } 21 | 22 | // calculate floor(a/b) 23 | // |a|, |b| <= (2^63)-1 (does not cover -2^63) 24 | ll floordiv(ll a, ll b) { 25 | if (b < 0) return floordiv(-a, -b); 26 | if (a >= 0) return a / b; 27 | return -(ll)(((ull)(-a) + b - 1) / b); 28 | } 29 | 30 | // calculate a*b % m 31 | // x86-64 only 32 | ll large_mod_mul(ll a, ll b, ll m) { 33 | return ll((__int128)a*(__int128)b%m); 34 | } 35 | 36 | // calculate a*b % m 37 | // |m| < 2^62, x86 available 38 | // O(logb) 39 | ll large_mod_mul(ll a, ll b, ll m) { 40 | a %= m; b %= m; ll r = 0, v = a; 41 | while (b) { 42 | if (b&1) r = (r + v) % m; 43 | b >>= 1; 44 | v = (v << 1) % m; 45 | } 46 | return r; 47 | } 48 | 49 | // calculate n^k % m 50 | ll modpow(ll n, ll k, ll m) { 51 | ll ret = 1; 52 | n %= m; 53 | while (k) { 54 | if (k & 1) ret = large_mod_mul(ret, n, m); 55 | n = large_mod_mul(n, n, m); 56 | k /= 2; 57 | } 58 | return ret; 59 | } 60 | 61 | // calculate gcd(a, b) 62 | ll gcd(ll a, ll b) { 63 | return b == 0 ? a : gcd(b, a % b); 64 | } 65 | 66 | // find a pair (c, d) s.t. ac + bd = gcd(a, b) 67 | pair extended_gcd(ll a, ll b) { 68 | if (b == 0) return { 1, 0 }; 69 | auto t = extended_gcd(b, a % b); 70 | return { t.second, t.first - t.second * (a / b) }; 71 | } 72 | 73 | // find x in [0,m) s.t. ax === gcd(a, m) (mod m) 74 | ll modinverse(ll a, ll m) { 75 | return (extended_gcd(a, m).first % m + m) % m; 76 | } 77 | 78 | // calculate modular inverse for 1 ~ n 79 | void calc_range_modinv(int n, int mod, int ret[]) { 80 | ret[1] = 1; 81 | for (int i = 2; i <= n; ++i) 82 | ret[i] = (ll)(mod - mod/i) * ret[mod%i] % mod; 83 | } 84 | -------------------------------------------------------------------------------- /src/math/chinese-remainder.cpp: -------------------------------------------------------------------------------- 1 | // find x s.t. x === a[0] (mod n[0]) 2 | // === a[1] (mod n[1]) 3 | // ... 4 | // assumption: gcd(n[i], n[j]) = 1 5 | ll chinese_remainder(ll* a, ll* n, int size) { 6 | if (size == 1) return *a; 7 | ll tmp = modinverse(n[0], n[1]); 8 | ll tmp2 = (tmp * (a[1] - a[0]) % n[1] + n[1]) % n[1]; 9 | ll ora = a[1]; 10 | ll tgcd = gcd(n[0], n[1]); 11 | a[1] = a[0] + n[0] / tgcd * tmp2; 12 | n[1] *= n[0] / tgcd; 13 | ll ret = chinese_remainder(a + 1, n + 1, size - 1); 14 | n[1] /= n[0] / tgcd; 15 | a[1] = ora; 16 | return ret; 17 | } 18 | -------------------------------------------------------------------------------- /src/math/fft.cpp: -------------------------------------------------------------------------------- 1 | void fft(int sign, int n, double *real, double *imag) { 2 | double theta = sign * 2 * pi / n; 3 | for (int m = n; m >= 2; m >>= 1, theta *= 2) { 4 | double wr = 1, wi = 0, c = cos(theta), s = sin(theta); 5 | for (int i = 0, mh = m >> 1; i < mh; ++i) { 6 | for (int j = i; j < n; j += m) { 7 | int k = j + mh; 8 | double xr = real[j] - real[k], xi = imag[j] - imag[k]; 9 | real[j] += real[k], imag[j] += imag[k]; 10 | real[k] = wr * xr - wi * xi, imag[k] = wr * xi + wi * xr; 11 | } 12 | double _wr = wr * c - wi * s, _wi = wr * s + wi * c; 13 | wr = _wr, wi = _wi; 14 | } 15 | } 16 | for (int i = 1, j = 0; i < n; ++i) { 17 | for (int k = n >> 1; k > (j ^= k); k >>= 1); 18 | if (j < i) swap(real[i], real[j]), swap(imag[i], imag[j]); 19 | } 20 | } 21 | // Compute Poly(a)*Poly(b), write to r; Indexed from 0 22 | // O(n*logn) 23 | int mult(int *a, int n, int *b, int m, int *r) { 24 | const int maxn = 100; 25 | static double ra[maxn], rb[maxn], ia[maxn], ib[maxn]; 26 | int fn = 1; 27 | while (fn < n + m) fn <<= 1; // n + m: interested length 28 | for (int i = 0; i < n; ++i) ra[i] = a[i], ia[i] = 0; 29 | for (int i = n; i < fn; ++i) ra[i] = ia[i] = 0; 30 | for (int i = 0; i < m; ++i) rb[i] = b[i], ib[i] = 0; 31 | for (int i = m; i < fn; ++i) rb[i] = ib[i] = 0; 32 | fft(1, fn, ra, ia); 33 | fft(1, fn, rb, ib); 34 | for (int i = 0; i < fn; ++i) { 35 | double real = ra[i] * rb[i] - ia[i] * ib[i]; 36 | double imag = ra[i] * ib[i] + rb[i] * ia[i]; 37 | ra[i] = real, ia[i] = imag; 38 | } 39 | fft(-1, fn, ra, ia); 40 | for (int i = 0; i < fn; ++i) r[i] = (int)floor(ra[i] / fn + 0.5); 41 | return fn; 42 | } 43 | -------------------------------------------------------------------------------- /src/math/gaussian.cpp: -------------------------------------------------------------------------------- 1 | const double EPS = 1e-10; 2 | typedef vector> VVD; 3 | 4 | // Gauss-Jordan elimination with full pivoting. 5 | // solving systems of linear equations (AX=B) 6 | // INPUT: a[][] = an n*n matrix 7 | // b[][] = an n*m matrix 8 | // OUTPUT: X = an n*m matrix (stored in b[][]) 9 | // A^{-1} = an n*n matrix (stored in a[][]) 10 | // O(n^3) 11 | bool gauss_jordan(VVD& a, VVD& b) { 12 | const int n = a.size(); 13 | const int m = b[0].size(); 14 | vector irow(n), icol(n), ipiv(n); 15 | 16 | for (int i = 0; i < n; i++) { 17 | int pj = -1, pk = -1; 18 | for (int j = 0; j < n; j++) if (!ipiv[j]) 19 | for (int k = 0; k < n; k++) if (!ipiv[k]) 20 | if (pj == -1 || fabs(a[j][k]) > fabs(a[pj][pk])) { pj = j; pk = k; } 21 | if (fabs(a[pj][pk]) < EPS) return false; // matrix is singular 22 | ipiv[pk]++; 23 | swap(a[pj], a[pk]); 24 | swap(b[pj], b[pk]); 25 | irow[i] = pj; 26 | icol[i] = pk; 27 | 28 | double c = 1.0 / a[pk][pk]; 29 | a[pk][pk] = 1.0; 30 | for (int p = 0; p < n; p++) a[pk][p] *= c; 31 | for (int p = 0; p < m; p++) b[pk][p] *= c; 32 | for (int p = 0; p < n; p++) if (p != pk) { 33 | c = a[p][pk]; 34 | a[p][pk] = 0; 35 | for (int q = 0; q < n; q++) a[p][q] -= a[pk][q] * c; 36 | for (int q = 0; q < m; q++) b[p][q] -= b[pk][q] * c; 37 | } 38 | } 39 | for (int p = n - 1; p >= 0; p--) if (irow[p] != icol[p]) { 40 | for (int k = 0; k < n; k++) swap(a[k][irow[p]], a[k][icol[p]]); 41 | } 42 | return true; 43 | } 44 | -------------------------------------------------------------------------------- /src/math/lucas-theorem.cpp: -------------------------------------------------------------------------------- 1 | // calculate nCm % p when p is prime 2 | int lucas_theorem(const char *n, const char *m, int p) { 3 | vector np, mp; 4 | int i; 5 | for (i = 0; n[i]; i++) { 6 | if (n[i] == '0' && np.empty()) continue; 7 | np.push_back(n[i] - '0'); 8 | } 9 | for (i = 0; m[i]; i++) { 10 | if (m[i] == '0' && mp.empty()) continue; 11 | mp.push_back(m[i] - '0'); 12 | } 13 | 14 | int ret = 1; 15 | int ni = 0, mi = 0; 16 | while (ni < np.size() || mi < mp.size()) { 17 | int nmod = 0, mmod = 0; 18 | for (i = ni; i < np.size(); i++) { 19 | if (i + 1 < np.size()) 20 | np[i + 1] += (np[i] % p) * 10; 21 | else 22 | nmod = np[i] % p; 23 | np[i] /= p; 24 | } 25 | for (i = mi; i < mp.size(); i++) { 26 | if (i + 1 < mp.size()) 27 | mp[i + 1] += (mp[i] % p) * 10; 28 | else 29 | mmod = mp[i] % p; 30 | mp[i] /= p; 31 | } 32 | while (ni < np.size() && np[ni] == 0) ni++; 33 | while (mi < mp.size() && mp[mi] == 0) mi++; 34 | // implement binomial. binomial(m,n) = 0 if m < n 35 | ret = (ret * binomial(nmod, mmod)) % p; 36 | } 37 | return ret; 38 | } 39 | -------------------------------------------------------------------------------- /src/math/matrix-operations.cpp: -------------------------------------------------------------------------------- 1 | const int MATSZ = 100; 2 | 3 | inline bool is_zero(double a) { return fabs(a) < 1e-9; } 4 | 5 | // out = A^(-1), returns det(A) 6 | // A becomes invalid after call this 7 | // O(n^3) 8 | double inverse_and_det(int n, double A[][MATSZ], double out[][MATSZ]) { 9 | double det = 1; 10 | for (int i = 0; i < n; i++) { 11 | for (int j = 0; j < n; j++) out[i][j] = 0; 12 | out[i][i] = 1; 13 | } 14 | for (int i = 0; i < n; i++) { 15 | if (is_zero(A[i][i])) { 16 | double maxv = 0; 17 | int maxid = -1; 18 | for (int j = i + 1; j < n; j++) { 19 | auto cur = fabs(A[j][i]); 20 | if (maxv < cur) { 21 | maxv = cur; 22 | maxid = j; 23 | } 24 | } 25 | if (maxid == -1 || is_zero(A[maxid][i])) return 0; 26 | for (int k = 0; k < n; k++) { 27 | A[i][k] += A[maxid][k]; 28 | out[i][k] += out[maxid][k]; 29 | } 30 | } 31 | det *= A[i][i]; 32 | double coeff = 1.0 / A[i][i]; 33 | for (int j = 0; j < n; j++) A[i][j] *= coeff; 34 | for (int j = 0; j < n; j++) out[i][j] *= coeff; 35 | for (int j = 0; j < n; j++) if (j != i) { 36 | double mp = A[j][i]; 37 | for (int k = 0; k < n; k++) A[j][k] -= A[i][k] * mp; 38 | for (int k = 0; k < n; k++) out[j][k] -= out[i][k] * mp; 39 | } 40 | } 41 | return det; 42 | } 43 | -------------------------------------------------------------------------------- /src/math/pollard-rho.cpp: -------------------------------------------------------------------------------- 1 | ll pollard_rho(ll n) { 2 | random_device rd; 3 | mt19937 gen(rd()); 4 | uniform_int_distribution dis(1, n - 1); 5 | ll x = dis(gen); 6 | ll y = x; 7 | ll c = dis(gen); 8 | ll g = 1; 9 | while (g == 1) { 10 | x = (modmul(x, x, n) + c) % n; 11 | y = (modmul(y, y, n) + c) % n; 12 | y = (modmul(y, y, n) + c) % n; 13 | g = gcd(abs(x - y), n); 14 | } 15 | return g; 16 | } 17 | 18 | // integer factorization 19 | // O(n^0.25 * logn) 20 | void factorize(ll n, vector& fl) { 21 | if (n == 1) { 22 | return; 23 | } 24 | if (n % 2 == 0) { 25 | fl.push_back(2); 26 | factorize(n / 2, fl); 27 | } 28 | else if (is_prime(n)) { 29 | fl.push_back(n); 30 | } 31 | else { 32 | ll f = pollard_rho(n); 33 | factorize(f, fl); 34 | factorize(n / f, fl); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/math/primality-test.cpp: -------------------------------------------------------------------------------- 1 | bool test_witness(ull a, ull n, ull s) { 2 | if (a >= n) a %= n; 3 | if (a <= 1) return true; 4 | ull d = n >> s; 5 | ull x = modpow(a, d, n); 6 | if (x == 1 || x == n-1) return true; 7 | while (s-- > 1) { 8 | x = large_mod_mul(x, x, n); 9 | if (x == 1) return false; 10 | if (x == n-1) return true; 11 | } 12 | return false; 13 | } 14 | 15 | // test whether n is prime 16 | // based on miller-rabin test 17 | // O(logn*logn) 18 | bool is_prime(ull n) { 19 | if (n == 2) return true; 20 | if (n < 2 || n % 2 == 0) return false; 21 | 22 | ull d = n >> 1, s = 1; 23 | for(; (d&1) == 0; s++) d >>= 1; 24 | 25 | #define T(a) test_witness(a##ull, n, s) 26 | if (n < 4759123141ull) return T(2) && T(7) && T(61); 27 | return T(2) && T(325) && T(9375) && T(28178) 28 | && T(450775) && T(9780504) && T(1795265022); 29 | #undef T 30 | } 31 | -------------------------------------------------------------------------------- /src/math/rational.cpp: -------------------------------------------------------------------------------- 1 | struct rational { 2 | long long p, q; 3 | 4 | void red() { 5 | if (q < 0) { 6 | p = -p; 7 | q = -q; 8 | } 9 | ll t = gcd((p >= 0 ? p : -p), q); 10 | p /= t; 11 | q /= t; 12 | } 13 | 14 | rational(): p(0), q(1) {} 15 | rational(long long p_): p(p_), q(1) {} 16 | rational(long long p_, long long q_): p(p_), q(q_) { red(); } 17 | 18 | bool operator==(const rational& rhs) const { 19 | return p == rhs.p && q == rhs.q; 20 | } 21 | bool operator!=(const rational& rhs) const { 22 | return p != rhs.p || q != rhs.q; 23 | } 24 | bool operator<(const rational& rhs) const { 25 | return p * rhs.q < rhs.p * q; 26 | } 27 | rational operator+(const rational& rhs) const { 28 | ll g = gcd(q, rhs.q); 29 | return rational(p * (rhs.q / g) + rhs.p * (q / g), (q / g) * rhs.q); 30 | } 31 | rational operator-(const rational& rhs) const { 32 | ll g = gcd(q, rhs.q); 33 | return rational(p * (rhs.q / g) - rhs.p * (q / g), (q / g) * rhs.q); 34 | } 35 | rational operator*(const rational& rhs) const { 36 | return rational(p * rhs.p, q * rhs.q); 37 | } 38 | rational operator/(const rational& rhs) const { 39 | return rational(p * rhs.q, q * rhs.p); 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /src/math/sieve.cpp: -------------------------------------------------------------------------------- 1 | // find prime numbers in 1 ~ n 2 | // ret[x] = false -> x is prime 3 | // O(n*loglogn) 4 | void sieve(int n, bool ret[]) { 5 | for (int i = 2; i * i <= n; ++i) 6 | if (!ret[i]) 7 | for (int j = i * i; j <= n; j += i) 8 | ret[i] = true; 9 | } 10 | 11 | // calculate number of divisors for 1 ~ n 12 | // when you need to calculate sum, change += 1 to += i 13 | // O(n*logn) 14 | void num_of_divisors(int n, int ret[]) { 15 | for (int i = 1; i <= n; ++i) 16 | for (int j = i; j <= n; j += i) 17 | ret[j] += 1; 18 | } 19 | 20 | // calculate euler totient function for 1 ~ n 21 | // phi(n) = number of x s.t. 0 < x < n && gcd(n, x) = 1 22 | // O(n*loglogn) 23 | void euler_phi(int n, int ret[]) { 24 | for (int i = 1; i <= n; ++i) ret[i] = i; 25 | for (int i = 2; i <= n; ++i) 26 | if (ret[i] == i) 27 | for (int j = i; j <= n; j += i) 28 | ret[j] -= ret[j] / i; 29 | } 30 | -------------------------------------------------------------------------------- /src/math/simplex.cpp: -------------------------------------------------------------------------------- 1 | // Two-phase simplex algorithm for solving linear programs of the form 2 | // maximize c^T x 3 | // subject to Ax <= b 4 | // x >= 0 5 | // INPUT: A -- an m x n matrix 6 | // b -- an m-dimensional vector 7 | // c -- an n-dimensional vector 8 | // x -- a vector where the optimal solution will be stored 9 | // OUTPUT: value of the optimal solution (infinity if unbounded 10 | // above, nan if infeasible) 11 | // To use this code, create an LPSolver object with A, b, and c as 12 | // arguments. Then, call Solve(x). 13 | typedef vector VD; 14 | typedef vector VVD; 15 | typedef vector VI; 16 | const double EPS = 1e-9; 17 | 18 | struct LPSolver { 19 | int m, n; 20 | VI B, N; 21 | VVD D; 22 | 23 | LPSolver(const VVD& A, const VD& b, const VD& c) : 24 | m(b.size()), n(c.size()), N(n + 1), B(m), D(m + 2, VD(n + 2)) { 25 | for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) D[i][j] = A[i][j]; 26 | for (int i = 0; i < m; i++) { B[i] = n + i; D[i][n] = -1; D[i][n + 1] = b[i]; } 27 | for (int j = 0; j < n; j++) { N[j] = j; D[m][j] = -c[j]; } 28 | N[n] = -1; D[m + 1][n] = 1; 29 | } 30 | 31 | void pivot(int r, int s) { 32 | double inv = 1.0 / D[r][s]; 33 | for (int i = 0; i < m + 2; i++) if (i != r) 34 | for (int j = 0; j < n + 2; j++) if (j != s) 35 | D[i][j] -= D[r][j] * D[i][s] * inv; 36 | for (int j = 0; j < n + 2; j++) if (j != s) D[r][j] *= inv; 37 | for (int i = 0; i < m + 2; i++) if (i != r) D[i][s] *= -inv; 38 | D[r][s] = inv; 39 | swap(B[r], N[s]); 40 | } 41 | 42 | bool simplex(int phase) { 43 | int x = phase == 1 ? m + 1 : m; 44 | while (true) { 45 | int s = -1; 46 | for (int j = 0; j <= n; j++) { 47 | if (phase == 2 && N[j] == -1) continue; 48 | if (s == -1 || D[x][j] < D[x][s] || D[x][j] == D[x][s] && N[j] < N[s]) s = j; 49 | } 50 | if (D[x][s] > -EPS) return true; 51 | int r = -1; 52 | for (int i = 0; i < m; i++) { 53 | if (D[i][s] < EPS) continue; 54 | if (r == -1 || D[i][n + 1] / D[i][s] < D[r][n + 1] / D[r][s] || 55 | (D[i][n + 1] / D[i][s]) == (D[r][n + 1] / D[r][s]) && B[i] < B[r]) r = i; 56 | } 57 | if (r == -1) return false; 58 | pivot(r, s); 59 | } 60 | } 61 | 62 | double solve(VD& x) { 63 | int r = 0; 64 | for (int i = 1; i < m; i++) if (D[i][n + 1] < D[r][n + 1]) r = i; 65 | if (D[r][n + 1] < -EPS) { 66 | pivot(r, n); 67 | if (!simplex(1) || D[m + 1][n + 1] < -EPS) 68 | return -numeric_limits::infinity(); 69 | for (int i = 0; i < m; i++) if (B[i] == -1) { 70 | int s = -1; 71 | for (int j = 0; j <= n; j++) 72 | if (s == -1 || D[i][j] < D[i][s] || D[i][j] == D[i][s] && N[j] < N[s]) s = j; 73 | pivot(i, s); 74 | } 75 | } 76 | if (!simplex(2)) 77 | return numeric_limits::infinity(); 78 | x = VD(n); 79 | for (int i = 0; i < m; i++) if (B[i] < n) x[B[i]] = D[i][n + 1]; 80 | return D[m][n + 1]; 81 | } 82 | }; 83 | -------------------------------------------------------------------------------- /src/miscellaneous/example.java: -------------------------------------------------------------------------------- 1 | import java.util.Scanner; 2 | 3 | public class example 4 | { 5 | public static void main(String[] args) 6 | { 7 | Scanner in = new Scanner(System.in); 8 | int T = in.nextInt(); 9 | while (T --> 0) 10 | { 11 | String str = in.next(); 12 | if (str.matches("[A-F]?A+F+C+[A-F]?")) 13 | System.out.println("Infected!"); 14 | else 15 | System.out.println("Good"); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/miscellaneous/fastio.cpp: -------------------------------------------------------------------------------- 1 | namespace fio { 2 | const int BSIZE = 524288; 3 | char buffer[BSIZE]; 4 | int p = BSIZE; 5 | inline char readChar() { 6 | if(p == BSIZE) { 7 | fread(buffer, 1, BSIZE, stdin); 8 | p = 0; 9 | } 10 | return buffer[p++]; 11 | } 12 | int readInt() { 13 | char c = readChar(); 14 | while ((c < '0' || c > '9') && c != '-') { 15 | c = readChar(); 16 | } 17 | int ret = 0; bool neg = c == '-'; 18 | if (neg) c = readChar(); 19 | while (c >= '0' && c <= '9') { 20 | ret = ret * 10 + c - '0'; 21 | c = readChar(); 22 | } 23 | return neg ? -ret : ret; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/setting/vimrc: -------------------------------------------------------------------------------- 1 | set nocp ai si nu et bs=2 mouse=a 2 | set ts=2 sts=2 sw=2 hls showmatch 3 | set ruler rulerformat=%17.(%l:%c%) 4 | set noswapfile autoread wildmenu wildmode=list:longest 5 | syntax on | colorscheme evening 6 | 7 | map :w:!g++ -g -Wall --std=c++0x -O2 %:r.cpp -o %:r && %:r < %:r.in > %:r.out 8 | map :w:!g++ -g -Wall --std=c++0x -O2 %:r.cpp -o %:r && %:r < %:r.in 9 | 10 | map k gk 11 | map j gj 12 | 13 | map h 14 | map j 15 | map k 16 | map l 17 | 18 | map :tabnew 19 | 20 | command -nargs=1 PS :cd d:/ | :vi .cpp | vs .in | sp .out 21 | -------------------------------------------------------------------------------- /src/string/aho-corasick.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | struct AhoCorasick 7 | { 8 | const int alphabet; 9 | struct node { 10 | node() {} 11 | explicit node(int alphabet) : next(alphabet) {} 12 | vector next, report; 13 | int back = 0, output_link = 0; 14 | }; 15 | int maxid = 0; 16 | vector dfa; 17 | explicit AhoCorasick(int alphabet) : alphabet(alphabet), dfa(1, node(alphabet)) { } 18 | template void add(int id, InIt first, InIt last, Fn func) { 19 | int cur = 0; 20 | for ( ; first != last; ++first) { 21 | auto s = func(*first); 22 | if (auto next = dfa[cur].next[s]) cur = next; 23 | else { 24 | cur = dfa[cur].next[s] = (int)dfa.size(); 25 | dfa.emplace_back(alphabet); 26 | } 27 | } 28 | dfa[cur].report.push_back(id); 29 | maxid = max(maxid, id); 30 | } 31 | void build() { 32 | queue q; 33 | vector visit(dfa.size()); 34 | visit[0] = 1; 35 | q.push(0); 36 | while(!q.empty()) { 37 | auto cur = q.front(); q.pop(); 38 | dfa[cur].output_link = dfa[cur].back; 39 | if (dfa[dfa[cur].back].report.empty()) 40 | dfa[cur].output_link = dfa[dfa[cur].back].output_link; 41 | for (int s = 0; s < alphabet; s++) { 42 | auto &next = dfa[cur].next[s]; 43 | if (next == 0) next = dfa[dfa[cur].back].next[s]; 44 | if (visit[next]) continue; 45 | if (cur) dfa[next].back = dfa[dfa[cur].back].next[s]; 46 | visit[next] = 1; 47 | q.push(next); 48 | } 49 | } 50 | } 51 | template vector countMatch(InIt first, InIt last, Fn func) { 52 | int cur = 0; 53 | vector ret(maxid+1); 54 | for (; first != last; ++first) { 55 | cur = dfa[cur].next[func(*first)]; 56 | for (int p = cur; p; p = dfa[p].output_link) 57 | for (auto id : dfa[p].report) ret[id]++; 58 | } 59 | return ret; 60 | } 61 | }; 62 | -------------------------------------------------------------------------------- /src/string/kmp.cpp: -------------------------------------------------------------------------------- 1 | typedef vector seq_t; 2 | 3 | void calculate_pi(vector& pi, const seq_t& str) { 4 | pi[0] = -1; 5 | for (int i = 1, j = -1; i < str.size(); i++) { 6 | while (j >= 0 && str[i] != str[j + 1]) j = pi[j]; 7 | if (str[i] == str[j + 1]) 8 | pi[i] = ++j; 9 | else 10 | pi[i] = -1; 11 | } 12 | } 13 | 14 | // returns all positions matched 15 | // O(|text|+|pattern|) 16 | vector kmp(const seq_t& text, const seq_t& pattern) { 17 | vector pi(pattern.size()), ans; 18 | if (pattern.size() == 0) return ans; 19 | calculate_pi(pi, pattern); 20 | for (int i = 0, j = -1; i < text.size(); i++) { 21 | while (j >= 0 && text[i] != pattern[j + 1]) j = pi[j]; 22 | if (text[i] == pattern[j + 1]) { 23 | j++; 24 | if (j + 1 == pattern.size()) { 25 | ans.push_back(i - j); 26 | j = pi[j]; 27 | } 28 | } 29 | } 30 | return ans; 31 | } 32 | -------------------------------------------------------------------------------- /src/string/manacher.cpp: -------------------------------------------------------------------------------- 1 | // find longest palindromic span for each element in str 2 | // O(|str|) 3 | void manacher(const string& str, int plen[]) { 4 | int r = -1, p = -1; 5 | for (int i = 0; i < str.length(); ++i) { 6 | if (i <= r) 7 | plen[i] = min((2 * p - i >= 0) ? plen[2 * p - i] : 0, r - i); 8 | else 9 | plen[i] = 0; 10 | while (i - plen[i] - 1 >= 0 && i + plen[i] + 1 < str.length() 11 | && str[i - plen[i] - 1] == str[i + plen[i] + 1]) { 12 | plen[i] += 1; 13 | } 14 | if (i + plen[i] > r) { 15 | r = i + plen[i]; 16 | p = i; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/string/suffix-array-lcp.cpp: -------------------------------------------------------------------------------- 1 | typedef char T; 2 | 3 | // calculates suffix array. 4 | // O(n*logn) 5 | vector suffix_array(const vector& in) { 6 | int n = (int)in.size(), c = 0; 7 | vector temp(n), pos2bckt(n), bckt(n), bpos(n), out(n); 8 | for (int i = 0; i < n; i++) out[i] = i; 9 | sort(out.begin(), out.end(), [&](int a, int b) { return in[a] < in[b]; }); 10 | for (int i = 0; i < n; i++) { 11 | bckt[i] = c; 12 | if (i + 1 == n || in[out[i]] != in[out[i + 1]]) c++; 13 | } 14 | for (int h = 1; h < n && c < n; h <<= 1) { 15 | for (int i = 0; i < n; i++) pos2bckt[out[i]] = bckt[i]; 16 | for (int i = n - 1; i >= 0; i--) bpos[bckt[i]] = i; 17 | for (int i = 0; i < n; i++) 18 | if (out[i] >= n - h) temp[bpos[bckt[i]]++] = out[i]; 19 | for (int i = 0; i < n; i++) 20 | if (out[i] >= h) temp[bpos[pos2bckt[out[i] - h]]++] = out[i] - h; 21 | c = 0; 22 | for (int i = 0; i + 1 < n; i++) { 23 | int a = (bckt[i] != bckt[i + 1]) || (temp[i] >= n - h) 24 | || (pos2bckt[temp[i + 1] + h] != pos2bckt[temp[i] + h]); 25 | bckt[i] = c; 26 | c += a; 27 | } 28 | bckt[n - 1] = c++; 29 | temp.swap(out); 30 | } 31 | return out; 32 | } 33 | 34 | // calculates lcp array. it needs suffix array & original sequence. 35 | // O(n) 36 | vector lcp(const vector& in, const vector& sa) { 37 | int n = (int)in.size(); 38 | if (n == 0) return vector(); 39 | vector rank(n), height(n - 1); 40 | for (int i = 0; i < n; i++) rank[sa[i]] = i; 41 | for (int i = 0, h = 0; i < n; i++) { 42 | if (rank[i] == 0) continue; 43 | int j = sa[rank[i] - 1]; 44 | while (i + h < n && j + h < n && in[i + h] == in[j + h]) h++; 45 | height[rank[i] - 1] = h; 46 | if (h > 0) h--; 47 | } 48 | return height; 49 | } 50 | -------------------------------------------------------------------------------- /src/string/z.cpp: -------------------------------------------------------------------------------- 1 | // Z[i] : maximum common prefix length of &s[0] and &s[i] 2 | // O(|s|) 3 | using seq_t = string; 4 | vector z_func(const seq_t &s) { 5 | vector z(s.size()); 6 | z[0] = s.size(); 7 | int l = 0, r = 0; 8 | 9 | for (int i = 1; i < s.size(); i++) { 10 | if (i > r) { 11 | int j; 12 | for (j = 0; i + j < s.size() && s[i + j] == s[j]; j++) ; 13 | z[i] = j; l = i; r = i + j - 1; 14 | } else if (z[i - l] < r - i + 1) { 15 | z[i] = z[i - l]; 16 | } else { 17 | int j; 18 | for (j = 1; r + j < s.size() && s[r + j] == s[r - i + j]; j++) ; 19 | z[i] = r - i + j; l = i; r += j - 1; 20 | } 21 | } 22 | 23 | return z; 24 | } 25 | -------------------------------------------------------------------------------- /teamnote.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ntopia/icpc-teamnote/9e4b112a56fff131d3e3dc153c0babcd9976583d/teamnote.pdf -------------------------------------------------------------------------------- /teamnote.tex: -------------------------------------------------------------------------------- 1 | \documentclass[10pt,landscape,a4paper,twocolumn]{article} 2 | 3 | \setlength{\columnsep}{20pt} 4 | 5 | \usepackage[left=1.0cm, right=1.0cm, top=1.5cm, bottom=1.0cm, headsep=0.4cm]{geometry} 6 | \usepackage{amsmath} 7 | \usepackage{amssymb} 8 | \usepackage{fontspec} 9 | \usepackage{kotex} 10 | \usepackage{graphicx} 11 | \usepackage{setspace} 12 | \usepackage{listings} 13 | \usepackage{comment} 14 | \usepackage{import} 15 | \usepackage{wrapfig} 16 | \usepackage{url} 17 | \usepackage{array} 18 | \usepackage[normal]{engord} 19 | \usepackage[svgnames,table]{xcolor} 20 | 21 | \usepackage{fancyhdr} 22 | \pagestyle{fancy} 23 | \fancyhead[R]{\thepage} 24 | \fancyhead[L]{Seoul National University - PLEASE OPEN TESTDATA} 25 | 26 | \setmonofont[ 27 | BoldFont = consolab.ttf, 28 | ItalicFont = consolai.ttf 29 | ]{consola.ttf} 30 | \setmainhangulfont{NanumMyeongjo} 31 | \setlength\parindent{0pt} 32 | \usepackage[parfill]{parskip} 33 | 34 | \definecolor{dkgrey}{RGB}{127, 127, 127} 35 | 36 | \lstset{ 37 | basicstyle=\footnotesize\ttfamily, 38 | breaklines=true, 39 | breakindent=1.1em 40 | % numbers=left, 41 | % numberstyle=\footnotesize\ttfamily\color{dkgrey}, 42 | % numbersep=5pt 43 | % frame=trbl 44 | } 45 | 46 | \lstdefinestyle{mycpp}{ 47 | language=[GNU]C++, 48 | keywordstyle=\color{blue}, 49 | commentstyle=\itshape\color{purple!40!black}, 50 | stringstyle=\color{orange}, 51 | } 52 | 53 | \begin{document} 54 | \tableofcontents 55 | 56 | 57 | \section{Setting} 58 | 59 | \subsection{vimrc} 60 | \lstinputlisting{src/setting/vimrc} 61 | 62 | 63 | \section{Math} 64 | 65 | \subsection{Basic Arithmetic} 66 | \lstinputlisting[style=mycpp]{src/math/basic-arithmetic.cpp} 67 | 68 | \subsection{Sieve Methods : Prime, Divisor, Euler phi} 69 | \lstinputlisting[style=mycpp]{src/math/sieve.cpp} 70 | 71 | \subsection{Primality Test} 72 | \lstinputlisting[style=mycpp]{src/math/primality-test.cpp} 73 | 74 | \subsection{Integer Factorization (Pollard's rho)} 75 | \lstinputlisting[style=mycpp]{src/math/pollard-rho.cpp} 76 | 77 | \subsection{Chinese Remainder Theorem} 78 | \lstinputlisting[style=mycpp]{src/math/chinese-remainder.cpp} 79 | 80 | \subsection{Modular Equation} 81 | 82 | $x \equiv a \pmod{m}$, $x \equiv b \pmod{n}$을 만족시키는 $x$를 구하는 방법. 83 | 84 | $m$과 $n$을 소인수분해한 후 소수의 제곱꼴의 합동식들로 각각 쪼갠다. 85 | 이 때 특정 소수에 대하여 모순이 생기면 불가능한 경우고, 86 | 모든 소수에 대해서 모순이 생기지 않으면 전체 식을 CRT로 합치면 된다. 이제 87 | $x \equiv x_1 \pmod{p^{k_1}}$과 $x \equiv x_2 \pmod{p^{k_2}}$가 88 | 모순이 생길 조건은 $k_1 \leq k_2$라고 했을 때, 89 | $x_1 \not\equiv x_2 \pmod{p^{k_1}}$인 경우이다. 90 | 모순이 생기지 않았을 때 답을 구하려면 91 | CRT로 합칠 때 $x \equiv x_2 \pmod{p^{k_2}}$만을 남기고 합쳐주면 된다. 92 | 93 | \subsection{Rational Number Class} 94 | \lstinputlisting[style=mycpp]{src/math/rational.cpp} 95 | 96 | \subsection{Catalan number} 97 | 98 | 다양한 문제의 답이 되는 수열이다. 99 | 100 | \begin{itemize} 101 | \item 길이가 $2n$인 올바른 괄호 수식의 수 102 | \item $n+1$개의 리프를 가진 풀 바이너리 트리의 수 103 | \item $n+2$각형을 $n$개의 삼각형으로 나누는 방법의 수 104 | \end{itemize} 105 | 106 | \begin{displaymath} 107 | C_n = \frac{1}{n + 1} \binom{2n}{n} 108 | \end{displaymath} 109 | 110 | \begin{displaymath} 111 | C_0 = 1 \quad \textrm{and} \quad C_{n + 1} = \sum_{i=0}^{n} C_i C_{n-i} 112 | \end{displaymath} 113 | 114 | \begin{displaymath} 115 | C_0 = 1 \quad \textrm{and} \quad C_{n + 1} = \frac{2(2n+1)}{n+2} C_n 116 | \end{displaymath} 117 | 118 | \subsection{Burnside's Lemma} 119 | 120 | 경우의 수를 세는데, 특정 transform operation(회전, 반사, ..)해서 같은 경우들은 하나로 친다. 121 | 전체 경우의 수는? 122 | 123 | - 각 operation마다 이 operation을 했을 때 변하지 않는 경우의 수를 센다 124 | (단, ``아무것도 하지 않는다''라는 operation도 있어야 함!) 125 | 126 | - 전체 경우의 수를 더한 후, operation의 수로 나눈다. (답이 맞다면 항상 나누어 떨어져야 한다) 127 | 128 | \subsection{Kirchoff's Theorem} 129 | 130 | 그래프의 스패닝 트리의 개수를 구하는 정리. 131 | 132 | 무향 그래프의 Laplacian matrix $L$를 만든다. 이것은 (정점의 차수 대각 행렬) - (인접행렬)이다. 133 | $L$에서 행과 열을 하나씩 제거한 것을 $L'$라 하자. 어느 행/열이든 관계 없다. 134 | 그래프의 스패닝 트리의 개수는 $det(L')$이다. 135 | 136 | \subsection{Lucas Theorem} 137 | \lstinputlisting[style=mycpp]{src/math/lucas-theorem.cpp} 138 | 139 | \subsection{Fast Fourier Transform} 140 | \lstinputlisting[style=mycpp]{src/math/fft.cpp} 141 | 142 | \subsection{Matrix Operations} 143 | \lstinputlisting[style=mycpp]{src/math/matrix-operations.cpp} 144 | 145 | \subsection{Gaussian Elimination} 146 | \lstinputlisting[style=mycpp]{src/math/gaussian.cpp} 147 | 148 | \subsection{Simplex Algorithm} 149 | \lstinputlisting[style=mycpp]{src/math/simplex.cpp} 150 | 151 | \subsection{Nim Game} 152 | 153 | Nim Game의 해법 : 각 더미의 돌의 개수를 모두 XOR했을 때 $0$이 아니면 첫번째, $0$이면 두번째 플레이어가 승리. 154 | 155 | Grundy Number : 가능한 다음 state의 Grundy Number를 모두 모은 다음, 그 set에 포함 156 | 되지 않는 가장 작은 수가 현재 state의 Grundy Number가 된다. 만약 다음 state가 157 | 독립된 여러 개의 state들로 나뉠 경우, 각각의 state의 Grundy Number의 XOR 합을 생각한다. 158 | 159 | Subtraction Game : 한 번에 $k$개까지의 돌만 가져갈 수 있는 경우, 160 | 각 더미의 돌의 개수를 $k + 1$로 나눈 나머지를 XOR 합하여 판단한다. 161 | 162 | Index-k Nim : 한 번에 최대 k개의 더미를 골라 각각의 더미에서 아무렇게나 돌을 163 | 제거할 수 있을 때, 각 binary digit에 대하여 합을 $k + 1$로 나눈 나머지를 계산한다. 164 | 만약 이 나머지가 모든 digit에 대하여 $0$이라면 두번째, 하나라도 $0$이 아니라면 165 | 첫번째 플레이어가 승리. 166 | 167 | 168 | \section{Data Structure} 169 | 170 | \subsection{Order statistic tree} 171 | \lstinputlisting[style=mycpp]{src/data-structure/order-statistic-tree.cpp} 172 | 173 | \subsection{Fenwick Tree} 174 | \lstinputlisting[style=mycpp]{src/data-structure/fenwick-tree.cpp} 175 | 176 | \subsection{Segment Tree with Lazy Propagation} 177 | \lstinputlisting[style=mycpp]{src/data-structure/segtree-lazyprop.cpp} 178 | 179 | \subsection{Persistent Segment Tree} 180 | \lstinputlisting[style=mycpp]{src/data-structure/persistent-segtree.cpp} 181 | 182 | \subsection{Splay Tree} 183 | \lstinputlisting[style=mycpp]{src/data-structure/splay-tree.cpp} 184 | 185 | \subsection{Link/Cut Tree} 186 | 187 | 188 | \section{DP} 189 | 190 | \subsection{Convex Hull Optimization} 191 | $O(n^{2}) \to O(n\log{n})$ 192 | 193 | DP 점화식 꼴 194 | 195 | $D[i] = \max_{j