├── .gitignore ├── CLion-Setting.zip ├── Clion-Setting.zip ├── DataStructure ├── ErasablePQ.cpp ├── EulerTourTree.cpp ├── HLD.cpp ├── LiChaoTree.cpp ├── LinkCutTree.cpp ├── O(1)LCA.cpp ├── O(N)CHT.cpp ├── PersistentSegmentTree.cpp ├── SparseTableRMQ.cpp ├── Splay-LCT.cpp └── UnionFind.cpp ├── Geometry ├── BaseTool.cpp ├── DualGraph.cpp ├── GrahamScan.cpp ├── HPI.cpp ├── KD-Tree.cpp ├── PointInConvexPolygon.cpp ├── PointInPolygon.cpp ├── RotatingCalipers.cpp └── SegmentIntersection.cpp ├── Graph ├── BipartiteMatching.cpp ├── Dinic.cpp ├── GeneralMatching.cpp ├── GlobalMinCut.cpp ├── Offline-Incremental-SCC.cpp ├── Online-Decremental-Dynamic-Connectivity-in-Planar-Graph.cpp ├── TwoSat.cpp ├── TwoSat.md └── zkwMCMF.cpp ├── Math ├── Berlekamp-Kitamasa.cpp ├── ExtendGCD.cpp ├── FFT.cpp ├── Fast-Kitamasa.cpp ├── Fraction.cpp ├── MatrixMultiply-SIMD.cpp ├── MillerRabin-PollardRho.cpp ├── NTT.cpp └── Xor-Maximization.cpp ├── README.md ├── String ├── Hashing.cpp └── Trie.cpp └── misc ├── .vscode ├── c_cpp_properties.json ├── keybindings.json ├── settings.json └── tasks.json ├── FastInput.cpp ├── Mo.cpp ├── PBDS.cpp ├── mt19937.cpp └── pragma.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* -------------------------------------------------------------------------------- /CLion-Setting.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justiceHui/AlgorithmImplement/20e7d223e1df2760671f175010dcf2351e05bf0e/CLion-Setting.zip -------------------------------------------------------------------------------- /Clion-Setting.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/justiceHui/AlgorithmImplement/20e7d223e1df2760671f175010dcf2351e05bf0e/Clion-Setting.zip -------------------------------------------------------------------------------- /DataStructure/ErasablePQ.cpp: -------------------------------------------------------------------------------- 1 | // dependency : 2 | // erasable priority_queue 3 | // Time Complexity: amortized O(log N) per query 4 | 5 | template 6 | struct pq_set{ 7 | priority_queue, greater> in, out; // min heap, inf = 1e18 8 | // priority_queue in, out; // max heap, inf = -1e18 9 | pq_set(){ in.push(inf); } 10 | void insert(T v){ in.push(v); } 11 | void erase(T v){ out.push(v); } 12 | T top(){ 13 | while(out.size() && in.top() == out.top()) in.pop(), out.pop(); 14 | return in.top(); 15 | } 16 | bool empty(){ 17 | while(out.size() && in.top() == out.top()) in.pop(), out.pop(); 18 | return in.top() == inf; 19 | } 20 | }; -------------------------------------------------------------------------------- /DataStructure/EulerTourTree.cpp: -------------------------------------------------------------------------------- 1 | using PII = pair; 2 | 3 | inline ll f(int s, int e){ return s * MAX_N + e; } 4 | namespace splayTree{ 5 | struct SplayNode{ 6 | SplayNode *p, *l, *r; 7 | int a, b, sz, flag; 8 | SplayNode() : SplayNode(-1, -1){} 9 | SplayNode(int a, int b) : a(a), b(b) { l = r = p = nullptr; sz = 1; flag = 0; }; 10 | friend int get_sz(const SplayNode *x) { return x ? x->sz : 0; } 11 | bool is_left() const { return p && this == p->l; } 12 | void update(){ 13 | sz = 1 + get_sz(l) + get_sz(r); 14 | } 15 | void rotate(){ 16 | if(is_left()) r && (r->p = p), p->l = r, r = p; 17 | else l && (l->p = p), p->r = l, l = p; 18 | if(p->p) (p->is_left()? p->p->l : p->p->r) = this; 19 | auto *t = p; p = t->p; t->p = this; 20 | t->update(); update(); 21 | } 22 | }; 23 | void splay(SplayNode *x){ 24 | for(; x->p; x->rotate()){ 25 | if(x->p->p) (x->is_left() ^ x->p->is_left() ? x : x->p)->rotate(); 26 | } 27 | } 28 | SplayNode* concat(SplayNode *a, SplayNode *b){ 29 | while(a->r) a = a->r; splay(a); 30 | a->r = b; b->p = a; a->update(); 31 | return a; 32 | } 33 | bool is_same_tree(SplayNode *a, SplayNode *b){ 34 | splay(a); splay(b); 35 | while(a->p) a = a->p; 36 | return a == b; 37 | } 38 | } 39 | 40 | struct EulerTourTree{ 41 | unordered_map edges; 42 | EulerTourTree(int n){ for(int i=1; i<=n; i++) edges[f(i,i)] = new splayTree::SplayNode(i, i); } 43 | void reRoot(int v){ 44 | auto x = edges[f(v,v)]; splay(x); 45 | auto xl = x->l, xr = x->r; 46 | if(!xl || !xr) return; 47 | x->l = x->r = xl->p = xr->p = nullptr; x->update(); 48 | concat(xr, xl); concat(xl->p, x); 49 | } 50 | void link(int u, int v){ 51 | if(is_connected(u,v)) return; 52 | auto x = edges[f(u,u)], y = edges[f(v,v)]; 53 | reRoot(u); reRoot(v); 54 | splay(x); splay(y); 55 | auto e1 = edges[f(u,v)] = new splayTree::SplayNode(u, v); 56 | auto e2 = edges[f(v,u)] = new splayTree::SplayNode(v, u); 57 | concat(x, e1); concat(e1, y); concat(e1, e2); 58 | } 59 | void cut(int a, int b){ 60 | if(!edges.count(f(a,b))) return; 61 | auto x = edges[f(a,b)], y = edges[f(b,a)]; 62 | splay(x); 63 | auto xl = x->l, xr = x->r; 64 | if(xl) xl->p = nullptr; 65 | if(xr) xr->p = nullptr; 66 | splay(y); 67 | auto yl = y->l, yr = y->r; 68 | bool flag = xl && (xl == y || xl->p); 69 | if(yl) yl->p = nullptr; 70 | if(yr) yr->p = nullptr; 71 | if(flag) yl && xr && concat(yl, xr); 72 | else xl && yr && concat(xl, yr); 73 | edges.erase(f(a,b)); edges.erase(f(b,a)); 74 | delete x; delete y; 75 | } 76 | bool is_connected(int u, int v){ 77 | return is_same_tree(edges[f(u,u)], edges[f(v,v)]); 78 | } 79 | int size(int v){ 80 | auto x = edges[f(v,v)]; 81 | splay(x); return x->sz; 82 | } 83 | }; 84 | -------------------------------------------------------------------------------- /DataStructure/HLD.cpp: -------------------------------------------------------------------------------- 1 | // Heavy Light Decomposition 2 | // dfs : undirected graph(inp) -> directed graph(g) 3 | // dfs1 : get subtree size, node depth, parent node 4 | // dfs2 : make heavy chain, euler tour trick 5 | 6 | namespace HLD{ 7 | const int SZ = 101010; 8 | vector inp[SZ], g[SZ]; 9 | int sz[SZ], par[SZ], dep[SZ], top[SZ], in[SZ], out[SZ]; 10 | void addEdge(int s, int e){ 11 | inp[s].push_back(e); inp[e].push_back(s); 12 | } 13 | void dfs(int v, int b = -1){ 14 | for(auto i : inp[v]) if(i != b) g[v].push_back(i), dfs(i); 15 | } 16 | void dfs1(int v){ 17 | sz[v] = 1; 18 | for(auto &i : g[v]){ 19 | dep[i] = dep[v] + 1; par[i] = v; 20 | dfs1(i); sz[v] += sz[i]; 21 | if(sz[i] > sz[g[v][0]]) swap(i, g[v][0]); 22 | } 23 | } 24 | void dfs2(int v){ 25 | in[v] = ++pv; 26 | for(auto i : g[v]) top[i] = (i == g[v][0]) ? top[v] : i, dfs2(i); 27 | out[v] = pv; 28 | } 29 | void hld(int root){ dfs(root); dfs1(root); dfs2(root); } 30 | void updatePath(int u, int v, ll x){ 31 | for(; top[u]!=top[v]; u=par[top[u]]){ 32 | if(dep[top[u]] < dep[top[v]]) swap(u, v); 33 | update(in[top[u]], in[u], x); 34 | } 35 | if(dep[u] > dep[v]) swap(u, v); 36 | update(in[u], in[v], x); 37 | // if edge query, then update(in[u]+1, in[v], x) 38 | } 39 | ll queryPath(int u, int v){ 40 | ll ret = 0; 41 | for(; top[u]!=top[v]; u=par[top[u]]){ 42 | if(dep[top[u]] < dep[top[v]]) swap(u, v); 43 | ret += query(in[top[u]], in[u]); 44 | } 45 | if(dep[u] > dep[v]) swap(u, v); 46 | ret += query(in[u], in[v]); 47 | // if edge query, then query(in[u]+1, in[v]) 48 | return ret; 49 | } 50 | } -------------------------------------------------------------------------------- /DataStructure/LiChaoTree.cpp: -------------------------------------------------------------------------------- 1 | // Li Chao Tree : max query 2 | // Time Complexity : O(Q log N), Space Complexity : O(Q log N) 3 | // call init() before use 4 | 5 | const ll inf = PRE_DEFINED_INF; 6 | struct LiChaoTree { 7 | struct Line { 8 | ll a, b; 9 | ll f(ll x) { return a * x + b; } 10 | Line(ll a, ll b) : a(a), b(b) {} 11 | Line() : Line(0, -inf) {} 12 | }; 13 | struct Node { 14 | Node() : l(-1), r(-1), v(0, -inf) {} 15 | int l, r; Line v; 16 | }; 17 | vector nd; 18 | ll S, E; 19 | void init(ll _s, ll _e) { nd.emplace_back(); S = _s, E = _e; } 20 | void update(int node, ll s, ll e, Line v) { 21 | Line lo = nd[node].v, hi = v; 22 | if (lo.f(s) > hi.f(s)) swap(lo, hi); 23 | if (lo.f(e) <= hi.f(e)) { nd[node].v = hi; return; } 24 | ll m = s + e >> 1; 25 | if (lo.f(m) <= hi.f(m)) { 26 | nd[node].v = hi; 27 | if (nd[node].r == -1) nd[node].r = nd.size(), nd.emplace_back(); 28 | update(nd[node].r, m + 1, e, lo); 29 | } 30 | else { 31 | nd[node].v = lo; 32 | if (nd[node].l == -1) nd[node].l = nd.size(), nd.emplace_back(); 33 | update(nd[node].l, s, m, hi); 34 | } 35 | } 36 | void update(Line v) { update(0, S, E, v); } 37 | ll query(int node, ll s, ll e, ll x) { 38 | if (node == -1) return -inf; 39 | ll t = nd[node].v.f(x); 40 | ll m = s + e >> 1; 41 | if (x <= m) return max(t, query(nd[node].l, s, m, x)); 42 | else return max(t, query(nd[node].r, m + 1, e, x)); 43 | } 44 | ll query(ll x) { return query(0, S, E, x); } 45 | }; -------------------------------------------------------------------------------- /DataStructure/LinkCutTree.cpp: -------------------------------------------------------------------------------- 1 | struct Node{ 2 | Node *l, *r, *p; 3 | bool flip; int sz; 4 | Node(){ l = r = p = nullptr; sz = 1; flip = false; } 5 | bool IsLeft() const { return p && this == p->l; } 6 | bool IsRoot() const { return !p || (this != p->l && this != p->r); } 7 | friend int GetSize(const Node *x){ return x ? x->sz : 0; } 8 | void Rotate(){ 9 | if(IsLeft()) r && (r->p = p), p->l = r, r = p; 10 | else l && (l->p = p), p->r = l, l = p; 11 | if(!p->IsRoot()) (p->IsLeft() ? p->p->l : p->p->r) = this; 12 | auto t = p; p = t->p; t->p = this; 13 | t->Update(); Update(); 14 | } 15 | void Update(){ 16 | sz = 1 + GetSize(l) + GetSize(r); 17 | } 18 | void Push(){ 19 | if(flip){ 20 | swap(l, r); 21 | if(l) l->flip ^= 1; 22 | if(r) r->flip ^= 1; 23 | flip = false; 24 | } 25 | } 26 | }; 27 | void Splay(Node *x){ 28 | for(; !x->IsRoot(); x->Rotate()){ 29 | if(!x->p->IsRoot()) x->p->p->Push(); x->p->Push(); x->Push(); 30 | if(!x->p->IsRoot()) (x->IsLeft() ^ x->p->IsLeft() ? x : x->p)->Rotate(); 31 | } 32 | x->Push(); 33 | } 34 | void Access(Node *x){ 35 | Splay(x); x->r = nullptr; 36 | for(; x->p; Splay(x)) Splay(x->p), x->p->r = x; 37 | } 38 | int GetDepth(Node *x){ 39 | Access(x); return GetSize(x->l); 40 | } 41 | Node* GetRoot(Node *x){ 42 | Access(x); x->Push(); 43 | while(x->l) x = x->l, x->Push(); 44 | Splay(x); return x; 45 | } 46 | Node* GetPar(Node *x){ 47 | Access(x); if(!x->l) return nullptr; 48 | x = x->l; x->Push(); 49 | while(x->r) x = x->r, x->Push(); 50 | Splay(x); return x; 51 | } 52 | void Link(Node *p, Node *c){ 53 | Access(c); Access(p); c->l = p; p->p = c; 54 | } 55 | void Cut(Node *x){ 56 | Access(x); x->l->p = nullptr; x->l = nullptr; 57 | } 58 | void Cut(Node *x, Node *y){ 59 | Cut(GetPar(x) == y ? x : y); 60 | } 61 | Node* GetLCA(Node *x, Node *y){ 62 | Access(x); Access(y); Splay(x); 63 | return x->p ? x->p : x; 64 | } 65 | Node* Ancestor(Node *x, int k){ 66 | k = GetDepth(x) - k; assert(k >= 0); 67 | for(;;x->Push()){ 68 | int s = GetSize(x->l); 69 | if(s == k) return Access(x), x; 70 | if(s < k) k -= s + 1, x = x->r; 71 | else x = x->l; 72 | } 73 | assert(false); 74 | } 75 | void MakeRoot(Node *x){ 76 | Access(x); Splay(x); x->flip ^= 1; 77 | } 78 | bool IsConnect(Node *x, Node *y){ 79 | return GetRoot(x) == GetRoot(y); 80 | } 81 | -------------------------------------------------------------------------------- /DataStructure/O(1)LCA.cpp: -------------------------------------------------------------------------------- 1 | // LCA in O(1) time 2 | // Time Complexity : pre-process O(N log N) Query O(1), Space Complexity : O(N log N) 3 | // add all edges and call buildConstantLCA() 4 | 5 | typedef pair p; 6 | 7 | namespace SparseTableRMQ{ 8 | const int SZ = 505050*2, LG = 22; // Array Size, log2(SZ) 9 | int pw2[LG], lg2[SZ]; // 2^i, floor( log2(i) ) 10 | p a[SZ], sparse[LG][SZ]; 11 | // 1-based 12 | void build_sparse(int n){ 13 | pw2[0] = 1; memset(lg2, -1, sizeof lg2); 14 | for(int i=1; i g[MV]; 30 | 31 | void addEdge(int s, int e){ g[s].push_back(e); g[e].push_back(s); } 32 | void dfs(int v, int b){ 33 | tour[++pv] = v; st[v] = pv; 34 | for(auto i : g[v]) if(i != b){ 35 | dep[i] = dep[v] + 1; dfs(i, v); 36 | tour[++pv] = v; 37 | } 38 | } 39 | void buildConstantLCA(){ 40 | dfs(1, -1); 41 | for(int i=1; i<=pv; i++) SparseTableRMQ::a[i] = {dep[tour[i]], tour[i]}; 42 | SparseTableRMQ::build_sparse(pv); 43 | } 44 | int lca(int u, int v){ 45 | u = st[u]; v = st[v]; 46 | if(u > v) swap(u, v); 47 | return SparseTableRMQ::query(u, v).y; 48 | } -------------------------------------------------------------------------------- /DataStructure/O(N)CHT.cpp: -------------------------------------------------------------------------------- 1 | // Convex Hull Trick : max query 2 | // Time Complexity : O(N), Space Complexity : O(N) 3 | // call init() before use 4 | 5 | struct CHT{ 6 | struct Line{ 7 | ll a, b, c; // y = ax + b, c = line index 8 | Line(ll a, ll b, ll c) : a(a), b(b), c(c) {} 9 | ll f(ll x){ return a * x + b; } 10 | }; 11 | vector v; int pv; 12 | void init(){ v.clear(); pv = 0; } 13 | int chk(const Line &a, const Line &b, const Line &c){ 14 | return (double)(a.b - b.b) / (b.a - a.a) >= (double)(c.b - b.b) / (b.a - c.a); 15 | } 16 | void insert(Line l){ 17 | if(v.size() > pv && v.back().a == l.a){ 18 | if(l.b < v.back().b) l = v.back(); v.pop_back(); 19 | } 20 | while(v.size() >= pv+2 && chk(v[v.size()-2], v.back(), l)) v.pop_back(); 21 | v.push_back(l); 22 | } 23 | p query(ll x){ 24 | // if min query, then v[pv].f(x) >= v[pv+1].f(x) 25 | while(pv+1 < v.size() && v[pv].f(x) <= v[pv+1].f(x)) pv++; 26 | return {v[pv].f(x), v[pv].c}; 27 | } 28 | }; -------------------------------------------------------------------------------- /DataStructure/PersistentSegmentTree.cpp: -------------------------------------------------------------------------------- 1 | // Persistent Segment Tree 2 | // Time Complexity : O(log N) 3 | // call init(root[0], s, e) before use 4 | // verify : BOJ7469, BOJ16978 (by Ryute) 5 | 6 | #define PST_MAX 101010 7 | typedef ll size_v; 8 | struct PSTNode { 9 | PSTNode* l, * r; size_v v; 10 | PSTNode() { l = r = nullptr; v = 0; } 11 | }; 12 | struct PST { 13 | PSTNode* root[PST_MAX]; 14 | int n, cnt; 15 | PST(int _n) : n(_n), cnt(0) { memset(root, 0, sizeof root); } 16 | void init(PSTNode* node, int s, int e, vector& in) { 17 | if (s == e) { if (!in.empty()) node->v = in[s]; return; } 18 | int m = s + e >> 1; 19 | node->l = new PSTNode; node->r = new PSTNode; 20 | init(node->l, s, m, in); init(node->r, m + 1, e, in); 21 | node->v = node->l->v + node->r->v; 22 | } 23 | void init(vector& in) { root[0] = new PSTNode; cnt++; init(root[0], 0, n - 1, in); } 24 | void init() { vector tmp; init(tmp); } 25 | void update(PSTNode* prv, PSTNode* now, int s, int e, int x, size_v v) { 26 | if (s == e) { now->v = v; return; } 27 | // IF addition query: DO if (s == e) { now->v = prv ? prv->v + v : v; return; } 28 | int m = s + e >> 1; 29 | if (x <= m) { 30 | now->l = new PSTNode; now->r = prv->r; 31 | update(prv->l, now->l, s, m, x, v); 32 | } 33 | else { 34 | now->r = new PSTNode; now->l = prv->l; 35 | update(prv->r, now->r, m + 1, e, x, v); 36 | } 37 | size_v t1 = now->l ? now->l->v : 0; 38 | size_v t2 = now->r ? now->r->v : 0; 39 | now->v = t1 + t2; 40 | } 41 | void update(int prv_idx, int x, size_v v) { 42 | root[cnt] = new PSTNode; 43 | update(root[prv_idx], root[cnt], 0, n - 1, x, v); cnt++; 44 | } void update(int x, size_v v) { update(cnt - 1, x, v); } 45 | size_v query(PSTNode* node, int s, int e, int l, int r) { 46 | if (r < s || e < l) return 0; 47 | if (l <= s && e <= r) return node->v; 48 | int m = s + e >> 1; 49 | return query(node->l, s, m, l, r) + query(node->r, m + 1, e, l, r); 50 | } size_v query(int root_idx, int l, int r) { return query(root[root_idx], 0, n - 1, l, r); } 51 | int kth(PSTNode* prv, PSTNode* now, int s, int e, int k) { //MUST be an addition query 52 | if (s == e) return s; 53 | int m = s + e >> 1; 54 | size_v diff = now->l->v - prv->l->v; 55 | if (k <= diff) return kth(prv->l, now->l, s, m, k); 56 | else return kth(prv->r, now->r, m + 1, e, k - diff); 57 | } int kth(int st, int en, int k) { return kth(root[st - 1], root[en], 0, n - 1, k); } 58 | }; -------------------------------------------------------------------------------- /DataStructure/SparseTableRMQ.cpp: -------------------------------------------------------------------------------- 1 | // RMQ with Sparse Table 2 | // Time Complexity : pre-process O(N log N) Query O(1), Space Complexity : O(N log N) 3 | // fill SparseTableRMQ::a[1..N] and call build_sparse(N) 4 | // query(s, e) : Min( A[s], A[s+1], ... , A[e] ) 5 | 6 | namespace SparseTableRMQ{ 7 | const int SZ = 505050, LG = 22; // Array Size, log2(SZ) 8 | int pw2[LG], lg2[SZ]; // 2^i, floor( log2(i) ) 9 | int a[SZ], sparse[LG][SZ]; 10 | // 1-based 11 | void input(int n){ 12 | for(int i=1; i<=n; i++) cin >> a[i]; 13 | } 14 | void build_sparse(int n){ 15 | pw2[0] = 1; memset(lg2, -1, sizeof lg2); 16 | for(int i=1; ir = new LinkCutNode(i, now); now = now->r; 24 | } 25 | now->r = new LinkCutNode(inf, now); //right dummy node 26 | root->dummy = now->r->dummy = 1; 27 | for(int i=n; i>=1; i--) update(nd[i]); 28 | } 29 | void lct_init(int n){ 30 | type = LINK_CUT_TREE; 31 | for(int i=1; i<=n; i++) nd[i] = new LinkCutNode(i); 32 | } 33 | void update(LinkCutNode *x){ 34 | x->sz = 1; x->mn = x->v; 35 | if(x->l) x->sz += x->l->sz, x->mn = min(x->mn, x->l->mn); 36 | if(x->r) x->sz += x->r->sz, x->mn = min(x->mn, x->r->mn); 37 | } 38 | void push(LinkCutNode *x){ 39 | if(!x->flip) return; 40 | swap(x->l, x->r); x->flip = 0; 41 | if(x->l) x->l->flip ^= 1; 42 | if(x->r) x->r->flip ^= 1; 43 | } 44 | void rotate(LinkCutNode *x){ 45 | if(!x->p) return; 46 | auto p = x->p; push(p); push(x); 47 | if(_is_left(x)) x->r && (x->r->p = p), p->l = x->r, x->r = p; 48 | else x->l && (x->l->p = p), p->r = x->l, x->l = p; 49 | if(!_is_root(p)) (_is_left(p)? p->p->l : p->p->r) = x; 50 | else if(type == SPLAY_TREE) root = x; 51 | x->p = p->p; p->p = x; update(p); update(x); 52 | } 53 | LinkCutNode* splay(LinkCutNode *x, LinkCutNode *g = nullptr){ 54 | for(; !_is_root(x) && x->p != g; rotate(x)){ 55 | if(_is_root(x->p) || x->p->p == g) continue; 56 | if(x->p->p != g) rotate(_is_left(x) ^ _is_left(x->p) ? x : x->p); 57 | } 58 | if(type == LINK_CUT_TREE || !g) return root = x; 59 | return root; 60 | } 61 | LinkCutNode* splay_kth(int k){ // 1-based, return kth element 62 | auto now = root; push(now); 63 | while(1){ 64 | while(now->l && now->l->sz > k) now = now->l, push(now); 65 | if(now->l) k -= now->l->sz; 66 | if(!k) break; k--; 67 | now = now->r; push(now); 68 | } 69 | return splay(now); 70 | } 71 | LinkCutNode* splay_gather(int s, int e){ // gather range [s, e] 72 | auto a = splay_kth(e+1), b = splay_kth(s-1); 73 | return splay(a, b)->r->l; 74 | } 75 | LinkCutNode* splay_flip(int s, int e){ // flip range [s, e] 76 | LinkCutNode *x = splay_gather(s, e); 77 | x->flip = !x->flip; return x; 78 | } 79 | LinkCutNode* splay_shift(int s, int e, int k){ //rightShift(k) range [s, e] 80 | LinkCutNode *range = splay_gather(s, e); 81 | if(k >= 0){ 82 | k %= (e-s+1); if(!k) return range; 83 | splay_flip(s, e); splay_flip(s, s+k-1); splay_flip(s+k, e); 84 | }else{ 85 | k *= -1; k %= (e-s+1); if(!k) return range; 86 | splay_flip(s, e); splay_flip(s, e-k); splay_flip(e-k+1, e); 87 | } 88 | return splay_gather(s, e); 89 | } 90 | // get node index(position) 91 | int splay_getidx(int k){ return splay(nd[k])->l->sz; } 92 | 93 | void access(LinkCutNode *x){ 94 | splay(x); push(x); x->r = nullptr; update(x); 95 | for(; x->p; splay(x)){ 96 | splay(x->p); push(x->p); x->p->r = x; update(x->p); 97 | } 98 | } 99 | void lct_link(int _u, int _p){ 100 | auto u = nd[_u], p = nd[_p]; 101 | access(u); access(p); push(u); 102 | u->l = p; p->p = u; update(u); 103 | } 104 | void lct_cut(int _u){ 105 | auto u = nd[_u]; access(u); push(u); 106 | u->l->p = 0; u->l = nullptr; update(u); 107 | } 108 | LinkCutNode* lct_lca(int _u, int _v){ 109 | auto u = nd[_u], v = nd[_v]; 110 | access(u); access(v); splay(u); 111 | return u->p? u->p : u; 112 | } 113 | LinkCutNode* lct_root(int _x){ 114 | auto x = nd[_x]; access(x); push(x); 115 | while(x->l) x = x->l, push(x); 116 | access(x); return x; 117 | } 118 | LinkCutNode* lct_par(int _x){ 119 | auto x = nd[_x]; access(x); push(x); 120 | if (!x->l) return nullptr; 121 | x = x->l; push(x); 122 | while(x->r) x = x->r, push(x); 123 | access(x); return x; 124 | } 125 | void inorder(LinkCutNode *x){ 126 | push(x); 127 | if(x->l) inorder(x->l); 128 | if(!x->dummy) print(x); 129 | if(x->r) inorder(x->r); 130 | } 131 | bool _is_left(LinkCutNode *x){ return x == x->p->l; } 132 | bool _is_root(LinkCutNode *x){ return !x->p || (!_is_left(x) && x != x->p->r); } 133 | } tree; -------------------------------------------------------------------------------- /DataStructure/UnionFind.cpp: -------------------------------------------------------------------------------- 1 | // Union Find with Roll Back 2 | // Time Complexity : O(log N), Space Complexity : O(N) 3 | // call init(n) or constructor(n) before use 4 | 5 | struct UnionFind{ 6 | typedef pair pii; 7 | vector par, rnk; 8 | vector rollback; 9 | UnionFind(){ } 10 | UnionFind(int n){ init(n); } 11 | void init(int n){ 12 | par.resize(n+1); 13 | rnk.resize(n+1); 14 | iota(par.begin(), par.end(), 0); 15 | fill(rnk.begin(), rnk.end(), 1); 16 | rollback.clear(); 17 | } 18 | int find(int v){ return v == par[v] ? v : find(par[v]); } 19 | bool merge(int u, int v){ 20 | u = find(u), v = find(v); 21 | if(u == v) return 0; 22 | if(rnk[u] > rnk[v]) swap(u, v); 23 | par[u] = v; 24 | if(rnk[u] == rnk[v]) rnk[v]++; 25 | rollback.push_back({u, v}); 26 | return 1; 27 | } 28 | void undo(){ 29 | assert(!rollback.empty()); 30 | int u = rollback.back().x, v = rollback.back().y; 31 | rollback.pop_back(); 32 | par[u] = u; 33 | if(rnk[u] == rnk[v]+1) rnk[v]--; 34 | } 35 | }; -------------------------------------------------------------------------------- /Geometry/BaseTool.cpp: -------------------------------------------------------------------------------- 1 | #define x first 2 | #define y second 3 | 4 | using ll = long long; 5 | using ld = long double; 6 | using Point = pair; 7 | const ld eps = 1e-7; 8 | 9 | istream& operator >> (istream &in, Point &t){ in >> t.x >> t.y; return in; } 10 | Point operator + (Point p1, Point p2){ return {p1.x+p2.x, p1.y-p2.y}; } 11 | Point operator - (Point p1, Point p2){ return {p1.x-p2.x, p1.y-p2.y}; } 12 | ll operator * (Point p1, Point p2){ return p1.x*p2.x + p1.y*p2.y; } /// dot product 13 | ll operator / (Point p1, Point p2){ return p1.x*p2.y - p2.x*p1.y; } /// cross product 14 | 15 | ll _CCW(const Point &p1, const Point &p2, const Point &p3){ return (p2-p1)/(p3-p2); } 16 | int CCW(Point p1, Point p2, Point p3){ 17 | ll res = _CCW(p1, p2, p3); 18 | return (res > 0) - (res < 0); 19 | } 20 | ll D(const Point &p1, const Point &p2){ 21 | ll dx = p1.x - p2.x, dy = p1.y - p2.y; 22 | return dx*dx + dy*dy; 23 | } -------------------------------------------------------------------------------- /Geometry/DualGraph.cpp: -------------------------------------------------------------------------------- 1 | // get dual of planar graph 2 | // Time Complexity : O(E log E), Space Complexity : O(V + E) 3 | 4 | // ith edge's face -> (i << 1), (i << 1 | 1) 5 | namespace DualGraph{ 6 | const int MV = 101010, ME = 101010; // MAX_V, MAX_E 7 | p pt[MV]; // vertex's coord 8 | vector

g[MV]; // g[s].emplace_back(e, edge_id); 9 | vector dual_pt; // coord compress 10 | int par[ME * 2]; // Union Find 11 | void uf_init(){ iota(par, par+ME*2, 0); } 12 | int find(int v){ return v == par[v] ? v : par[v] = find(par[v]); } 13 | void merge(int u, int v){ u = find(u); v = find(v); if(u != v) par[u] = v; } 14 | p base; // sort by angle 15 | bool cmp_angle(const p &_a, const p &_b){ 16 | p a = pt[_a.x], b = pt[_b.x]; 17 | if((a > base) != (b > base)) return a > b; 18 | return ccw(a, base, b) > 0; 19 | } 20 | void addEdge(int s, int e, int id){ 21 | g[s].emplace_back(e, id); g[e].emplace_back(s, id); 22 | } 23 | int out; //outer face 24 | void getDual(int n, int m){ 25 | uf_init(); 26 | for(int i=1; i<=n; i++){ 27 | base = pt[i]; sort(all(g[i]), cmp_angle); 28 | // up, left : *2+1 / down, right : *2 29 | for(int j=0; j base) u ^= 1; 34 | if(p2 > base) v ^= 1; 35 | merge(u, v); 36 | } 37 | } 38 | int mn_idx = min_element(pt+1, pt+n+1) - pt; 39 | out = find(g[mn_idx][0].y << 1 | 1); 40 | for(int i=1; i<=m; i++){ 41 | dual_pt.push_back(find(i << 1)); 42 | dual_pt.push_back(find(i << 1 | 1)); 43 | } 44 | compress(dual_pt); 45 | // @TODO coord compress 46 | } 47 | } -------------------------------------------------------------------------------- /Geometry/GrahamScan.cpp: -------------------------------------------------------------------------------- 1 | // dependency : ./BaseTool.cpp 2 | // get 2D convex hull 3 | // Time Complexity : O(N log N), Space Complexity : O(N) 4 | 5 | vector ConvexHull(vector &V){ 6 | swap(V[0], *min_element(all(V))); 7 | sort(V.begin()+1, V.end(), [&V](const Point &p1, const Point &p2){ 8 | int cw = CCW(V[0], p1, p2); 9 | if(cw) return cw > 0; 10 | return D(V[0], p1) < D(V[0], p2); 11 | }); 12 | vector hull; 13 | for(const auto &i : V){ 14 | while(hull.size() >= 2 && CCW(hull[hull.size()-2], hull.back(), i) <= 0) hull.pop_back(); 15 | hull.push_back(i); 16 | } 17 | return move(hull); 18 | } -------------------------------------------------------------------------------- /Geometry/HPI.cpp: -------------------------------------------------------------------------------- 1 | // Half Plane Intersection 2 | // Time Complexity : O(N log N) 3 | // Line : ax + by + c = 0 4 | // verify : BOJ5255 5 | 6 | const pdd o = pdd(0, 0); 7 | ld ccw(pdd a, pdd b, pdd c){ 8 | ld dx1 = b.x - a.x, dy1 = b.y - a.y; 9 | ld dx2 = c.x - b.x, dy2 = c.y - b.y; 10 | return dx1*dy2 - dx2*dy1; 11 | } 12 | namespace HalfPlaneIntersection{ 13 | struct Line{ 14 | ld a, b, c; 15 | Line() : Line(0, 0, 0) {} 16 | Line(ld a, ld b, ld c) : a(a), b(b), c(c) {} 17 | bool operator < (const Line &l) const { 18 | bool f1 = pdd(a, b) > o; 19 | bool f2 = pdd(l.a, l.b) > o; 20 | if(f1 != f2) return f1 > f2; 21 | ld cw = ccw(o, pdd(a, b), pdd(l.a, l.b)); 22 | return same(cw, 0) ? c * hypot(l.a, l.b) < l.c * hypot(a, b) : cw > 0; 23 | } 24 | pdd slope() const { return pdd(a, b); } 25 | }; 26 | pdd lineCross(Line a, Line b){ 27 | ld det = a.a*b.b - b.a*a.b; 28 | ld x = (a.c*b.b - a.b*b.c) / det; 29 | ld y = (a.a*b.c - a.c*b.a) / det; 30 | return pdd(x, y); 31 | } 32 | bool hpi_chk(Line a, Line b, Line c){ 33 | if(ccw(o, a.slope(), b.slope()) <= 0) return 0; 34 | pdd v = lineCross(a, b); 35 | return v.x*c.a + v.y*c.b >= c.c; 36 | } 37 | vector hpi(vector v){ 38 | sort(v.begin(), v.end()); 39 | deque dq; vector ret; 40 | for(auto &i : v){ 41 | if(dq.size() && same(ccw(o, dq.back().slope(), i.slope()), 0)) continue; 42 | while(dq.size() >= 2 && hpi_chk(dq[dq.size()-2], dq.back(), i)) dq.pop_back(); 43 | while(dq.size() >= 2 && hpi_chk(i, dq[0], dq[1])) dq.pop_front(); 44 | dq.push_back(i); 45 | } 46 | while(dq.size() > 2 && hpi_chk(dq[dq.size()-2], dq.back(), dq[0])) dq.pop_back(); 47 | while(dq.size() > 2 && hpi_chk(dq.back(), dq[0], dq[1])) dq.pop_front(); 48 | for(int i=0; i(); 51 | ret.push_back(lineCross(now, nxt)); 52 | } 53 | return ret; 54 | } 55 | } -------------------------------------------------------------------------------- /Geometry/KD-Tree.cpp: -------------------------------------------------------------------------------- 1 | // k-d tree : find closest point from arbitrary point 2 | // Time Complexity : average O(log N), worst O(N) 3 | // verify : BOJ7890 4 | 5 | struct KDNode{ 6 | pll v; bool dir; 7 | ll sx, ex, sy, ey; 8 | KDNode(){ sx = sy = inf; ex = ey = -inf; } 9 | }; 10 | const auto xcmp = [](pll a, pll b){ return tie(a.x, a.y) < tie(b.x, b.y); }; 11 | const auto ycmp = [](pll a, pll b){ return tie(a.y, a.x) < tie(b.y, b.x); }; 12 | struct KDTree{ 13 | // Segment Tree Size 14 | static const int S = 1 << 18; 15 | KDNode nd[S]; int chk[S]; 16 | vector v; 17 | KDTree(){ init(); } 18 | void init(){ memset(chk, 0, sizeof chk); } 19 | void _build(int node, int s, int e){ 20 | chk[node] = 1; 21 | nd[node].sx = min_element(v.begin()+s, v.begin()+e+1, xcmp)->x; 22 | nd[node].ex = max_element(v.begin()+s, v.begin()+e+1, xcmp)->x; 23 | nd[node].sy = min_element(v.begin()+s, v.begin()+e+1, ycmp)->y; 24 | nd[node].ey = max_element(v.begin()+s, v.begin()+e+1, ycmp)->y; 25 | nd[node].dir = !nd[node/2].dir; 26 | 27 | if(nd[node].dir) sort(v.begin()+s, v.begin()+e+1, ycmp); 28 | else sort(v.begin()+s, v.begin()+e+1, xcmp); 29 | 30 | int m = s + e >> 1; nd[node].v = v[m]; 31 | if(s <= m-1) _build(node << 1, s, m-1); 32 | if(m+1 <= e) _build(node << 1 | 1, m+1, e); 33 | } 34 | void build(const vector &_v){ 35 | v = _v; sort(all(v)); 36 | _build(1, 0, v.size()-1); 37 | } 38 | ll query(pll t, int node = 1){ 39 | ll tmp, ret = inf; 40 | if(t != nd[node].v) ret = min(ret, dst(t, nd[node].v)); 41 | bool x_chk = (!nd[node].dir && xcmp(t, nd[node].v)); 42 | bool y_chk = (nd[node].dir && ycmp(t, nd[node].v)); 43 | if(x_chk || y_chk){ 44 | if(chk[node << 1]) ret = min(ret, query(t, node << 1)); 45 | if(chk[node << 1 | 1]){ 46 | if(nd[node].dir) tmp = nd[node << 1 | 1].sy - t.y; 47 | else tmp = nd[node << 1 | 1].sx - t.x; 48 | if(tmp*tmp < ret) ret = min(ret, query(t, node << 1 | 1)); 49 | } 50 | } 51 | else{ 52 | if(chk[node << 1 | 1]) ret = min(ret, query(t, node << 1 | 1)); 53 | if(chk[node << 1]){ 54 | if(nd[node].dir) tmp = nd[node << 1].ey - t.y; 55 | else tmp = nd[node << 1].ex - t.x; 56 | if(tmp*tmp < ret) ret = min(ret, query(t, node << 1)); 57 | } 58 | } 59 | return ret; 60 | } 61 | }; -------------------------------------------------------------------------------- /Geometry/PointInConvexPolygon.cpp: -------------------------------------------------------------------------------- 1 | // dependency : ./BaseTool.cpp 2 | // point in convex polygon test 3 | // Time Complexity : O(log N) 4 | // input : (convex hull, point) 5 | 6 | bool pip_convex(const vector

&v, p pt){ 7 | int i = lower_bound(v.begin()+1, v.end(), pt, [&](const p &a, const p &b){ 8 | int cw = ccw(v[0], a, b); 9 | if(cw) return cw > 0; 10 | return dst(v[0], a) < dst(v[0], b); 11 | }) - v.begin(); 12 | if(i == v.size()) return 0; 13 | if(i == 1) return ccw(v[0], pt, v[1]) == 0 && v[0] <= pt && pt <= v[1]; 14 | int t1 = ccw(v[0], pt, v[i]) * ccw(v[0], pt, v[i-1]); 15 | int t2 = ccw(v[i], v[i-1], v[0]) * ccw(v[i], v[i-1], pt); 16 | if(t1 == -1 && t2 == -1) return 0; 17 | return ccw(v[0], pt, v[i-1]) != 0; 18 | } -------------------------------------------------------------------------------- /Geometry/PointInPolygon.cpp: -------------------------------------------------------------------------------- 1 | // dependency : ./SegmentIntersection.cpp 2 | // point in polygon test 3 | // Time Complexity : O(N) 4 | // input : (sorted polygon, point) 5 | 6 | const ll MAX_COORD = 1e15; 7 | bool pip(const vector

&v, p p1){ 8 | int n = v.size(), cnt = 0; 9 | p p2 = p(MAX_COORD+1, p1.y+1); 10 | for(int i=0; i= 0; 10 | } 11 | pair rotating_calipers(const vector

&hull){ 12 | auto n = hull.size(); int pv = 0; 13 | ll mx = 0; p a, b; 14 | for(int i=0; i b) swap(a, b); 10 | if(c > d) swap(c, d); 11 | return !(b < c || d < a); 12 | } 13 | return ab <= 0 && cd <= 0; 14 | } -------------------------------------------------------------------------------- /Graph/BipartiteMatching.cpp: -------------------------------------------------------------------------------- 1 | // Maximum Bipartite Matching - Hopcroft 2 | // Time Complexity : O(E sqrt V) 3 | // verify : BOJ2544 4 | 5 | template 6 | struct BMatch{ 7 | vector G[_N]; 8 | int Dist[_N], L[_N], R[_M]; 9 | bitset<_N> Visit; 10 | bitset<_N+_M> Track; 11 | void clear(){ for(int i=0; i<_N; i++) G[i].clear(); Track.reset(); } 12 | void AddEdge(int s, int e){ G[s].push_back(e); } 13 | bool BFS(int N){ 14 | bool ret = false; 15 | queue Q; 16 | memset(Dist, 0, sizeof Dist); 17 | for(int i=1; i<=N; i++){ 18 | if(L[i] == -1 && !Dist[i]) Q.push(i), Dist[i] = 1; 19 | } 20 | while(Q.size()){ 21 | int v = Q.front(); Q.pop(); 22 | for(const auto &i : G[v]){ 23 | if(R[i] == -1) ret = true; 24 | else if(!Dist[R[i]]) Dist[R[i]] = Dist[v] + 1, Q.push(R[i]); 25 | } 26 | } 27 | return ret; 28 | } 29 | bool DFS(int v){ 30 | if(Visit[v]) return false; 31 | Visit[v] = true; 32 | for(const auto &i : G[v]){ 33 | if(R[i] == -1 || !Visit[R[i]] && Dist[R[i]] == Dist[v] + 1 && DFS(R[i])){ 34 | L[v] = i; R[i] = v; return true; 35 | } 36 | } 37 | return false; 38 | } 39 | int Match(int N){ 40 | memset(L, -1, sizeof L); 41 | memset(R, -1, sizeof R); 42 | int ret = 0; 43 | while(BFS(N)){ 44 | Visit.reset(); 45 | for(int i=1; i<=N; i++) if(L[i] == -1 && DFS(i)) ret++; 46 | } 47 | return ret; 48 | } 49 | void DFS2(int v, int N){ 50 | if(Track[v]) return; 51 | Track[v] = true; 52 | for(const auto &i : G[v]) Track[i+N] = true, DFS2(R[i], N); 53 | } 54 | pair, vector> MinVertexCover(int N, int M){ 55 | Match(N); 56 | for(int i=1; i<=N; i++) if(L[i] == -1) DFS2(i, N); 57 | vector a, b; 58 | for(int i=1; i<=N; i++) if(!Track[i]) a.push_back(i); 59 | for(int i=N+1; i<=N+M; i++) if(Track[i]) b.push_back(i-N); 60 | return make_pair(a, b); 61 | } 62 | }; -------------------------------------------------------------------------------- /Graph/Dinic.cpp: -------------------------------------------------------------------------------- 1 | // dependency : 2 | // get Max Flow 3 | // Dinic's Algorithm 4 | // Time Complexity : O(V^2 E), Space Complexity : O(V + E) 5 | 6 | template 7 | struct Dinic{ 8 | struct Edge{ int v, dual; FlowType c; }; 9 | int Level[_Sz], Work[_Sz]; 10 | vector G[_Sz]; 11 | void clear(){ for(int i=0; i<_Sz; i++) G[i].clear(); } 12 | void AddEdge(int s, int e, FlowType x){ 13 | G[s].push_back({e, (int)G[e].size(), x}); 14 | G[e].push_back({s, (int)G[s].size()-1, 0}); 15 | } 16 | bool BFS(int S, int T){ 17 | memset(Level, 0, sizeof Level); 18 | queue Q; Q.push(S); Level[S] = 1; 19 | while(Q.size()){ 20 | int v = Q.front(); Q.pop(); 21 | for(const auto &i : G[v]){ 22 | if(!Level[i.v] && i.c) Q.push(i.v), Level[i.v] = Level[v] + 1; 23 | } 24 | } 25 | return Level[T]; 26 | } 27 | FlowType DFS(int v, int T, FlowType tot){ 28 | if(v == T) return tot; 29 | for(int &_i=Work[v]; _i, vector, vector>> MinCut(int S, int T){ 49 | FlowType fl = MaxFlow(S, T); 50 | vector a, b; 51 | vector> edges; 52 | const int Bias = 1e9; 53 | queue Q; Q.push(S); Level[S] += Bias; 54 | while(Q.size()){ 55 | int v = Q.front(); Q.pop(); 56 | for(const auto &i : G[v]){ 57 | if(!Level[i.v]) edges.emplace_back(v, i.v); 58 | else if(Level[i.v] < Bias) Q.push(i.v), Level[i.v] += Bias; 59 | } 60 | } 61 | for(int i=0; i<_Sz; i++){ 62 | if(Level[i]) a.push_back(i); 63 | else b.push_back(i); 64 | } 65 | return make_tuple(fl, a, b, edges); 66 | } 67 | }; -------------------------------------------------------------------------------- /Graph/GeneralMatching.cpp: -------------------------------------------------------------------------------- 1 | // General Graph Matching - Blossom Algorithm 2 | // Time Complexity : O(N^3) 3 | 4 | namespace GeneralMatching{ 5 | #define zer(x) memset(x, 0, sizeof x) 6 | #define fu(x) memset(x, -1, sizeof x) 7 | const int SZ = 111; 8 | int n; 9 | vector g[SZ]; 10 | int match[SZ]; 11 | int par[SZ], chk[SZ], gid[SZ], color[SZ]; 12 | 13 | void addEdge(int s, int e){ 14 | g[s].push_back(e); g[e].push_back(s); 15 | } 16 | 17 | int lca_chk[SZ], pv; 18 | int lca(int rt, int u, int v){ pv++; 19 | while(u != rt) lca_chk[u] = pv, u = gid[par[match[u]]]; 20 | while(v != rt){ 21 | if(lca_chk[v] == pv) return v; v = gid[par[match[v]]]; 22 | } 23 | return rt; 24 | } 25 | void group(int l, int u, int v){ 26 | while(l != gid[u]){ 27 | int vv = match[u]; 28 | int uu = par[vv]; 29 | chk[vv] = 1; 30 | par[u] = v; gid[u] = gid[vv] = l; 31 | u = uu; v = vv; 32 | } 33 | } 34 | void add_match(int rt, int v){ 35 | while(par[v] != rt){ 36 | int p = par[v]; 37 | int vv = match[p]; 38 | match[v] = p; match[p] = v; match[vv] = 0; 39 | v = vv; 40 | } 41 | match[v] = rt; match[rt] = v; 42 | } 43 | int arg(int st){ 44 | zer(par); zer(chk); fu(color); iota(gid, gid+SZ, 0); 45 | queue q; q.push(st); chk[st] = 1; color[st] = 0; 46 | while(q.size()){ 47 | int v = q.front(); q.pop(); 48 | for(auto i : g[v]){ 49 | if(color[i] == -1){ 50 | par[i] = v; color[i] = 1; 51 | if(!match[i]){ add_match(st, i); return 1; } 52 | color[match[i]] = 0; chk[match[i]] = 1; 53 | q.push(match[i]); 54 | } 55 | else if(!color[i] && gid[v] != gid[i]){ 56 | int l = lca(gid[st], gid[v], gid[i]); 57 | group(l, v, i); group(l, i, v); 58 | for(int j=1; j<=n; j++) if(chk[j] && color[j]){ 59 | color[j] = 0; q.push(j); 60 | } 61 | } 62 | } 63 | } 64 | return 0; 65 | } 66 | int run(int _n){ 67 | n = _n; int ret = 0; 68 | for(int i=1; i<=n; i++) if(!match[i] && arg(i)) ret++; 69 | return ret; 70 | } 71 | } -------------------------------------------------------------------------------- /Graph/GlobalMinCut.cpp: -------------------------------------------------------------------------------- 1 | // Global Min Cut - Stoer Wagner 2 | // Time Complexity : O(N^3) 3 | // verify : BOJ13367 4 | 5 | namespace GlobalMinCut{ 6 | const int S = 555; 7 | int g[S][S], dst[S], chk[S], del[S]; 8 | int vertex; 9 | void init(){ 10 | memset(g, 0, sizeof g); 11 | memset(del, 0, sizeof del); 12 | } 13 | void addEdge(int s, int e, int x){ g[s][e] = g[e][s] = x; } 14 | int minCutPhase(int &s, int &t){ 15 | memset(dst, 0, sizeof dst); 16 | memset(chk, 0, sizeof chk); 17 | int mincut = 0; 18 | for(int i=1; i<=vertex; i++){ 19 | int k = -1, mx = -1; 20 | for(int j=1; j<=vertex; j++) if(!del[j] && !chk[j]) { 21 | if(dst[j] > mx) k = j, mx = dst[j]; 22 | } 23 | if(k == -1) return mincut; 24 | s = t,t = k; 25 | mincut = mx, chk[k] = 1; 26 | for(int j=1; j<=vertex; j++){ 27 | if(!del[j] && !chk[j]) dst[j] += g[k][j]; 28 | } 29 | } 30 | return mincut; 31 | } 32 | 33 | int getMinCut(int n){ 34 | vertex = n; 35 | int mincut = 1e9+7; 36 | for(int i=1; i 2 | using namespace std; 3 | 4 | constexpr int MAX_V = 101010; 5 | constexpr int MAX_E = 252525; 6 | 7 | struct Edge{ int s, e; }; 8 | 9 | template struct UnionFind { 10 | int P[_Sz]; 11 | UnionFind(){ iota(P, P+_Sz, 0); } 12 | int find(int v){ return v == P[v] ? v : P[v] = find(P[v]); } 13 | bool merge(int u, int v){ 14 | u = find(u); v = find(v); 15 | if(u == v) return false; 16 | P[u] = v; return true; 17 | } 18 | }; 19 | 20 | template struct SCC { 21 | vector G[_Sz], R[_Sz], dfn, use; 22 | int id[_Sz], pv; 23 | int cnt[_Sz]; 24 | void clear(){ 25 | for(auto i : use) cnt[id[i]] = 0, G[i].clear(), R[i].clear(), id[i] = 0; 26 | dfn.clear(); use.clear(); pv = 0; 27 | } 28 | void addEdge(int s, int e){ 29 | G[s].push_back(e); 30 | R[e].push_back(s); 31 | use.push_back(s); 32 | use.push_back(e); 33 | } 34 | void dfs(int v){ 35 | id[v] = 1; 36 | for(auto i : G[v]) if(!id[i]) dfs(i); 37 | dfn.push_back(v); 38 | } 39 | void rfs(int v, int color){ 40 | id[v] = color; cnt[color]++; 41 | for(auto i : R[v]) if(!id[i]) rfs(i, color); 42 | } 43 | void getSCC(){ 44 | for(auto i : use) if(!id[i]) dfs(i); 45 | reverse(dfn.begin(), dfn.end()); 46 | for(auto i : use) id[i] = 0; 47 | for(auto i : dfn) if(!id[i]) rfs(i, ++pv); 48 | } 49 | }; 50 | 51 | int N, M; 52 | Edge E[MAX_E]; 53 | UnionFind uf; 54 | SCC scc; 55 | int Time[MAX_E]; // connect time 56 | 57 | void Solve(int s, int e, const vector &li){ 58 | if(s == e){ 59 | for(const auto &i : li) uf.merge(E[i].s, E[i].e), Time[i] = s; 60 | // @TODO : operation (uf: maintain scc) 61 | return; 62 | } 63 | scc.clear(); 64 | 65 | int m = s + e >> 1; 66 | for(const auto &i : li){ 67 | int st = uf.find(E[i].s), ed = uf.find(E[i].e); 68 | if(i <= m) scc.addEdge(st, ed); 69 | } 70 | scc.getSCC(); 71 | 72 | vector l, r; 73 | for(const auto &i : li){ 74 | if(i > m){ r.push_back(i); continue; } 75 | int st = uf.find(E[i].s), ed = uf.find(E[i].e); 76 | if(scc.id[st] == scc.id[ed]) l.push_back(i); 77 | else r.push_back(i); 78 | } 79 | Solve(s, m, l); 80 | Solve(m+1, e, r); 81 | } 82 | 83 | int main(){ 84 | ios_base::sync_with_stdio(false); cin.tie(nullptr); 85 | cin >> N >> M; 86 | for(int i=1; i<=M; i++) cin >> E[i].s >> E[i].e; 87 | 88 | vector li(M); 89 | iota(li.begin(), li.end(), 1); 90 | Solve(1, M+1, li); 91 | } 92 | -------------------------------------------------------------------------------- /Graph/Online-Decremental-Dynamic-Connectivity-in-Planar-Graph.cpp: -------------------------------------------------------------------------------- 1 | // dependency : 2 | // Online Decremental Dynamic Connectivity in Planar Graphs 3 | // Time Complexity : O((N+Q) log N), amortized O(log N) per query, Space Complexity : O(V + E) 4 | 5 | #include 6 | #define all(v) v.begin(), v.end() 7 | #define compress(v) sort(all(v)), v.erase(unique(all(v)), v.end()) 8 | using namespace std; 9 | 10 | typedef long long ll; 11 | 12 | namespace Solver{ 13 | #define x first 14 | #define y second 15 | typedef pair p; 16 | const int MV = 101010, ME = 101010; // MAX_V, MAX_E 17 | 18 | namespace DualGraph{ 19 | p pt[MV]; 20 | vector

g[MV]; // g[s].emplace_back(e, edge_id); 21 | set

gph[MV]; // g[s].emplace_back(e, edge_id); 22 | vector dual_pt; 23 | 24 | ll ccw(const p &a, const p &b, const p &c){ 25 | ll dx1 = b.x - a.x, dy1 = b.y - a.y; 26 | ll dx2 = c.x - b.x, dy2 = c.y - b.y; 27 | ll res = dx1*dy2 - dx2*dy1; 28 | if(res > 0) return 1; 29 | if(res) return -1; 30 | return 0; 31 | } 32 | 33 | // Union Find 34 | int par[ME * 2]; 35 | void uf_init(){ iota(par, par+ME*2, 0); } 36 | int find(int v){ return v == par[v] ? v : par[v] = find(par[v]); } 37 | int merge(int u, int v){ 38 | u = find(u); v = find(v); 39 | if(u == v) return 0; 40 | par[u] = v; return 1; 41 | } 42 | 43 | p base; 44 | bool cmp_angle(const p &_a, const p &_b){ 45 | p a = pt[_a.x], b = pt[_b.x]; 46 | if((a > base) != (b > base)) return a > b; 47 | return ccw(a, base, b) > 0; 48 | } 49 | 50 | void addEdge(int s, int e, int id){ 51 | g[s].emplace_back(e, id); 52 | g[e].emplace_back(s, id); 53 | gph[s].emplace(e, id); // if use removeEdge 54 | gph[e].emplace(s, id); // if use removeEdge 55 | } 56 | 57 | void removeEdge(int s, int e, int id){ 58 | gph[s].erase(gph[s].find(p(e, id))); 59 | gph[e].erase(gph[e].find(p(s, id))); 60 | } 61 | 62 | int out; //outer face 63 | void getDual(int n, int m){ 64 | uf_init(); 65 | for(int i=1; i<=n; i++){ 66 | base = pt[i]; 67 | sort(all(g[i]), cmp_angle); 68 | // up, left : *2+1 69 | // down, right : *2 70 | for(int j=0; j base) u ^= 1; 75 | if(p2 > base) v ^= 1; 76 | merge(u, v); 77 | } 78 | } 79 | int mn_idx = min_element(pt+1, pt+n+1) - pt; 80 | out = find(g[mn_idx][0].y << 1 | 1); 81 | 82 | for(int i=1; i<=m; i++){ 83 | dual_pt.push_back(find(i << 1)); 84 | dual_pt.push_back(find(i << 1 | 1)); 85 | } 86 | compress(dual_pt); 87 | } 88 | } 89 | 90 | map edgeList; 91 | int visitCheck[101010]; 92 | int vertexColor[101010], colorCount = 0; 93 | 94 | void _coloring(int a, int b){ 95 | colorCount++; 96 | vector

stk[2]; 97 | vector arr[2]; 98 | stk[0].emplace_back(a, 0); 99 | stk[1].emplace_back(b, 0); 100 | while(stk[0].size() && stk[1].size()){ 101 | for(int i=0; i<2; i++){ 102 | int v = stk[i].back().x, c = stk[i].back().y; stk[i].pop_back(); 103 | arr[i].push_back(v); visitCheck[v] = colorCount; 104 | auto it = DualGraph::gph[v].lower_bound(p(c, -1)); 105 | if(it == DualGraph::gph[v].end()) continue; 106 | stk[i].emplace_back(v, it->x + 1); 107 | if(visitCheck[it->x] != colorCount) stk[i].emplace_back(it->x, 0); 108 | } 109 | } 110 | if(stk[0].empty()) for(auto i : arr[0]) vertexColor[i] = colorCount; 111 | else for(auto i : arr[1]) vertexColor[i] = colorCount; 112 | } 113 | 114 | void _addPoint(int x, int y, int idx){ DualGraph::pt[idx] = p(x, y); } 115 | void _addEdge(int a, int b, int idx){ 116 | if(a > b) swap(a, b); 117 | DualGraph::addEdge(a, b, idx); 118 | edgeList[p(a, b)] = idx; 119 | } 120 | 121 | void _getGraphInfo(int n, int m){ 122 | for(int i=1; i<=n; i++){ 123 | int x, y; cin >> x >> y; 124 | _addPoint(x, y, i); 125 | } 126 | for(int i=1; i<=m; i++){ 127 | int u, v; cin >> u >> v; 128 | _addEdge(u, v, i); 129 | } 130 | } 131 | 132 | void _dfs(int v, int color){ 133 | vertexColor[v] = color; 134 | for(auto i : DualGraph::g[v]) if(!vertexColor[i.x]) _dfs(i.x, color); 135 | } 136 | 137 | // Call after add edge 138 | void buildSolver(int n, int m){ 139 | _getGraphInfo(n, m); 140 | DualGraph::getDual(n, m); 141 | for(int i=1; i<=n; i++) if(!vertexColor[i]) _dfs(i, ++colorCount); 142 | } 143 | 144 | void removeEdge(int a, int b){ 145 | if(a > b) swap(a, b); 146 | if(edgeList.find(p(a, b)) == edgeList.end()) return; 147 | int edge_id = edgeList[p(a, b)]; 148 | edgeList.erase(p(a, b)); 149 | DualGraph::removeEdge(a, b, edge_id); 150 | if(DualGraph::merge(edge_id << 1, edge_id << 1 | 1)) return; 151 | _coloring(a, b); 152 | } 153 | 154 | bool isConnected(int a, int b){ return vertexColor[a] == vertexColor[b]; } 155 | 156 | #undef x 157 | #undef y 158 | } 159 | 160 | // use example 161 | int main(){ 162 | const int REMOVE_EDGE = 1; 163 | const int IS_CONNECTED = 2; 164 | 165 | int n, m, q; 166 | cin >> n >> m >> q; 167 | Solver::buildSolver(n, m); 168 | for(int i=0; i> op >> a >> b; 171 | if(op == REMOVE_EDGE) Solver::removeEdge(a, b); 172 | else if(op == IS_CONNECTED) cout << Solver::isConnected(a, b) << "\n"; 173 | } 174 | } -------------------------------------------------------------------------------- /Graph/TwoSat.cpp: -------------------------------------------------------------------------------- 1 | // SCC / 2-SAT with Targan's Algorithm 2 | // Time Complexity : O(N+M) 3 | // CNF: (A or B) / alwaysTrue: A => B / setValue / mostOne / exactlyOne 4 | 5 | inline int True(int x){ return x << 1; } 6 | inline int False(int x){ return x << 1 | 1; } 7 | inline int Inv(int x){ return x ^ 1; } 8 | struct TwoSat{ 9 | int n; 10 | vector> g; 11 | vector result; 12 | TwoSat(int n, int m = 0) : n(n), g(n+n) { if(!m) g.reserve(m+m); } 13 | int addVar(){ g.emplace_back(); g.emplace_back(); return n++; } 14 | void addEdge(int s, int e){ g[s].push_back(e); } 15 | void addCNF(int a, int b){ addEdge(Inv(a), b); addEdge(Inv(b), a); } // (A or B) 16 | void setValue(int x){ addCNF(x, x); } // (A or A) 17 | void addAlwaysTrue(int a, int b){ addEdge(a, b); addEdge(Inv(b), Inv(a)); } // A => B 18 | void addMostOne(const vector &li){ 19 | if(li.empty()) return; int t; 20 | for(int i=0; i &li){ 29 | if(li.empty()) return; int t; 30 | for(int i=0; i val, comp, z; int pv = 0; 40 | int dfs(int i){ 41 | int low = val[i] = ++pv, x; z.push_back(i); 42 | for(int e : g[i]) if(!comp[e]) low = min(low, val[e] ? val[e] : dfs(e)); 43 | if(low == val[i]){ 44 | do{ 45 | x = z.back(); z.pop_back(); 46 | comp[x] = low; 47 | if (result[x>>1] == -1) result[x>>1] = ~x&1; 48 | }while(x != i); 49 | } 50 | return val[i] = low; 51 | } 52 | bool sat(){ 53 | result.assign(n, -1); 54 | val.assign(2*n, 0); comp = val; 55 | for(int i=0; i getValue(){ return move(result); } 60 | }; 61 | -------------------------------------------------------------------------------- /Graph/TwoSat.md: -------------------------------------------------------------------------------- 1 | # TwoSat 2 | 3 | ## Explanation 4 | 5 | Solves 2-SAT problem. 6 | 7 | ## Implementation 8 | 9 | Simply implemented with SCC(Tarjan). The SCC implementation is from kactl. One variable has two vertex which represent that variable is true or false; you should distinguish these two index - variable index and vertex index(twice of variable index). 10 | 11 | ## Class and Functions 12 | 13 | ### Constructor 14 | 15 | ```cpp 16 | TwoSat(int n, int m = 0) 17 | ``` 18 | `n` is a number of variable of 2-SAT formula. `m` is number of vertex which of graph representation of 2-SAT problem. Unless `m` is specified, `m` is automatically set to twice as `n` and it is highly recommended to set as default. 19 | 20 | ### Basic Functions 21 | 22 | ```cpp 23 | inline int True(int x) 24 | inline int False(int x) 25 | inline int Inv(int x) 26 | ``` 27 | `True` and `False` Takes the index of variable as an input and returns the index of a vertex representing true index of a vertex representing false, respectively. `Inv` returns index of inversed vertex(which means True(x) = Inv(False(x))). 28 | 29 | ### Constructing Formula 30 | 31 | You MUST use **index of vertex** to construct the formula correctly. Therefore you may use `True` or `False` function on index of variable. 32 | 33 | ```cpp 34 | void addCNF(int a, int b) 35 | ``` 36 | Add CNF (A or B). 37 | 38 | ```cpp 39 | void setValue(int x) 40 | ``` 41 | Add CNF (X or X). 42 | 43 | ```cpp 44 | void addAlwaysTrue(int a, int b) 45 | ``` 46 | Add constraints which means A -> B (If A is true, B also must be true). 47 | 48 | ```cpp 49 | void addMostOne(const vector& li) 50 | ``` 51 | Add constraints which means only up to one of the vertex numbers given as input can be true. 52 | 53 | ```cpp 54 | void addExactlyOne(const vector& li) 55 | ``` 56 | Add constraints which means exactly one of the vertex numbers given as input should be true. 57 | 58 | ### Run 59 | 60 | ```cpp 61 | bool sat() 62 | ``` 63 | Runs 2-SAT algorithm. Returns this 2-SAT problem is solvable(1) or not(0). Time Complexity : O(n) 64 | 65 | ```cpp 66 | vector getValue() 67 | ``` 68 | Returns one of backtracked value of 2-SAT problem. It returns a vector `result` and its length is `n`, `result[i]` stores ith **variable** is true(1) or false(0). Be careful: it is variable index, not a vertex index. 69 | 70 | 71 | -------------------------------------------------------------------------------- /Graph/zkwMCMF.cpp: -------------------------------------------------------------------------------- 1 | // dependency : 2 | // get Min Cost Max Flow 3 | // zkw MCMF (hell-joseon MCMF) 4 | // optimized for short-augmenting-path 5 | 6 | template 7 | struct ZKW{ 8 | struct Edge{ int v, dual; FlowType c; CostType d; }; 9 | vector G[_Sz]; 10 | bool InQ[_Sz], Check[_Sz]; 11 | CostType Pi[_Sz], Dist[_Sz]; 12 | int Work[_Sz]; 13 | void AddEdge(int s, int e, FlowType c, CostType d){ 14 | G[s].push_back({e, (int)G[e].size(), c, d}); 15 | G[e].push_back({s, (int)G[s].size()-1, 0, -d}); 16 | } 17 | void Init(int S, int T){ 18 | fill(Pi, Pi+_Sz, _Inf); 19 | fill(Dist, Dist+_Sz, _Inf); 20 | 21 | // Johnson's Algorithm with SPFA 22 | memset(InQ, false, sizeof InQ); 23 | queue Q; Q.push(S); InQ[S] = true; 24 | while(Q.size()){ 25 | int v = Q.front(); Q.pop(); InQ[v] = false; 26 | for(const auto &i : G[v]){ 27 | if(i.c && Pi[i.v] > Pi[v] + i.d){ 28 | Pi[i.v] = Pi[v] + i.d; 29 | if(!InQ[i.v]) InQ[i.v] = true, Q.push(i.v); 30 | } 31 | } 32 | } 33 | for(int i=0; i<_Sz; i++) for(auto &j : G[i]) if(j.c) j.d += Pi[i] - Pi[j.v]; 34 | 35 | // Get Shortest Path DAG with Dijkstra 36 | priority_queue> pq; pq.emplace(0, S); Dist[S] = 0; 37 | while(pq.size()){ 38 | auto [cst, now] = pq.top(); pq.pop(); cst = -cst; 39 | if(Dist[now] != cst) continue; 40 | for(auto i : G[now]){ 41 | if(i.c && Dist[i.v] > Dist[now] + i.d){ 42 | Dist[i.v] = Dist[now] + i.d; 43 | pq.emplace(-Dist[i.v], i.v); 44 | } 45 | } 46 | } 47 | for(int i=0; i<_Sz; i++) Dist[i] += Pi[T] - Pi[S]; 48 | } 49 | bool Update(){ // Update DAG in O(V+E) 50 | CostType mn = _Inf; 51 | for(int i=0; i<_Sz; i++){ 52 | if(!Check[i]) continue; 53 | for(const auto &j : G[i]){ 54 | if(j.c && !Check[j.v]) mn = min(mn, Dist[i] + j.d - Dist[j.v]); 55 | } 56 | } 57 | if(mn == _Inf) return false; 58 | for(int i=0; i<_Sz; i++) if(!Check[i]) Dist[i] += mn; 59 | return true; 60 | } 61 | FlowType DFS(int v, int T, FlowType tot){ 62 | Check[v] = true; 63 | if(v == T) return tot; 64 | for(int &_i=Work[v]; _i MinCostFlow(int S, int T){ 76 | Init(S, T); 77 | FlowType fl = 0, tmp; CostType cst = 0; 78 | do{ 79 | memset(Check, false, sizeof Check); 80 | memset(Work, 0, sizeof Work); 81 | while((tmp = DFS(S, T, _Inf_f))){ 82 | fl += tmp; 83 | cst += Dist[T] * tmp; 84 | memset(Check, false, sizeof Check); 85 | } 86 | }while(Update()); 87 | return make_pair(fl, cst); 88 | } 89 | }; -------------------------------------------------------------------------------- /Math/Berlekamp-Kitamasa.cpp: -------------------------------------------------------------------------------- 1 | // Berlekamp + Kitamasa 2 | // Time Complextity : O(NK + N log mod) 3 | // 벡터 크기 N, 점화식 크기 K 4 | 5 | const int mod = 1e9+7; 6 | ll pw(ll a, ll b){ 7 | ll ret = 1; a %= mod; 8 | while(b){ 9 | if(b & 1) ret = ret * a % mod; 10 | b >>= 1; a = a * a % mod; 11 | } 12 | return ret; 13 | } 14 | vector berlekamp_massey(vector x){ 15 | vector ls, cur; 16 | int lf, ld; 17 | for(int i=0; i c(i-lf-1); c.push_back(k); 28 | for(auto &j : ls) c.push_back(-j * k % mod); 29 | if(c.size() < cur.size()) c.resize(cur.size()); 30 | for(int j=0; j=(int)cur.size()){ 32 | tie(ls, lf, ld) = make_tuple(cur, i, (t - x[i]) % mod); 33 | } 34 | cur = c; 35 | } 36 | for(auto &i : cur) i = (i % mod + mod) % mod; 37 | return cur; 38 | } 39 | int get_nth(vector rec, vector dp, ll n){ 40 | int m = rec.size(); vector s(m), t(m); 41 | s[0] = 1; 42 | if(m != 1) t[1] = 1; 43 | else t[0] = rec[0]; 44 | auto mul = [&rec](vector v, vector w){ 45 | int m = v.size(); 46 | vector t(2 * m); 47 | for(int j=0; j= mod) t[j+k] -= mod; 50 | } 51 | for(int j=2*m-1; j>=m; j--) for(int k=1; k<=m; k++){ 52 | t[j-k] += 1ll * t[j] * rec[k-1] % mod; 53 | if(t[j-k] >= mod) t[j-k] -= mod; 54 | } 55 | t.resize(m); 56 | return t; 57 | }; 58 | while(n){ 59 | if(n & 1) s = mul(s, t); 60 | t = mul(t, t); n >>= 1; 61 | } 62 | ll ret = 0; 63 | for(int i=0; i x, ll n){ 67 | if(n < x.size()) return x[n]; 68 | vector v = berlekamp_massey(x); 69 | if(v.empty()) return 0; 70 | return get_nth(v, x, n); 71 | } -------------------------------------------------------------------------------- /Math/ExtendGCD.cpp: -------------------------------------------------------------------------------- 1 | // dependency : 2 | // find x, y such that ax + by = gcd(a, b) 3 | // Time Complexity : O(log min(a, b)) 4 | 5 | ll gcd(ll x, ll y) { return y ? gcd(y, x%y) : x; } 6 | ll lcm(ll x, ll y) { return x / gcd(x, y) * y; } 7 | ll mod(ll a, ll b) { return ((a%b) + b) % b; } 8 | ll ext_gcd(ll a, ll b, ll &x, ll &y) { //ax + by = gcd(a, b) 9 | ll g = a; x = 1, y = 0; 10 | if (b) g = ext_gcd(b, a % b, y, x), y -= a / b * x; 11 | return g; 12 | } 13 | ll inv(ll a, ll m){ //return x when (ax mod m = 1), fail -> -1 14 | ll x, y; 15 | ll g = ext_gcd(a, m, x, y); 16 | if(g > 1) return -1; 17 | return mod(x, m); 18 | } 19 | // Return (z, M), fail -> M = -1 20 | pll crt(ll a1, ll m1, ll a2, ll m2){ 21 | ll s, t; ll g = ext_gcd(m1, m2, s, t); 22 | if(a1 % g != a2 % g) return pll(0, -1); 23 | s = mod(s*a2, m2); t = mod(t*a1, m1); 24 | ll res = mod(s*(m1/g) + t*(m2/g), m1/g*m2), M = m1/g*m2; 25 | return pll(res, M); 26 | } 27 | pll crt(const vector &a, const vector &m){ 28 | if(a.size() == 1) return pll(a[0], m[0]); 29 | pll ret = crt(a[0], m[0], a[1], m[1]); 30 | for(int i=2; i cpx; 5 | typedef vector poly; 6 | const double pi = acos(-1); 7 | 8 | void fft(poly &f, bool inv = 0){ 9 | int n = f.size(), j = 0; 10 | vector root(n >> 1); 11 | for(int i=1; i> 1); 13 | while(j >= bit) j -= bit, bit >>= 1; 14 | j += bit; 15 | if(i < j) swap(f[i], f[j]); 16 | } 17 | double ang = 2 * pi / n; if(inv) ang *= -1; 18 | for(int i=0; i multiply(const vector &_a, const vector &_b){ 31 | poly a, b; a.reserve(_a.size()); b.reserve(_b.size()); 32 | for(auto i : _a) a.push_back(i); 33 | for(auto i : _b) b.push_back(i); 34 | int n = 1; 35 | while(n < a.size() + b.size()) n <<= 1; 36 | a.resize(n); b.resize(n); 37 | cpx w(cos(2*pi/n), sin(2*pi/n)); 38 | fft(a); fft(b); 39 | for(int i=0; i ret(n); fft(a, 1); 41 | for(int i=0; i 1 && !ret.back()) ret.pop_back(); 43 | return ret; 44 | } -------------------------------------------------------------------------------- /Math/Fast-Kitamasa.cpp: -------------------------------------------------------------------------------- 1 | // codechef RNG (Random Number Generator) 2 | // BOJ 13725 3 | 4 | #include 5 | #define x first 6 | #define y second 7 | #define all(v) v.begin(), v.end() 8 | #define compress(v) sort(all(v)), v.erase(unique(all(v)), v.end()) 9 | #define IDX(v, x) (lower_bound(all(v), x) - v.begin()) 10 | using namespace std; 11 | 12 | using uint = unsigned; 13 | using ll = long long; 14 | using ull = unsigned long long; 15 | 16 | template 17 | struct MINT{ 18 | int v; 19 | MINT() : v(0) {} 20 | MINT(ll val){ 21 | v = (-M <= val && val < M) ? val : val % M; 22 | if(v < 0) v += M; 23 | } 24 | 25 | friend istream& operator >> (istream &is, MINT &a) { ll t; is >> t; a = MINT(t); return is; } 26 | friend ostream& operator << (ostream &os, const MINT &a) { return os << a.v; } 27 | friend bool operator == (const MINT &a, const MINT &b) { return a.v == b.v; } 28 | friend bool operator != (const MINT &a, const MINT &b) { return a.v != b.v; } 29 | friend MINT pw(MINT a, ll b){ 30 | MINT ret= 1; 31 | while(b){ 32 | if(b & 1) ret *= a; 33 | b >>= 1; a *= a; 34 | } 35 | return ret; 36 | } 37 | friend MINT inv(const MINT a) { return pw(a, M-2); } 38 | MINT operator - () const { return MINT(-v); } 39 | MINT& operator += (const MINT m) { if((v += m.v) >= M) v -= M; return *this; } 40 | MINT& operator -= (const MINT m) { if((v -= m.v) < 0) v += M; return *this; } 41 | MINT& operator *= (const MINT m) { v = (ll)v*m.v%M; return *this; } 42 | MINT& operator /= (const MINT m) { *this *= inv(m); return *this; } 43 | friend MINT operator + (MINT a, MINT b) { a += b; return a; } 44 | friend MINT operator - (MINT a, MINT b) { a -= b; return a; } 45 | friend MINT operator * (MINT a, MINT b) { a *= b; return a; } 46 | friend MINT operator / (MINT a, MINT b) { a /= b; return a; } 47 | operator int32_t() const { return v; } 48 | operator int64_t() const { return v; } 49 | }; 50 | 51 | namespace fft{ 52 | template 53 | static void NTT(vector> &f, bool inv_fft = false){ 54 | using T = MINT; 55 | int N = f.size(); 56 | vector root(N >> 1); 57 | for(int i=1, j=0; i> 1; 59 | while(j >= bit) j -= bit, bit >>= 1; 60 | j += bit; 61 | if(i < j) swap(f[i], f[j]); 62 | } 63 | T ang = pw(T(W), (M-1)/N); if(inv_fft) ang = inv(ang); 64 | root[0] = 1; for(int i=1; i>1; i++) root[i] = root[i-1] * ang; 65 | for(int i=2; i<=N; i<<=1){ 66 | int step = N / i; 67 | for(int j=0; j>1)] * root[k*step]; 70 | f[j+k] = u + v; 71 | f[j+k+(i>>1)] = u - v; 72 | } 73 | } 74 | } 75 | if(inv_fft){ 76 | T rev = inv(T(N)); 77 | for(int i=0; i 81 | vector> multiply_ntt(vector> a, vector> b){ 82 | int N = 2; while(N < a.size() + b.size()) N <<= 1; 83 | a.resize(N); b.resize(N); 84 | NTT(a); NTT(b); 85 | for(int i=0; i(a, true); 87 | return a; 88 | } 89 | } 90 | 91 | template 92 | struct PolyMod{ 93 | using T = MINT; 94 | vector a; 95 | 96 | // constructor 97 | PolyMod(){} 98 | PolyMod(T a0) : a(1, a0) { normalize(); } 99 | PolyMod(const vector a) : a(a) { normalize(); } 100 | 101 | // method from vector 102 | int size() const { return a.size(); } 103 | int deg() const { return a.size() - 1; } 104 | void normalize(){ while(a.size() && a.back() == T(0)) a.pop_back(); } 105 | T operator [] (int idx) const { return a[idx]; } 106 | typename vector::const_iterator begin() const { return a.begin(); } 107 | typename vector::const_iterator end() const { return a.end(); } 108 | void push_back(const T val) { a.push_back(val); } 109 | void pop_back() { a.pop_back(); } 110 | 111 | // basic manipulation 112 | PolyMod reversed() const { 113 | vector b = a; 114 | reverse(b.begin(), b.end()); 115 | return b; 116 | } 117 | PolyMod trim(int n) const { 118 | return vector(a.begin(), a.begin() + min(n, size())); 119 | } 120 | PolyMod inv(int n){ 121 | PolyMod q(T(1) / a[0]); 122 | for(int i=1; i(a, b.a); 154 | normalize(); 155 | return *this; 156 | } 157 | PolyMod operator /= (const PolyMod &b){ 158 | if(deg() < b.deg()) return *this = PolyMod(); 159 | int sz = deg() - b.deg() + 1; 160 | PolyMod ra = reversed().trim(sz), rb = b.reversed().trim(sz).inv(sz); 161 | *this = (ra * rb).trim(sz); 162 | for(int i=sz-size(); i; i--) push_back(T(0)); 163 | reverse(all(a)); 164 | normalize(); 165 | return *this; 166 | } 167 | PolyMod operator %= (const PolyMod &b){ 168 | if(deg() < b.deg()) return *this; 169 | PolyMod tmp = *this; tmp /= b; tmp *= b; 170 | *this -= tmp; 171 | normalize(); 172 | return *this; 173 | } 174 | 175 | // operator 176 | PolyMod operator * (const T x) const { return PolyMod(*this) *= x; } 177 | PolyMod operator / (const T x) const { return PolyMod(*this) /= x; } 178 | PolyMod operator + (const PolyMod &b) const { return PolyMod(*this) += b; } 179 | PolyMod operator - (const PolyMod &b) const { return PolyMod(*this) -= b; } 180 | PolyMod operator * (const PolyMod &b) const { return PolyMod(*this) *= b; } 181 | PolyMod operator / (const PolyMod &b) const { return PolyMod(*this) /= b; } 182 | PolyMod operator % (const PolyMod &b) const { return PolyMod(*this) %= b; } 183 | }; 184 | 185 | constexpr int W = 3, MOD = 104857601; 186 | using mint = MINT; 187 | using poly = PolyMod; 188 | 189 | mint kitamasa(poly c, poly a, ll n){ 190 | poly d = vector{1}; 191 | poly xn = vector{0, 1}; 192 | poly f; 193 | for(int i=0; i>= 1; xn = xn * xn % f; 198 | } 199 | mint ret = 0; 200 | for(int i=0; i<=a.deg(); i++) ret += a[i] * d[i]; 201 | return ret; 202 | } 203 | 204 | int main(){ 205 | ios_base::sync_with_stdio(false); cin.tie(nullptr); 206 | ll K, N; cin >> K >> N; 207 | vector v_dp(K), v_rec(K); 208 | for(int i=0; i> t; v_dp[i] = mint(t); 210 | } 211 | for(int i=0; i> t; v_rec[i] = mint(t); 213 | } 214 | reverse(all(v_rec)); 215 | poly dp(v_dp), rec(v_rec); 216 | cout << kitamasa(rec, dp, N-1); 217 | } 218 | -------------------------------------------------------------------------------- /Math/Fraction.cpp: -------------------------------------------------------------------------------- 1 | // Fraction Structure 2 | 3 | struct Fraction{ 4 | ll p, q; 5 | Fraction(ll a, ll b) : p(q), q(b) { 6 | ll g = __gcd(a, b); 7 | p = a / g; 8 | q = b / g; 9 | } 10 | Fraction() : Fraction(0, 1) {} 11 | Fraction(ll x) : Fraction(x, 1) {} 12 | Fraction operator +(Fraction &x){ 13 | return Fraction(p*x.q + q*x.p, q*x.q); 14 | } 15 | Fraction operator -(Fraction &x){ 16 | return Fraction(p*x.q - q*x.p, q*x.q); 17 | } 18 | Fraction operator *(Fraction &x){ 19 | return Fraction(p*x.p, q*x.q); 20 | } 21 | Fraction operator /(Fraction &x){ 22 | return Fraction(p*x.q, q*x.p); 23 | } 24 | Fraction operator *(ll x){ 25 | return Fraction(p*x, q); 26 | } 27 | Fraction operator /(ll x){ 28 | return Fraction(p, q*x); 29 | } 30 | bool operator <(Fraction &x){ 31 | return p*x.q < x.p*q; 32 | } 33 | bool operator >(Fraction &x){ 34 | return p*x.q > x.p*q; 35 | } 36 | bool operator <=(Fraction &x){ 37 | return p*x.q <= x.p*q; 38 | } 39 | bool operator >=(Fraction &x){ 40 | return p*x.q >= x.p*q; 41 | } 42 | bool operator ==(Fraction &x){ 43 | return p*x.q == x.p*q; 44 | } 45 | Fraction abs(){ 46 | return Fraction(p > 0 ? p : -p, q > 0 ? q : -q); 47 | } 48 | }; 49 | -------------------------------------------------------------------------------- /Math/MatrixMultiply-SIMD.cpp: -------------------------------------------------------------------------------- 1 | // dependency : 2 | // matrix multiply with avx 3 | // Time Complexity : fast O(N^3) 4 | // 500 : 59ms, 1000 : 300ms, 2000 : 2400ms, 3000 : 10000ms 5 | // (normal) 500 : 120ms, 1000 : 830ms, 2000 : 5700ms 6 | 7 | #include 8 | #pragma GCC optimize("fast-math") 9 | #pragma GCC target("avx,avx2,fma") 10 | using namespace std; 11 | 12 | struct Matrix{ 13 | int n, m; float **v; 14 | void init(int N, int M){ 15 | n = N; m = M; v = (float**)malloc(sizeof(float*) * n); 16 | #ifndef LOCAL 17 | for(int i=0; i>4<<4); // for linux 18 | #else 19 | for(int i=0; i>4<<4, 256/8); // for windows 20 | #endif 21 | } 22 | ~Matrix(){ 23 | if(v) for(int i=0; i prime; 6 | void sieve(){ 7 | memset(isp, 1, sizeof isp); 8 | isp[0] = isp[1] = 0; 9 | for(ll i=2; i<=10000000; i++){ 10 | if(isp[i]) prime.push_back(i); 11 | for(auto j : prime){ 12 | if(i*j > 10000000) break; 13 | isp[i*j] = 0; 14 | if(i % j == 0) break; 15 | } 16 | } 17 | } 18 | /* 19 | +------------+---------+--------------------------------------------------+ 20 | | Range | Usage | a (a % N == 0 is prime) | 21 | +------------+---------+--------------------------------------------------+ 22 | | 1050535501 | <= 10^9 | 336781006125, 9639812373923155 | 23 | | 4759123141 | <= 2^32 | 2, 7, 61 | 24 | | ? | <= 2^64 | 2, 325, 9375, 28178, 450775, 9780504, 1795265022 | 25 | +------------+---------+--------------------------------------------------+ 26 | */ 27 | bool MR(ull n, ull a){ // Miller Rabin 28 | if(a % n == 0) return 1; 29 | int cnt = __builtin_ctzll(n-1); 30 | ull d = n >> cnt; 31 | ull p = pw(a, d, n); 32 | if(p == 1 || p == n - 1) return 1; 33 | while(cnt--){ 34 | p = mul(p, p, n); 35 | if(p == n-1) return 1; 36 | } 37 | return 0; 38 | } 39 | bool isPrime(ll n){ 40 | if(n < 10000001) return isp[n]; 41 | if(n <= 2) return n == 2; 42 | if(!(n & 1)) return 0; 43 | if(n % 3 == 0 || n % 5 == 0 || n % 7 == 0 || n % 11 == 0) return 0; 44 | for(int p : { 2, 325, 9375, 28178, 450775, 9780504, 1795265022}){ 45 | if(!MR(n, p)) return 0; 46 | } 47 | return 1; 48 | } 49 | ll rho(ll n){ 50 | while(1){ 51 | ll x = rand() % (n - 2) + 2; 52 | ll y = x, c = rand() % (n-1) + 1; 53 | while(1){ 54 | x = (mul(x, x, n) + c) % n; 55 | y = (mul(y, y, n) + c) % n; 56 | y = (mul(y, y, n) + c) % n; 57 | ll d = __gcd(abs(x - y), n); 58 | if(d == 1) continue; 59 | if(!isPrime(d)){ n = d; break; } 60 | else return d; 61 | } 62 | } 63 | } 64 | vector pollard_rho(ll n){ 65 | vector v; 66 | while(~n & 1) n >>= 1, v.push_back(2); 67 | if(n == 1) return move(v); 68 | while(!isPrime(n)){ 69 | ll d = rho(n); 70 | while(n % d == 0) v.push_back(d), n /= d; 71 | if(n == 1) break; 72 | } 73 | if(n != 1) v.push_back(n); 74 | return move(v); 75 | } -------------------------------------------------------------------------------- /Math/NTT.cpp: -------------------------------------------------------------------------------- 1 | // NTT - Polynomial Multiply with Special Modulo 2 | // Time Complexity : O(N log N) 3 | 4 | /* 5 | p = (a*2^b+1) | a b w 6 | ----------------------- 7 | 104,857,601 | 25 22 3 8 | 998,244,353 | 119 23 3 9 | 2,281,701,377 | 17 27 3 10 | 2,483,027,969 | 37 26 3 11 | 2,113,929,217 | 63 25 5 12 | 1,092,616,193 | 521 21 3 13 | */ 14 | typedef vector poly; 15 | template 16 | class NTT{ 17 | public: 18 | void ntt(poly &f, bool inv = 0){ 19 | int n = f.size(), j = 0; 20 | vector root(n/2); 21 | for(int i=1; i= bit) j -= bit, bit >>= 1; 24 | j += bit; 25 | if(i < j) swap(f[i], f[j]); 26 | } 27 | ll ang = pw(w, (mod - 1) / n, mod); if(inv) ang = pw(ang, mod - 2, mod); 28 | root[0] = 1; for(int i=1; i> 1] += mod; 37 | } 38 | } 39 | } 40 | ll t = pw(n, mod - 2, mod); 41 | if(inv) for(int i=0; i multiply(poly &_a, poly &_b){ 44 | vector a(all(_a)), b(all(_b)); 45 | int n = 2; 46 | while(n < a.size() + b.size()) n <<= 1; 47 | a.resize(n); b.resize(n); 48 | ntt(a); ntt(b); 49 | for(int i=0; i 2 | T xor_max(const vector &V){ 3 | T basis[mx_bit] = {0}; 4 | for(auto i : V){ 5 | for(int j=mx_bit-1; ~j; j--){ 6 | if(~(i >> j) & 1) continue; 7 | if(!basis[j]){ basis[j] = i; break; } 8 | i ^= basis[j]; 9 | } 10 | } 11 | T mx = 0; 12 | for(int i=mx_bit-1; ~i; i--) mx = max(mx, mx ^ basis[i]); 13 | return mx; 14 | } 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AlgorithmImplement 2 | algorithm implemention and also use as library 3 | 4 | **[https://github.com/justiceHui/icpc-teamnote](https://github.com/justiceHui/icpc-teamnote)로 옮겼습니다.** 5 | 6 | * DataStructure 7 | * ErasablePQ.cpp 8 | * HLD.cpp 9 | * LiChaoTree.cpp 10 | * O(1)LCA.cpp 11 | * O(n)CHT.cpp 12 | * SparseTableRMQ.cpp 13 | * Splay-LCT.cpp 14 | * UnionFind.cpp 15 | * TODO 16 | * Centroid 17 | * Tree Compress? 18 | * Geometry 19 | * BaseTool.cpp 20 | * DualGraph.cpp 21 | * GrahamScan.cpp 22 | * HPI.cpp 23 | * KD-Tree.cpp 24 | * PointInConvexPolygon.cpp 25 | * PointInPolygon.cpp 26 | * RotatingCalipers.cpp 27 | * SegmentIntersection.cpp 28 | * TODO 29 | * Voronoi 30 | * Graph 31 | * BipartiteMatching.cpp 32 | * Dinic.cpp 33 | * GeneralMatching.cpp 34 | * GlobalMinCut.cpp 35 | * TwoSat.cpp 36 | * zkwMCMF.cpp 37 | * TODO 38 | * BCC 39 | * MCMF 40 | * Math (TODO) 41 | * Berlekamp-Kitamasa.cpp 42 | * ExtendGCD.cpp 43 | * FFT.cpp 44 | * Fraction.cpp 45 | * MatrixMultiply-SIMD.cpp 46 | * MillerRabin-PollardRho.cpp 47 | * NTT.cpp 48 | * TODO 49 | * ModInt 50 | * **I Hate Math** 51 | * String (TODO) 52 | * Hashing.cpp 53 | * Trie.cpp 54 | * TODO 55 | * Aho-Corasick (need fast impl) 56 | * KMP 57 | * SA-LCP 58 | * misc 59 | * FastInput.cpp 60 | * Mo.cpp 61 | * mt19937.cpp 62 | * PBDS.cpp 63 | * pragma.cpp 64 | -------------------------------------------------------------------------------- /String/Hashing.cpp: -------------------------------------------------------------------------------- 1 | /****************************** 2 | Author: jhnah917(Justice_Hui) 3 | g++ -std=c++17 -DLOCAL 4 | ******************************/ 5 | 6 | #include 7 | using namespace std; 8 | 9 | using ll = long long; 10 | 11 | template struct Hashing{ 12 | vector H, B; 13 | void Build(const string &S){ 14 | H.resize(S.size()+1); 15 | B.resize(S.size()+1); 16 | B[0] = 1; 17 | for(int i=1; i<=S.size(); i++) H[i] = (H[i-1] * P + S[i-1]) % M; 18 | for(int i=1; i<=S.size(); i++) B[i] = B[i-1] * P % M; 19 | } 20 | ll sub(int s, int e){ 21 | ll res = (H[e] - H[s-1] * B[e-s+1]) % M; 22 | return res < 0 ? res + M : res; 23 | } 24 | }; 25 | 26 | constexpr int P1 = 1299709, M1 = 1'000'000'007; 27 | constexpr int P2 = 1301021, M2 = 1'000'000'009; 28 | 29 | Hashing H1; 30 | Hashing H2; 31 | 32 | pair sub(int s, int e){ 33 | return {H1.sub(s, e), H2.sub(s, e)}; 34 | } 35 | 36 | int main(){ 37 | // BOJ 1786 38 | ios_base::sync_with_stdio(false); cin.tie(nullptr); 39 | string S, P; 40 | getline(cin, S); 41 | getline(cin, P); 42 | 43 | H1.Build(P); H2.Build(P); 44 | int P_H1 = H1.H.back(); 45 | int P_H2 = H2.H.back(); 46 | 47 | H1.Build(S); H2.Build(S); 48 | 49 | vector res; 50 | for(int i=1; i+P.size()-1<=S.size(); i++){ 51 | if(sub(i, i+P.size()-1) == make_pair(P_H1, P_H2)) res.push_back(i); 52 | } 53 | 54 | cout << res.size() << "\n"; 55 | for(auto i : res) cout << i << " "; 56 | } 57 | -------------------------------------------------------------------------------- /String/Trie.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | class TrieNode{ 5 | public: 6 | bool valid; 7 | int child[26]; 8 | TrieNode(){ 9 | valid = false; 10 | for(int i=0; i<26; i++) child[i] = -1; 11 | } 12 | }; 13 | 14 | class Trie{ 15 | private: 16 | vector trie; 17 | int _newNode(){ 18 | TrieNode tmp; 19 | trie.push_back(tmp); 20 | return trie.size() - 1; 21 | } 22 | void _add(string &str, int node, int idx){ 23 | if(idx == str.size()){ 24 | trie[node].valid = true; return; 25 | } 26 | int c = str[idx] - 'A'; 27 | if(trie[node].child[c] == -1){ 28 | int next = _newNode(); 29 | trie[node].child[c] = next; 30 | } 31 | _add(str, trie[node].child[c], idx+1); 32 | } 33 | bool _exist(string &str){ 34 | int now = 0; 35 | for(int i=0; i 기본설정 > 바로 가기 키 3 | [ 4 | { "key": "f10", "command": "workbench.action.tasks.build" } 5 | { "key": "f11", "command": "workbench.action.tasks.test" } 6 | ] 7 | -------------------------------------------------------------------------------- /misc/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "type_traits": "cpp", 4 | "array": "cpp", 5 | "atomic": "cpp", 6 | "*.tcc": "cpp", 7 | "bitset": "cpp", 8 | "cctype": "cpp", 9 | "cfenv": "cpp", 10 | "chrono": "cpp", 11 | "cinttypes": "cpp", 12 | "clocale": "cpp", 13 | "cmath": "cpp", 14 | "complex": "cpp", 15 | "condition_variable": "cpp", 16 | "csetjmp": "cpp", 17 | "csignal": "cpp", 18 | "cstdarg": "cpp", 19 | "cstddef": "cpp", 20 | "cstdint": "cpp", 21 | "cstdio": "cpp", 22 | "cstdlib": "cpp", 23 | "cstring": "cpp", 24 | "ctime": "cpp", 25 | "cwchar": "cpp", 26 | "cwctype": "cpp", 27 | "deque": "cpp", 28 | "forward_list": "cpp", 29 | "list": "cpp", 30 | "unordered_map": "cpp", 31 | "unordered_set": "cpp", 32 | "vector": "cpp", 33 | "exception": "cpp", 34 | "algorithm": "cpp", 35 | "functional": "cpp", 36 | "ratio": "cpp", 37 | "system_error": "cpp", 38 | "tuple": "cpp", 39 | "fstream": "cpp", 40 | "future": "cpp", 41 | "initializer_list": "cpp", 42 | "iomanip": "cpp", 43 | "iosfwd": "cpp", 44 | "iostream": "cpp", 45 | "istream": "cpp", 46 | "limits": "cpp", 47 | "memory": "cpp", 48 | "mutex": "cpp", 49 | "new": "cpp", 50 | "ostream": "cpp", 51 | "numeric": "cpp", 52 | "scoped_allocator": "cpp", 53 | "sstream": "cpp", 54 | "stdexcept": "cpp", 55 | "streambuf": "cpp", 56 | "thread": "cpp", 57 | "regex": "cpp", 58 | "utility": "cpp", 59 | "typeindex": "cpp", 60 | "typeinfo": "cpp", 61 | "valarray": "cpp", 62 | "ios": "cpp", 63 | "iterator": "cpp", 64 | "locale": "cpp", 65 | "map": "cpp", 66 | "queue": "cpp", 67 | "random": "cpp", 68 | "set": "cpp", 69 | "stack": "cpp", 70 | "string": "cpp", 71 | "xfacet": "cpp", 72 | "xfunctional": "cpp", 73 | "xhash": "cpp", 74 | "xiosbase": "cpp", 75 | "xlocale": "cpp", 76 | "xlocbuf": "cpp", 77 | "xlocinfo": "cpp", 78 | "xlocmes": "cpp", 79 | "xlocmon": "cpp", 80 | "xlocnum": "cpp", 81 | "xloctime": "cpp", 82 | "xmemory": "cpp", 83 | "xmemory0": "cpp", 84 | "xstddef": "cpp", 85 | "xstring": "cpp", 86 | "xtr1common": "cpp", 87 | "xtree": "cpp", 88 | "xutility": "cpp", 89 | "rope": "cpp" 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /misc/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "runner": "terminal", 4 | "type": "shell", 5 | "echoCommand": true, 6 | "presentation" : { "reveal": "always" }, 7 | "tasks": [ 8 | //C++ 컴파일 9 | { 10 | "label": "save and compile for C++", 11 | "command": "g++", 12 | "args": [ 13 | "-O2", 14 | "-std=c++14", 15 | "${file}", 16 | "-o", 17 | "${fileDirname}/${fileBasenameNoExtension}", 18 | "-DLOCAL" 19 | ], 20 | "group": "build", 21 | 22 | //컴파일시 에러를 편집기에 반영 23 | //참고: https://code.visualstudio.com/docs/editor/tasks#_defining-a-problem-matcher 24 | 25 | "problemMatcher": { 26 | "fileLocation": [ 27 | "relative", 28 | "${workspaceRoot}" 29 | ], 30 | "pattern": { 31 | // The regular expression. 32 | //Example to match: helloWorld.c:5:3: warning: implicit declaration of function 'prinft' 33 | "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning error):\\s+(.*)$", 34 | "file": 1, 35 | "line": 2, 36 | "column": 3, 37 | "severity": 4, 38 | "message": 5 39 | } 40 | } 41 | }, 42 | //C 컴파일 43 | { 44 | "label": "save and compile for C", 45 | "command": "gcc", 46 | "args": [ 47 | "${file}", 48 | "-o", 49 | "${fileDirname}/${fileBasenameNoExtension}" 50 | ], 51 | "group": "build", 52 | 53 | //컴파일시 에러를 편집기에 반영 54 | //참고: https://code.visualstudio.com/docs/editor/tasks#_defining-a-problem-matcher 55 | 56 | "problemMatcher": { 57 | "fileLocation": [ 58 | "relative", 59 | "${workspaceRoot}" 60 | ], 61 | "pattern": { 62 | // The regular expression. 63 | //Example to match: helloWorld.c:5:3: warning: implicit declaration of function 'prinft' 64 | "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning error):\\s+(.*)$", 65 | "file": 1, 66 | "line": 2, 67 | "column": 3, 68 | "severity": 4, 69 | "message": 5 70 | } 71 | } 72 | }, 73 | // 바이너리 실행(Ubuntu) 74 | // { 75 | // "label": "execute", 76 | // "command": "cd ${fileDirname} && ./${fileBasenameNoExtension}", 77 | // "group": "test" 78 | // } 79 | // 바이너리 실행(Windows) 80 | { 81 | "label": "execute", 82 | "command": "cmd", 83 | "group": "test", 84 | "args": [ 85 | "/C", "${fileDirname}\\${fileBasenameNoExtension}" 86 | ] 87 | 88 | } 89 | ] 90 | } 91 | -------------------------------------------------------------------------------- /misc/FastInput.cpp: -------------------------------------------------------------------------------- 1 | inline int readChar(); 2 | template inline T readInt(); 3 | template inline void writeInt(T x, char end = 0); 4 | inline void writeChar(int x); 5 | inline void writeWord(const char *s); 6 | static const int buf_size = 1 << 18; 7 | inline int getChar(){ 8 | #ifndef LOCAL 9 | static char buf[buf_size]; 10 | static int len = 0, pos = 0; 11 | if(pos == len) pos = 0, len = fread(buf, 1, buf_size, stdin); 12 | if(pos == len) return -1; 13 | return buf[pos++]; 14 | #endif 15 | } 16 | inline int readChar(){ 17 | #ifndef LOCAL 18 | int c = getChar(); 19 | while(c <= 32) c = getChar(); 20 | return c; 21 | #else 22 | char c; cin >> c; return c; 23 | #endif 24 | } 25 | template 26 | inline T readInt(){ 27 | #ifndef LOCAL 28 | int s = 1, c = readChar(); 29 | T x = 0; 30 | if(c == '-') s = -1, c = getChar(); 31 | while('0' <= c && c <= '9') x = x * 10 + c - '0', c = getChar(); 32 | return s == 1 ? x : -x; 33 | #else 34 | T x; cin >> x; return x; 35 | #endif 36 | } 37 | static int write_pos = 0; 38 | static char write_buf[buf_size]; 39 | inline void writeChar(int x){ 40 | if(write_pos == buf_size) fwrite(write_buf, 1, buf_size, stdout), write_pos = 0; 41 | write_buf[write_pos++] = x; 42 | } 43 | template 44 | inline void writeInt(T x, char end){ 45 | if(x < 0) writeChar('-'), x = -x; 46 | char s[24]; int n = 0; 47 | while(x || !n) s[n++] = '0' + x % 10, x /= 10; 48 | while(n--) writeChar(s[n]); 49 | if(end) writeChar(end); 50 | } 51 | inline void writeWord(const char *s){ 52 | while(*s) writeChar(*s++); 53 | } 54 | struct Flusher{ 55 | ~Flusher(){ if(write_pos) fwrite(write_buf, 1, write_pos, stdout), write_pos = 0; } 56 | }flusher; -------------------------------------------------------------------------------- /misc/Mo.cpp: -------------------------------------------------------------------------------- 1 | // dependency : 2 | // Mo's Algorithm 3 | // Time Complexity : O((N+Q) sqrt N T(N)) 4 | 5 | struct Query{ 6 | int s, e, x; 7 | bool operator < (const Query &t) const { 8 | return tie(s/400, e) < tie(t.s/400, t.e); 9 | } 10 | }; 11 | 12 | while(qry[i].s < l) insert(--l); 13 | while(qry[i].e > r) insert(++r); 14 | while(qry[i].s > l) erase(l++); 15 | while(qry[i].e < r) erase(r--); 16 | res[qry[i].x] = get(); -------------------------------------------------------------------------------- /misc/PBDS.cpp: -------------------------------------------------------------------------------- 1 | // dependency : 2 | // how to use pbds (ordered_set, crope) 3 | 4 | #include 5 | #include 6 | #include 7 | //using namespace __gnu_pbds; //ordered_set : find_by_order(order), order_of_key(key) 8 | //using namespace __gnu_cxx; //crope : append(str), substr(s, e), at(idx) 9 | /*template 10 | using ordered_set = tree, rb_tree_tag, tree_order_statistics_node_update>;*/ -------------------------------------------------------------------------------- /misc/mt19937.cpp: -------------------------------------------------------------------------------- 1 | // dependency : 2 | // how to use mt19937 3 | 4 | int rand(mt19937 &rd, int l, int r){ 5 | // mt19937 rd((unsigned)chrono::steady_clock::now().time_since_epoch().count()); 6 | // mt19937 rd(0x917917); 7 | uniform_int_distribution rnd(l, r); 8 | return rnd(rd); 9 | } -------------------------------------------------------------------------------- /misc/pragma.cpp: -------------------------------------------------------------------------------- 1 | # pragma GCC optimize ("O3") 2 | # pragma GCC optimize ("Ofast") 3 | # pragma GCC optimize ("unroll-loops") 4 | # pragma GCC target ("avx,avx2,fma") --------------------------------------------------------------------------------