├── README.md ├── .gitignore ├── Math ├── combinatorics.cpp ├── Random.cpp ├── SparseSquareMatrix.cpp ├── Kitamasa.cpp ├── FFT.cpp ├── Mod.cpp ├── Math.cpp ├── SquareMatrix.cpp ├── SparseMatrix.cpp ├── Matrix.cpp └── Polynomial.cpp ├── .vimrc ├── Template.cpp ├── Tex ├── src │ ├── String.tex │ ├── Template.tex │ ├── Others.tex │ ├── Geometry.tex │ ├── Math.tex │ ├── Structure.tex │ ├── Tips.tex │ └── Graph.tex └── Main.tex ├── Others ├── LowerBound.cpp ├── Compressor.cpp ├── LIS.cpp ├── Cout.cpp ├── LCS.cpp ├── RegularOctahedron.cpp ├── Dice.cpp ├── Poker.cpp └── Subsets.cpp ├── .emacs ├── .Xmodmap ├── String ├── ZAlgorithm.cpp ├── Manacher.cpp ├── KMP.cpp ├── RollingHash.cpp ├── SuffixArray.cpp └── AhoCorasick.cpp ├── Structure ├── SlideMin.cpp ├── check │ ├── stlu_check4.cpp │ ├── stlu_check3.cpp │ ├── stlu_check2.cpp │ ├── stlu_check1.cpp │ ├── stlu_check5.cpp │ └── checker.cpp ├── UnionFind.cpp ├── ConvexHullTrick.cpp ├── SegmentTree2D.cpp ├── SegmentTree.cpp ├── SegmentTreeDual.cpp ├── FenwickTree.cpp ├── SkewHeapDijkstra.cpp ├── SegmentTreePersistent.cpp ├── Treap.cpp ├── RBST.cpp ├── PartitionTree.cpp ├── SkewHeap.cpp ├── UnionFindPersistent.cpp ├── BigRangeQuery.cpp ├── SegmentTreeLazy.cpp ├── kdTree.cpp ├── SqrtDecomposition.cpp └── SegmentTreeLazyUniversal.cpp ├── Geometry ├── Visualize.html ├── Geometry.cpp ├── Polygon.cpp ├── Arrangement.cpp ├── CircleRange.cpp ├── Convex.cpp ├── DualGraph.cpp ├── Visualize.cpp ├── 3DGeometry.cpp └── Intersect.cpp ├── Graph ├── ChromaticNumber.cpp ├── LCA(RMQ).cpp ├── GlobalMinimumCut.cpp ├── BipartiteMatching.cpp ├── LCA(BinarySearch).cpp ├── MaximumIndependentSet.cpp ├── Hungarian.cpp ├── MinimumSpanningTree.cpp ├── FordFulkerson.cpp ├── RecessionAnalysis.cpp ├── ShortestHamiltonPath.cpp ├── HopcroftKarp.cpp ├── Bridge.cpp ├── LCA(Structure).cpp ├── 2SAT.cpp ├── StronglyConnectedComponents.cpp ├── Dinic.cpp ├── ArticulationPoints.cpp ├── MinimumArborescence.cpp ├── EulerPath.cpp ├── MinCostFlow.cpp ├── HLD.cpp ├── ZDD.cpp └── ShortestPath.cpp └── library.sh /README.md: -------------------------------------------------------------------------------- 1 | 2 | #Primasta Team Library 3 | 4 | --- 5 | 6 | ICPCのチームライブラリ 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.aux 2 | *.dvi 3 | *.log 4 | *.out 5 | *.pdf 6 | *.ps 7 | *.toc 8 | test.cpp 9 | -------------------------------------------------------------------------------- /Math/combinatorics.cpp: -------------------------------------------------------------------------------- 1 | // zeta 2 | REP(i,n) REP(j,1< 2 | 3 | #define REP(i,n) for(int i=0;i<(int)(n);i++) 4 | #define ALL(x) (x).begin(),(x).end() 5 | 6 | using namespace std; 7 | 8 | int main() { 9 | 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /Tex/src/String.tex: -------------------------------------------------------------------------------- 1 | \section{String} 2 | 3 | \subsection{KMP} 4 | \lstinputlisting{../String/KMP.cpp} 5 | 6 | \subsection{Aho-Corasick} 7 | \lstinputlisting{../String/AhoCorasick.cpp} 8 | 9 | \subsection{Suffix Array} 10 | \lstinputlisting{../String/SuffixArray.cpp} 11 | -------------------------------------------------------------------------------- /Others/LowerBound.cpp: -------------------------------------------------------------------------------- 1 | using Data = int; 2 | int N, K; 3 | int a[1024]; 4 | 5 | int LowerBound(Data k) { 6 | int lb = -1, ub = N; 7 | while (ub - lb > 1) { 8 | int mid = (lb + ub) / 2; 9 | if (a[mid] >= K) ub = mid; else lb = mid; 10 | } 11 | return ub; 12 | } 13 | -------------------------------------------------------------------------------- /Others/Compressor.cpp: -------------------------------------------------------------------------------- 1 | using Data = int; 2 | vector compressor(vector c) { 3 | const int n = c.size(); 4 | vector v = c; 5 | vector res(n); 6 | sort(v.begin(), v.end()); 7 | auto it = unique(ALL(v)); 8 | REP(i,n) res[i] = lower_bound(begin(v), it, c[i]) - begin(v); 9 | return res; 10 | } 11 | -------------------------------------------------------------------------------- /.emacs: -------------------------------------------------------------------------------- 1 | (setq backup-inhibited t) 2 | (setq auto-save-default nil) 3 | 4 | (column-number-mode t) 5 | (setq-default tab-width 2 indent-tabs-mode nil) 6 | 7 | (global-set-key "\C-h" 'delete-backward-char) 8 | 9 | (setq indent-line-function 'indent-relative-maybe) 10 | (global-set-key "\C-m" 'newline-and-indent) 11 | (global-set-key (kbd "C-/") 'undo) 12 | -------------------------------------------------------------------------------- /Tex/src/Template.tex: -------------------------------------------------------------------------------- 1 | \section{Template} 2 | 3 | \subsection{テンプレート} 4 | \lstinputlisting{../Template.cpp} 5 | 6 | \subsection{emacs設定ファイル} 7 | \lstinputlisting{../.emacs} 8 | 9 | \subsection{vim設定ファイル} 10 | \lstinputlisting{../.vimrc} 11 | 12 | \subsection{Xmodmap} 13 | CtrlとCapsLockの交換,あるいはCapsLockのCtrlへの変更を行うこと. 14 | \lstinputlisting{../.Xmodmap} 15 | -------------------------------------------------------------------------------- /.Xmodmap: -------------------------------------------------------------------------------- 1 | ! 2 | ! Change Caps_Lock to Ctrl 3 | ! % xmodmap .Xmodmap 4 | ! 5 | remove Lock = Caps_Lock 6 | keysym Caps_Lock = Control_L 7 | add Control = Control_L 8 | 9 | ! 10 | ! Swap Ctrl and Caps_Lock 11 | ! % xmodmap .Xmodmap 12 | ! 13 | remove Lock = Caps_Lock 14 | remove Control = Control_L 15 | keysym Control_L = Caps_Lock 16 | keysym Caps_Lock = Control_L 17 | add Lock = Caps_Lock 18 | add Control = Control_L 19 | -------------------------------------------------------------------------------- /String/ZAlgorithm.cpp: -------------------------------------------------------------------------------- 1 | vector zalgorithm(const string &s) { 2 | int n = s.size(); 3 | vector a(n); 4 | a[0] = n; 5 | int i = 1, j = 0; 6 | while (i < n) { 7 | while (i + j < n && s[j] == s[i + j]) ++j; 8 | a[i] = j; 9 | if (j == 0) { ++i; continue;} 10 | int k = 1; 11 | while (i + k < n && k + a[k] < j) a[i + k] = a[k], ++k; 12 | i += k; 13 | j -= k; 14 | } 15 | return a; 16 | } 17 | -------------------------------------------------------------------------------- /Structure/SlideMin.cpp: -------------------------------------------------------------------------------- 1 | using Data = int; 2 | 3 | struct SlideMin { 4 | deque> deq; 5 | int c, w; 6 | SlideMin(int w) : c(0), w(w) {;} 7 | Data query(Data d) { 8 | ++c; 9 | while (!deq.empty() && deq.front().first <= c - w) deq.pop_front(); 10 | while (!deq.empty() && deq.back().second >= d) deq.pop_back(); 11 | deq.push_back(make_pair(c, d)); 12 | return deq.front().second; 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /Structure/check/stlu_check4.cpp: -------------------------------------------------------------------------------- 1 | // Range Set - Range Sum (Unverified) 2 | struct Data { 3 | int num; 4 | Data() : num(0) {;} 5 | Data(int n) : num(n) {;} 6 | }; 7 | 8 | const Data identity = Data(0); 9 | 10 | inline Data Merge(Data left, Data right) { return Data(left.num + right.num); } 11 | inline Data Set(Data lazy, Data val) { return val; } 12 | inline Data Eval(Data data, Data lazy, int num) { return Data(lazy.num * num); } 13 | -------------------------------------------------------------------------------- /Structure/check/stlu_check3.cpp: -------------------------------------------------------------------------------- 1 | // Range Set - Range Min (Unverified) 2 | struct Data { 3 | int num; 4 | Data() : num(1000000000) {;} 5 | Data(int n) : num(n) {;} 6 | }; 7 | 8 | const Data identity = Data(1000000000); 9 | 10 | inline Data Merge(Data left, Data right) { return Data(min(left.num, right.num)); } 11 | inline Data Set(Data lazy, Data val) { return val; } 12 | inline Data Eval(Data data, Data lazy, int num) { return lazy; } 13 | -------------------------------------------------------------------------------- /String/Manacher.cpp: -------------------------------------------------------------------------------- 1 | // 奇数長の回文のみ検出(偶数長もほしい場合, ダミー文字を挟むこと) 2 | vector manacher(const string &s) { 3 | int n = s.size(); 4 | vector rad(n); 5 | int i = 0, j = 0; 6 | while (i < n) { 7 | while (i - j >= 0 && i + j < n && s[i - j] == s[i + j]) ++j; 8 | rad[i] = j; 9 | int k = 1; 10 | while (i - k >= 0 && i + k < n && k + rad[i - k] < j) rad[i + k] = rad[i - k], ++k; 11 | i += k; 12 | j -= k; 13 | } 14 | return rad; 15 | } 16 | -------------------------------------------------------------------------------- /Structure/check/stlu_check2.cpp: -------------------------------------------------------------------------------- 1 | // Range Add - Range Sum (Unverified) 2 | struct Data { 3 | int num; 4 | Data() : num(0) {;} 5 | Data(int n) : num(n) {;} 6 | }; 7 | 8 | const Data identity = Data(0); 9 | 10 | inline Data Merge(Data left, Data right) { return Data(left.num + right.num); } 11 | inline Data Set(Data lazy, Data val) { return Data(lazy.num + val.num); } 12 | inline Data Eval(Data data, Data lazy, int num) { return Data(data.num + lazy.num * num); } 13 | -------------------------------------------------------------------------------- /Geometry/Visualize.html: -------------------------------------------------------------------------------- 1 | 2 | visualizer 3 | 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Graph/ChromaticNumber.cpp: -------------------------------------------------------------------------------- 1 | using Weight = int; 2 | Weight INF = 1000000000; 3 | 4 | using Array = vector; 5 | using Matrix = vector; 6 | 7 | int chromaticNumber(const Matrix &g) { 8 | int N = g.size(); 9 | Array dp(1< ok(1< lis(const vector& a) { 5 | const int n = a.size(); 6 | if (n == 0) return vector(0); 7 | vector A(n, INF); 8 | vector id(n); 9 | for (int i = 0; i < n; i++) { 10 | id[i] = distance(A.begin(), lower_bound(A.begin(), A.end(), a[i])); 11 | A[id[i]] = a[i]; 12 | } 13 | int m = *max_element(id.begin(), id.end()); 14 | vector res(m + 1); 15 | for (int i = n - 1; i >= 0; i--) 16 | if (id[i] == m) res[m--] = a[i]; 17 | return res; 18 | } 19 | -------------------------------------------------------------------------------- /Structure/check/stlu_check1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | #define REP(i,n) for(int i = 0; i < (int)(n); ++i) 6 | // Range Add - Range Min (Verified: SPOJ61) 7 | struct Data { 8 | int64_t num; 9 | Data() : num(0) {;} 10 | Data(int n) : num(n) {;} 11 | }; 12 | 13 | const Data identity = Data(1000000000); 14 | 15 | inline Data Merge(Data left, Data right) { return Data(min(left.num, right.num)); } 16 | inline Data Set(Data lazy, Data val) { return Data(lazy.num + val.num); } 17 | inline Data Eval(Data data, Data lazy, int num) { return Data(data.num + lazy.num); } 18 | 19 | -------------------------------------------------------------------------------- /Math/Random.cpp: -------------------------------------------------------------------------------- 1 | // xoroshiro128plus (http://xoroshiro.di.unimi.it/xoroshiro128plus.c) 2 | // License: CC0 1.0 3 | // See . 4 | 5 | // seed must not be {0, 0} 6 | uint64_t s[2] = { 0xbeac0467eba5facb, 0xd86b048b86aa9922 }; 7 | 8 | static inline uint64_t rotl(const uint64_t x, int k) { 9 | return (x << k) | (x >> (64 - k)); 10 | } 11 | 12 | uint64_t rnd(void) { 13 | const uint64_t s0 = s[0]; 14 | uint64_t s1 = s[1]; 15 | const uint64_t result = s0 + s1; 16 | 17 | s1 ^= s0; 18 | s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b 19 | s[1] = rotl(s1, 36); // c 20 | 21 | return result; 22 | } 23 | -------------------------------------------------------------------------------- /Graph/LCA(RMQ).cpp: -------------------------------------------------------------------------------- 1 | #define MAX_V 100 2 | int root, V; 3 | 4 | vector g[MAX_V]; 5 | int vs[2 * MAX_V - 1]; 6 | int depth[2 * MAX_V - 1]; 7 | int id[MAX_V]; 8 | 9 | void dfs(int v, int p, int d, int &k) { 10 | id[v] = k; 11 | vs[k] = v; 12 | depth[k++] = d; 13 | REP(i, g.size()) { 14 | if (g[v][i] != p) { 15 | dfs(g[v][i], v, d + 1, k); 16 | vs[k] = v; 17 | depth[k++] = d; 18 | } 19 | } 20 | } 21 | 22 | void init(void) { 23 | int k = 0; 24 | dfs(root, -1, 0, k); 25 | rmq_init(depth, 2 * V - 1); 26 | } 27 | 28 | int lca(int u, int v) { 29 | return vs[query(min(id[u], id[v]) , max(id[u], id[v]) + 1)]; 30 | } 31 | -------------------------------------------------------------------------------- /Structure/check/stlu_check5.cpp: -------------------------------------------------------------------------------- 1 | // Range Add, Set - Range Sum (Unverified) 2 | struct Data { 3 | int type; // 0:data, 1:add, 2:set 4 | int num; 5 | Data() : type(0), num(0) {;} 6 | Data(int t, int n) : type(t), num(n) {;} 7 | }; 8 | 9 | const Data identity = Data(0, 0); 10 | 11 | inline Data Merge(Data left, Data right) { return Data(0, left.num + right.num); } 12 | inline Data Set(Data lazy, Data val) { 13 | if (val.type == 2) return val; 14 | lazy.num += val.num; return lazy; 15 | } 16 | inline Data Eval(Data data, Data lazy, int num) { 17 | if (lazy.type == 2) return Data(0, lazy.num * num); 18 | return Data(0, data.num + lazy.num * num); 19 | } 20 | -------------------------------------------------------------------------------- /Tex/src/Others.tex: -------------------------------------------------------------------------------- 1 | \section{Others} 2 | 3 | \subsection{二分探索} 4 | チーム内で実装は統一しておいたほうがよい 5 | \lstinputlisting{../Others/LowerBound.cpp} 6 | 7 | \subsection{座標圧縮} 8 | \lstinputlisting{../Others/Compressor.cpp} 9 | 10 | \subsection{サイコロ} 11 | 六面体サイコロ 12 | \lstinputlisting{../Others/Dice.cpp} 13 | 八面体サイコロ 14 | \lstinputlisting{../Others/RegularOctahedron.cpp} 15 | 16 | \subsection{ポーカー役判定・勝利判定} 17 | \lstinputlisting{../Others/Poker.cpp} 18 | 19 | \subsection{最長増加部分列} 20 | upperboundにすると,最長非減少部分列を求められる. 21 | \lstinputlisting{../Others/LIS.cpp} 22 | 23 | \subsection{最長共通部分列} 24 | \lstinputlisting{../Others/LCS.cpp} 25 | 26 | \subsection{出力} 27 | 困った時は出力 28 | \lstinputlisting{../Others/Cout.cpp} 29 | -------------------------------------------------------------------------------- /Structure/UnionFind.cpp: -------------------------------------------------------------------------------- 1 | struct UnionFind { 2 | vector parent; 3 | UnionFind (int n) : parent(n, -1) {} 4 | int root(int x) { return parent[x] < 0 ? x : parent[x] = root(parent[x]); } 5 | bool merge(int x, int y) { 6 | x = root(x); y = root(y); 7 | if (x == y) return false; 8 | if (parent[y] < parent[x]) swap(x, y); 9 | if (parent[x] == parent[y]) --parent[x]; 10 | parent[y] = x; 11 | return true; 12 | } 13 | }; 14 | 15 | // Light version 16 | 17 | struct UnionFind { 18 | vector p; 19 | UnionFind (int n) : p(n, -1) {} 20 | int root(int x) { return p[x] < 0 ? x : p[x] = root(p[x]); } 21 | void merge(int x, int y) { if (root(x) != root(y)) p[root(y)] = x; } 22 | }; 23 | -------------------------------------------------------------------------------- /String/KMP.cpp: -------------------------------------------------------------------------------- 1 | struct KMP { 2 | string P; 3 | vector f; 4 | KMP (const string &str) { 5 | P = str; 6 | int n = P.size(), k = 0; 7 | f.assign(n, 0); 8 | f[0] = 0; 9 | for (int i = 1; i < n; ++i) { 10 | while (k > 0 && P[k] != P[i]) k = f[k-1]; 11 | if (P[k] == P[i]) ++k; 12 | f[i] = k; 13 | } 14 | } 15 | vector query(const string &T) { 16 | int n = P.size(), L = T.size(), k = 0; 17 | vector res; 18 | for (int i = 0; i < L; ++i) { 19 | while (k > 0 && P[k] != T[i]) k = f[k-1]; 20 | if (P[k] == T[i]) ++k; 21 | if (k == n) { 22 | res.push_back(i - n + 1); 23 | k = f[k-1]; 24 | } 25 | } 26 | return res; 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /Structure/ConvexHullTrick.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct ConvexHullTrick { 3 | deque> l; 4 | bool check(pair l3) { 5 | const auto l1 = *prev(end(l), 2); 6 | const auto l2 = *prev(end(l), 1); 7 | Data a = (l2.first - l1.first) * (l3.second - l2.second); 8 | Data b = (l2.second - l1.second) * (l3.first - l2.first); 9 | return a >= b; 10 | } 11 | void add(Data a, Data b) { 12 | pair n(a, b); 13 | while ((int)l.size() >= 2 && check(n)) l.pop_back(); 14 | l.emplace_back(n); 15 | } 16 | Data f(int k, Data x) { return l[k].first * x + l[k].second; } 17 | Data query(Data x){ 18 | while ((int)l.size() >= 2 && f(0, x) >= f(1, x)) l.pop_front(); 19 | return f(0, x); 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /String/RollingHash.cpp: -------------------------------------------------------------------------------- 1 | // Verified: AOJ2444 2 | 3 | class RollingHash { 4 | const int n; 5 | static const ll moda = 1000000000000037LL; 6 | static const ll modb = 1000000000000091LL; 7 | static const ll pa = 17LL; 8 | static const ll pb = 19LL; 9 | vector a, b, p, q; 10 | public: 11 | RollingHash (const string &str) : 12 | n(str.size()), a(n+1, 0), b(n+1, 0), p(n+1, 1), q(n+1, 1) { 13 | REP(i,n) a[i+1] = (a[i] * pa + str[i]) % moda; 14 | REP(i,n) b[i+1] = (b[i] * pb + str[i]) % modb; 15 | REP(i,n) p[i+1] = p[i] * pa % moda; 16 | REP(i,n) q[i+1] = q[i] * pb % modb; 17 | } 18 | pair query(int l, int r) { 19 | return make_pair(((__int128)p[r - l] * a[l] - a[r] + moda) % moda, 20 | ((__int128)q[r - l] * b[l] - b[r] + modb) % modb); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /Tex/src/Geometry.tex: -------------------------------------------------------------------------------- 1 | \section{Geometry} 2 | 3 | \subsection{基本セット} 4 | \lstinputlisting{../Geometry/Geometry.cpp} 5 | 6 | \subsection{交点} 7 | tangent系は,線分ではなくて直線を求めていることに注意.(端点が接点とは限らない) 8 | \lstinputlisting{../Geometry/Intersect.cpp} 9 | 10 | \subsection{凸包} 11 | \lstinputlisting{../Geometry/Convex.cpp} 12 | 13 | \subsection{多角形} 14 | \lstinputlisting{../Geometry/Polygon.cpp} 15 | 16 | \subsection{線分アレンジメント} 17 | \lstinputlisting{../Geometry/Arrangement.cpp} 18 | 19 | \subsection{平面グラフの双対グラフ} 20 | \lstinputlisting{../Geometry/DualGraph.cpp} 21 | 22 | \subsection{角度範囲ライブラリ} 23 | \lstinputlisting{../Geometry/CircleRange.cpp} 24 | 25 | \subsection{3次元幾何} 26 | \lstinputlisting{../Geometry/3DGeometry.cpp} 27 | 28 | \subsection{ビジュアライザ} 29 | \lstinputlisting{../Geometry/Visualize.html} 30 | \lstinputlisting{../Geometry/Visualize.cpp} 31 | -------------------------------------------------------------------------------- /Graph/GlobalMinimumCut.cpp: -------------------------------------------------------------------------------- 1 | using Weight = int; 2 | Weight INF = 1000000000; 3 | using Array = vector; 4 | using Matrix = vector; 5 | 6 | // StoerWagner (Verified: POJ2914) 7 | Weight global_minimum_cut(Matrix h) { 8 | int N = h.size(); 9 | vector V(N); REP(u, N) V[u] = u; 10 | Weight cut = INF; 11 | for(int m = N; m > 1; m--) { 12 | vector ws(m, 0); 13 | int u, v = -1; 14 | Weight w; 15 | REP(k, m) { 16 | u = v; 17 | v = max_element(ws.begin(), ws.end()) - ws.begin(); 18 | w = ws[v]; 19 | ws[v] = -1; 20 | REP(i, m) if (ws[i] >= 0) ws[i] += h[V[v]][V[i]]; 21 | } 22 | REP(i, m) { 23 | h[V[i]][V[u]] += h[V[i]][V[v]]; 24 | h[V[u]][V[i]] += h[V[v]][V[i]]; 25 | } 26 | V.erase(V.begin() + v); 27 | cut = min(cut, w); 28 | } 29 | return cut; 30 | } 31 | -------------------------------------------------------------------------------- /Graph/BipartiteMatching.cpp: -------------------------------------------------------------------------------- 1 | class BipartiteMatching { 2 | int V; 3 | vector> g; 4 | vector match; 5 | vector used; 6 | bool dfs(int v) { 7 | used[v] = true; 8 | for (int u: g[v]) { 9 | int w = match[u]; 10 | if (w < 0 || (!used[w] && dfs(w))) { 11 | match[v] = u; match[u] = v; 12 | return true; 13 | } 14 | } 15 | return false; 16 | } 17 | public: 18 | BipartiteMatching (int v) : V(v), g(v), match(v), used(v) {} 19 | void add_edge(int u, int v) { 20 | g[u].push_back(v); 21 | g[v].push_back(u); 22 | } 23 | int maximum_matching(void) { 24 | int res = 0; 25 | fill (ALL(match), -1); 26 | REP(v, V) { 27 | if (match[v] < 0) { 28 | fill (ALL(used), 0); 29 | if (dfs(v)) res++; 30 | } 31 | } 32 | return res; 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /Structure/SegmentTree2D.cpp: -------------------------------------------------------------------------------- 1 | struct Seg2D{ 2 | int n; vector data; 3 | Seg2D(int H, int W) : n(1 << H), data(n * 2, SegmentTree(W)) {} 4 | void update (int posi, int posj, Data value) { 5 | data[posi].update(posj, value); 6 | while (posi < 2*n-1) { 7 | int l = posi, r = posi^1; 8 | posi = posi / 2 + n; 9 | data[posi].update(posj, Merge(data[l].data[posj], data[r].data[posj])); 10 | } 11 | } 12 | Data sub(int T, int B, int L, int R, int node, int la, int ra){ 13 | if (ra<=T || B<=la) return Data(); 14 | if (T<=la && ra<=B) return data[node].query(L,R); 15 | Data vl = sub(T, B, L, R, (node-n)*2+0, la, (la+ra)/2); 16 | Data vr = sub(T, B, L, R, (node-n)*2+1, (la+ra)/2, ra); 17 | return Merge(vl, vr); 18 | } 19 | Data query(int T, int B, int L, int R) { 20 | return sub(T,B,L,R,2*n-2,0,n); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /Tex/src/Math.tex: -------------------------------------------------------------------------------- 1 | \section{Math} 2 | 3 | \subsection{基本セット} 4 | \lstinputlisting{../Math/Math.cpp} 5 | 6 | \subsection{Mod} 7 | \lstinputlisting{../Math/Mod.cpp} 8 | 9 | \subsection{行列} 10 | \lstinputlisting{../Math/Matrix.cpp} 11 | \lstinputlisting{../Math/SquareMatrix.cpp} 12 | 13 | \subsection{疎行列} 14 | \lstinputlisting{../Math/SparseMatrix.cpp} 15 | \lstinputlisting{../Math/SparseSquareMatrix.cpp} 16 | 17 | \subsection{高速フーリエ変換} 18 | convolutionの返すvectorのサイズは,$2^n$ である. 19 | \lstinputlisting{../Math/FFT.cpp} 20 | 21 | \subsection{キタマサ法} 22 | \lstinputlisting{../Math/Kitamasa.cpp} 23 | 24 | \subsection{多項式} 25 | \lstinputlisting{../Math/Polynomial.cpp} 26 | 27 | \subsection{高速ゼータ変換,高速メビウス変換} 28 | \begin{itemize} 29 | \item 高速ゼータ変換 : $g(S) = \displaystyle\sum_{S \subset T} f(T)$ 30 | \item 高速メビウス変換 : $g(S) = \displaystyle\sum_{T \subset S} f(T)$ 31 | \end{itemize} 32 | \lstinputlisting{../Math/combinatorics.cpp} 33 | -------------------------------------------------------------------------------- /Graph/LCA(BinarySearch).cpp: -------------------------------------------------------------------------------- 1 | #define MAX_V 100000 2 | #define LOG_V 17 3 | int root, V; 4 | vector g[MAX_V]; 5 | 6 | int parent[LOG_V][MAX_V]; 7 | int depth[MAX_V]; 8 | 9 | void dfs(int v, int p, int d) { 10 | parent[0][v] = p; 11 | depth[v] = d; 12 | REP(i, g[v].size()) if (g[v][i] != p) dfs(g[v][i], v, d + 1); 13 | } 14 | 15 | void init(void) { 16 | dfs(root, -1, 0); 17 | REP(k, LOG_V - 1) REP(v, V) { 18 | if (parent[k][v] < 0) parent[k + 1][v] = -1; 19 | else parent[k + 1][v] = parent[k][parent[k][v]]; 20 | } 21 | } 22 | 23 | int lca(int u, int v) { 24 | if (depth[u] > depth[v]) swap(u, v); 25 | REP(k, LOG_V) if (((depth[v] - depth[u]) >> k) & 1) v = parent[k][v]; 26 | if (u == v) return u; 27 | for (int k = LOG_V - 1; k >= 0; k--) { 28 | if (parent[k][u] != parent[k][v]) { 29 | u = parent[k][u]; 30 | v = parent[k][v]; 31 | } 32 | } 33 | return parent[0][u]; 34 | } 35 | -------------------------------------------------------------------------------- /Graph/MaximumIndependentSet.cpp: -------------------------------------------------------------------------------- 1 | #define MAX_V 100 2 | 3 | //O(n*1.4656^n) 4 | vector MaximumIndependentSet(vector>& g, bitset usable) { 5 | int n=g.size(); 6 | int v=-1; 7 | vector res; 8 | REP(i,n) { 9 | if(!usable[i]) continue; 10 | int neigh = (usable & g[i]).count(); 11 | if (neigh <= 1) { 12 | usable[i] = false; 13 | usable &= ~g[i]; 14 | res.push_back(i); 15 | } 16 | } 17 | REP(i,n) { 18 | if(!usable[i]) continue; 19 | v = i; 20 | } 21 | if (v < 0) return res; 22 | usable[v] = false; 23 | bitset used = usable & ~g[v]; 24 | auto res1 = MaximumIndependentSet(g, used); 25 | res1.push_back(v); 26 | auto res2 = MaximumIndependentSet(g, usable); 27 | if (res1.size() > res2.size()) 28 | res.insert(end(res),begin(res1),end(res1)); 29 | else 30 | res.insert(end(res),begin(res2),end(res2)); 31 | return res; 32 | } 33 | -------------------------------------------------------------------------------- /Graph/Hungarian.cpp: -------------------------------------------------------------------------------- 1 | Weight hungarian(const Matrix &a) { 2 | int n = a.size(), p, q; 3 | Array fx(n, inf), fy(n, 0); 4 | vector x(n, -1), y(n, -1); 5 | for (int i = 0; i < n; ) { 6 | vector t(n, -1), s(n+1, i); 7 | for (p = q = 0; p <= q && x[i] < 0; ++p) 8 | for (int k = s[p], j = 0; j < n && x[i] < 0; ++j) 9 | if (fx[k] + fy[j] == a[k][j] && t[j] < 0) { 10 | s[++q] = y[j], t[j] = k; 11 | if (s[q] < 0) 12 | for (p = j; p >= 0; j = p) 13 | y[j] = k = t[j], p = x[k], x[k] = j; 14 | } 15 | if (x[i] < 0) { 16 | Weight d = inf; 17 | for (int k = 0; k <= q; ++k) 18 | REP(j,n) 19 | if (t[j] < 0) d = min(d, fx[s[k]] + fy[j] - a[s[k]][j]); 20 | REP(j,n) fy[j] += (t[j] < 0 ? 0 : d); 21 | for (int k = 0; k <= q; ++k) fx[s[k]] -= d; 22 | } else ++i; 23 | } 24 | Weight ret = 0; 25 | REP(i,n) ret += a[i][x[i]]; 26 | return ret; 27 | } 28 | -------------------------------------------------------------------------------- /Geometry/Geometry.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using ld = long double; 4 | using P = complex; 5 | using VP = vector

; 6 | const ld eps = 1e-8, pi = acos(-1.0); 7 | 8 | #define EQ(a,b) (abs((a)-(b)) eps) return 1; // counter clockwise 27 | if (cross(b, c) < -eps) return -1; // clockwise 28 | if (dot(b, c) < 0) return 2; // c--a--b on line 29 | if (norm(b) < norm(c)) return -2; // a--b--c on line 30 | return 0; // a--c--b on line 31 | } 32 | -------------------------------------------------------------------------------- /Others/Cout.cpp: -------------------------------------------------------------------------------- 1 | template 2 | ostream &operator<<(ostream &os, const vector &v) { 3 | os << "[ "; 4 | for (auto it = v.begin(); it != v.end(); ++it) { 5 | if (it != v.begin()) os << ", "; 6 | os << *it; 7 | } 8 | os << " ]"; 9 | return os; 10 | } 11 | 12 | template 13 | ostream &operator<<(ostream &os, const map &m) { 14 | os << "{ "; 15 | for (auto it = m.begin(); it != m.end(); ++it) { 16 | if (it != m.begin()) os << ", "; 17 | os << " " << it->first << " : " << it->second; 18 | } 19 | os << "}"; 20 | return os; 21 | } 22 | 23 | template 24 | ostream &operator<<(ostream &os, const set &s) { 25 | os << "{ "; 26 | for (auto it = s.begin(); it != s.end(); ++it) { 27 | if (it != s.begin()) os << ", "; 28 | os << *it; 29 | } 30 | os << " }"; 31 | return os; 32 | } 33 | 34 | template 35 | ostream &operator<<(ostream &os, const pair &p) { 36 | os << "(" << p.first << ", " << p.second << ")"; 37 | return os; 38 | } 39 | -------------------------------------------------------------------------------- /Structure/SegmentTree.cpp: -------------------------------------------------------------------------------- 1 | // verified: AOJ DSL_2 A 2 | 3 | struct Data { 4 | int num; 5 | Data() : num(0x7FFFFFFF) {;} 6 | Data(int n) : num(n) {;} 7 | }; 8 | 9 | inline Data Merge(Data left, Data right) { 10 | return Data(left.num < right.num ? left.num : right.num); 11 | } 12 | 13 | struct SegmentTree { 14 | int n; vector data; 15 | SegmentTree(int N) : n(1 << N), data(n * 2) {} 16 | void update (int pos, Data value) { 17 | data[pos] = value; 18 | while (pos < 2*n-1) { 19 | int l = pos, r = pos^1; 20 | if (l > r) swap(l, r); 21 | pos = pos / 2 + n; 22 | data[pos] = Merge(data[l], data[r]); 23 | } 24 | } 25 | Data sub(int fr, int to, int node, int la, int ra) { 26 | if (ra<=fr || to<=la) return Data(); 27 | if (fr<=la && ra<=to) return data[node]; 28 | Data vl = sub(fr, to, (node-n)*2+0, la, (la+ra)/2); 29 | Data vr = sub(fr, to, (node-n)*2+1, (la+ra)/2, ra); 30 | return Merge(vl, vr); 31 | } 32 | Data query(int fr, int to) { return sub(fr, to, 2*n-2, 0, n); } 33 | }; 34 | -------------------------------------------------------------------------------- /Graph/MinimumSpanningTree.cpp: -------------------------------------------------------------------------------- 1 | using Weight = int; 2 | struct Edge{ 3 | int src, dest; Weight weight; 4 | bool operator < (const Edge &rhs) const {return weight > rhs.weight;} 5 | }; 6 | 7 | using Edges = vector; 8 | 9 | // Kruskal 10 | // N, operator < 11 | Edges kruskal(int V, Edges &es) { 12 | sort(es.rbegin(), es.rend()); 13 | UnionFind uf(V); 14 | Edges res; 15 | REP(i, es.size()) { 16 | Edge e = es[i]; 17 | if(uf.root(e.src) != uf.root(e.dest)) { 18 | uf.merge(e.src, e.dest); 19 | res.push_back(e); 20 | } 21 | } 22 | return res; 23 | } 24 | 25 | Edges prim(Graph &g){ 26 | Edges res; 27 | vector visited(g.size(), 0); 28 | priority_queue q; 29 | q.push((Edge){-1, 0, 0}); 30 | while (!q.empty()) { 31 | Edge e = q.top(); 32 | q.pop(); 33 | if (visited[e.dest]) continue; 34 | if (e.src >= 0) res.push_back(e); 35 | visited[e.dest] = 1; 36 | for (Edge i : g[e.dest]) if(visited[i.dest] == 0) q.push(i); 37 | } 38 | sort(res.rbegin(), res.rend()); 39 | return res; 40 | } 41 | -------------------------------------------------------------------------------- /Structure/SegmentTreeDual.cpp: -------------------------------------------------------------------------------- 1 | // Range Update, Point Get 2 | // verified: AtCoder ABC179 F 3 | 4 | struct Data { 5 | int num; 6 | Data() : num(0x7FFFFFFF) {;} 7 | Data(int n) : num(n) {;} 8 | }; 9 | 10 | inline Data Merge(Data left, Data right) { 11 | return Data(left.num < right.num ? left.num : right.num); 12 | } 13 | 14 | struct SegmentTree { 15 | int n; vector data; 16 | SegmentTree(int N) : n(1 << N), data(n * 2) {} 17 | Data get(int pos) { 18 | auto value = data[pos]; 19 | while (pos < 2*n-1) { 20 | pos = pos / 2 + n; 21 | value = Merge(value, data[pos]); 22 | } 23 | return value; 24 | } 25 | void sub(int fr, int to, int node, int la, int ra, Data value) { 26 | if (ra<=fr || to<=la) return; 27 | if (fr<=la && ra<=to) { 28 | data[node] = Merge(data[node], value); 29 | return; 30 | } 31 | sub(fr, to, (node-n)*2+0, la, (la+ra)/2, value); 32 | sub(fr, to, (node-n)*2+1, (la+ra)/2, ra, value); 33 | } 34 | void update(int fr, int to, Data value) { sub(fr, to, 2*n-2, 0, n, value); } 35 | }; 36 | -------------------------------------------------------------------------------- /Graph/FordFulkerson.cpp: -------------------------------------------------------------------------------- 1 | #define MAX_V 1000 2 | struct Edge{ 3 | int src, dest; 4 | int cap, rev; 5 | }; 6 | 7 | const int INF = 1000000000; 8 | 9 | using Edges = vector; 10 | using Graph = vector; 11 | bool visited[MAX_V]; 12 | 13 | void add_edge(Graph &g, int src, int dest, int cap) { 14 | g[src].push_back((Edge){src, dest, cap, (int)g[dest].size()}); 15 | g[dest].push_back((Edge){dest, src, 0, (int)g[src].size() - 1}); 16 | } 17 | 18 | int dfs(Graph &g, int v, int t, int f) { 19 | if (v == t) return f; 20 | visited[v] = true; 21 | REP(i, g[v].size()) { 22 | Edge &e = g[v][i]; 23 | if (!visited[e.dest] && e.cap > 0) { 24 | int d = dfs(g, e.dest, t, min(f, e.cap)); 25 | if (d > 0) { 26 | e.cap -= d; 27 | g[e.dest][e.rev].cap += d; 28 | return d; 29 | } 30 | } 31 | } 32 | return 0; 33 | } 34 | 35 | int max_flow(Graph &g, int s, int t) { 36 | int flow = 0; 37 | for(;;) { 38 | memset(visited, 0, sizeof(visited)); 39 | int f = dfs(g, s, t, INF); 40 | if (f == 0) return flow; 41 | flow += f; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Others/LCS.cpp: -------------------------------------------------------------------------------- 1 | // verified : AOJ2090 2 | 3 | const int INF = 1e9; 4 | 5 | struct node { 6 | int value; node *next; 7 | node(int value, node *next) : value(value), next(next) { } 8 | }; 9 | 10 | int index_of(vector as, int x) { 11 | return lower_bound(as.begin(), as.end(), x) - as.begin(); 12 | } 13 | 14 | vector lcs(const vector &a, const vector &b) { 15 | const int n = a.size(), m = b.size(); 16 | vector> M(256); 17 | for (int j = m-1; j >= 0; --j) M[b[j]].push_back(j); 18 | vector xs(n+1, INF); xs[0] = -INF; 19 | vector link(n+1), del; 20 | REP(i,n) { 21 | if (M[a[i]].empty()) continue; 22 | vector ys = M[a[i]]; 23 | for (int j : ys) { 24 | int k = index_of(xs, j); 25 | xs[k] = j; 26 | link[k] = new node(b[j], link[k-1]); 27 | del.push_back(link[k]); 28 | } 29 | } 30 | int l = index_of(xs, INF-1) - 1; 31 | vector c; 32 | for (node *p = link[l]; p; p = p->next) 33 | c.push_back(p->value); 34 | reverse(c.begin(), c.end()); 35 | for (auto i : del) delete i; 36 | return c; 37 | } 38 | -------------------------------------------------------------------------------- /Graph/RecessionAnalysis.cpp: -------------------------------------------------------------------------------- 1 | struct Edge{ int src, dest; }; 2 | 3 | using Edges = vector; 4 | using Graph = vector; 5 | 6 | void add_edge(Graph &g, int src, int dest) { 7 | g[src].push_back((Edge){src, dest}); 8 | } 9 | int update(const Graph &g, vector &res, int v) { 10 | for (auto e: g[v]) { 11 | if (res[e.dest] == -1) { 12 | res[v] = 1; 13 | return 1; 14 | } 15 | } 16 | res[v] = -1; 17 | return 1e9; 18 | } 19 | 20 | void recession(const Graph &g, vector &res) { 21 | assert(g.size() == res.size()); 22 | int n = g.size(); 23 | vector> rg(n); 24 | for (int i = 0; i < n; ++i) 25 | for (auto e: g[i]) rg[e.dest].push_back(i); 26 | vector cnt(n); 27 | REP(i,n) cnt[i] = g[i].size(); 28 | queue que; 29 | REP(i,n) if (cnt[i] == 0) que.push(i); 30 | while (!que.empty()) { 31 | int v = que.front(); que.pop(); 32 | int c = update(g, res, v); 33 | for (int i: rg[v]) { 34 | if (res[i] != 0) continue; 35 | if (cnt[i] <= 0) continue; 36 | cnt[i] -= c; 37 | if (cnt[i] <= 0) que.push(i); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Graph/ShortestHamiltonPath.cpp: -------------------------------------------------------------------------------- 1 | using Weight = int; 2 | const Weight INF = 1000000000; 3 | struct Edge{ int src, dest; Weight weight; }; 4 | 5 | using Array = vector; 6 | using Matrix = vector; 7 | 8 | Weight shortestHamiltonPath(Matrix w, int s) { 9 | int n = w.size(), N = 1 << n; 10 | vector> best(N, vector(n)); 11 | REP(v,N) REP(i,n) best[v][i] = INF; 12 | best[1< best[v][i] + w[i][j]) 15 | best[v|(1<> best(N, vector(n)); 24 | REP(v,N) REP(i,n) best[v][i] = INF; 25 | best[1][0] = 0; 26 | REP(v,N) REP(i,n) if (v & (1 << i)) 27 | REP(j,n) if (!(v&(1< best[v][i] + w[i][j]) 28 | best[v|(1<face[i] != d.face[i]) {ok = false; break;} 22 | if (ok) return true; 23 | } 24 | } 25 | return false; 26 | } 27 | bool operator<(const Dice& d) const { 28 | REP(i, 8) { 29 | if(this->face[i] < d.face[i]) return true; 30 | if(this->face[i] > d.face[i]) return false; 31 | } 32 | return false; 33 | } 34 | bool operator==(const Dice& d) { 35 | return this->equivalentTo(d); 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /Math/Kitamasa.cpp: -------------------------------------------------------------------------------- 1 | // verified : TDPC T 2 | // a_n = sum c_i a_n-k+i 3 | // O(K^2 logN) 4 | 5 | vector convolution(const vector &lhs, const vector &rhs) { 6 | int n = lhs.size(), m = rhs.size(); 7 | vector res(n + m); 8 | REP(i,n) REP(j,m) res[i+j] += lhs[i] * rhs[j]; 9 | return res; 10 | } 11 | 12 | vector km_sub(const vector &c1, const vector &c2, int K, ll N) { 13 | vector res(K); 14 | if (N < K) res[N] = Mod(1); 15 | else if (N % 2 == 0) { 16 | res = km_sub(c1, c2, K, N/2); 17 | res = convolution(res, res); 18 | REP(i,K) REP(j,c1.size()) res[K-i+c1[j]-1] += c2[j] * res[2*K-i-1]; 19 | res.resize(K); 20 | } 21 | else { 22 | res = km_sub(c1, c2, K, N-1); 23 | Mod carry = res[K-1]; 24 | REP(i,K-1) res[K-i-1] = res[K-i-2]; 25 | res[0] = Mod(0); 26 | REP(i,c1.size()) res[c1[i]] += c2[i] * carry; 27 | } 28 | return res; 29 | } 30 | 31 | Mod kita_masa(const vector &c, const vector &a, ll N) { 32 | assert(c.size() == a.size()); 33 | int K = c.size(); 34 | vector c1; vector c2; 35 | REP(i,K) if (c[i].num) { c1.push_back(i); c2.push_back(c[i]); } 36 | vector b = km_sub(c1, c2, K, N); 37 | Mod res = Mod(0); 38 | REP(i,K) res += a[i] * b[i]; 39 | return res; 40 | } 41 | -------------------------------------------------------------------------------- /Graph/HopcroftKarp.cpp: -------------------------------------------------------------------------------- 1 | //計算用に1つ頂点が余分に必要(NIL)なことに注意 2 | #define MAX_V 100001 3 | vector g[MAX_V]; 4 | int V1, V2, NIL, match[MAX_V], d[MAX_V]; 5 | 6 | void add_edge(int u, int v) { 7 | g[u].push_back(v); 8 | g[v].push_back(u); 9 | } 10 | 11 | bool bfs() { 12 | queue que; 13 | fill(d, d + V1, INF); 14 | REP(i, V1) if(match[i] == NIL) { 15 | d[i] = 0; 16 | que.push(i); 17 | } 18 | d[NIL] = INF; 19 | while(!que.empty()) { 20 | int u = que.front(); que.pop(); 21 | if(u != NIL) { 22 | for (int v : g[u]) { 23 | if(d[match[v]] == INF) { 24 | d[match[v]] = d[u] + 1; 25 | que.push(match[v]); 26 | } 27 | } 28 | } 29 | } 30 | return (d[NIL] != INF); 31 | } 32 | 33 | bool dfs(int u) { 34 | if(u != NIL) { 35 | for (int v : g[u]) { 36 | if(d[match[v]] == d[u] + 1) { 37 | if(dfs(match[v])) { 38 | match[v] = u; 39 | match[u] = v; 40 | return true; 41 | } 42 | } 43 | } 44 | d[u] = INF; 45 | return false; 46 | } 47 | return true; 48 | } 49 | 50 | int bipartite_matching(int v1, int v2) { 51 | int matching = 0; 52 | V1 = v1, V2 = v2, NIL = V1 + V2; 53 | REP(i, V1 + V2) match[i] = NIL; 54 | while(bfs()) REP(i, V1) if(match[i] == NIL && dfs(i)) matching++; 55 | return matching; 56 | } 57 | -------------------------------------------------------------------------------- /Graph/Bridge.cpp: -------------------------------------------------------------------------------- 1 | struct Edge{ int src, dest; }; 2 | 3 | using Edges = vector; 4 | using Graph = vector; 5 | 6 | Edges edges; 7 | vector > connect; 8 | vector roots, st, order; 9 | int cnt; 10 | 11 | void bridgeDfs(const Graph &g, int from, int parent) { 12 | order[from] = cnt++; 13 | st.push_back(from); 14 | roots.push_back(from); 15 | for (Edge e : g[from]) { 16 | int to = e.dest; 17 | if (to == parent) continue; 18 | if (order[to] == -1) { 19 | bridgeDfs(g, to, from); 20 | } 21 | else { 22 | while (order[roots.back()] > order[to]) roots.pop_back(); 23 | } 24 | } 25 | if (from == roots.back()) { 26 | edges.push_back(Edge{parent, from}); 27 | connect.push_back(vector()); 28 | while (true) { 29 | int w = st.back(); 30 | st.pop_back(); 31 | connect.back().push_back(w); 32 | if (from == w) break; 33 | } 34 | roots.pop_back(); 35 | } 36 | } 37 | 38 | Edges bridge(const Graph &g) { 39 | const int n = g.size(); 40 | edges.clear(); connect.clear(); 41 | roots.clear(); st.clear(); order.assign(n, -1); 42 | cnt = 0; 43 | for (int i = 0; i < n; i++) { 44 | if (order[i] != -1) continue; 45 | bridgeDfs(g, i, i); 46 | edges.pop_back(); 47 | } 48 | return edges; 49 | } 50 | -------------------------------------------------------------------------------- /Geometry/Polygon.cpp: -------------------------------------------------------------------------------- 1 | P centroid(VP tri) { 2 | return (tri[0] + tri[1] + tri[2]) / (ld)3.0; 3 | } 4 | 5 | P incenter(VP tri) { 6 | ld l[3]; 7 | REP(i,3) l[i] = abs(tri[(i+1)%3] - tri[(i+2)%3]); 8 | ld p = l[0]+l[1]+l[2]; 9 | P ic; 10 | REP(i,3) ic += l[i]/p*tri[i]; 11 | return ic; 12 | } 13 | 14 | P circumcenter(VP tri) { 15 | P a=tri[1]-tri[0], b=tri[2]-tri[0]; 16 | ld sncab = cross(a,b)*cross(a,b); 17 | return ((norm(a)*b-norm(b)*a)*cross(a,b))/(2*sncab) + tri[0]; 18 | } 19 | 20 | 21 | ld area(const VP &p) { 22 | ld res = 0; 23 | int n = p.size(); 24 | REP(j,n) res += cross(p[j], p[(j+1)%n]); 25 | return res / 2; 26 | } 27 | 28 | bool is_polygon(L l, VP &g) { 29 | int n = g.size(); 30 | for (int i = 0; i < n; i++) { 31 | P a = g[i]; 32 | P b = g[(i+1)%n]; 33 | if (isis_ss(l, (L){a, b})) return true; 34 | } 35 | return false; 36 | } 37 | 38 | int is_in_Polygon(const VP &g, P p) { 39 | bool in = false; 40 | int n = g.size(); 41 | for (int i = 0; i < n; i++) { 42 | P a = g[i] - p, b = g[(i+1)%n] - p; 43 | if (imag(a) > imag(b)) swap(a, b); 44 | if (imag(a) <= 0 && 0 < imag(b)) 45 | if (cross(a, b) < 0) in = !in; 46 | if (abs(cross(a, b)) < eps && dot(a, b) < eps) return 0; // on 47 | } 48 | if(in) return 1; // in 49 | return -1; // out 50 | } 51 | -------------------------------------------------------------------------------- /Math/FFT.cpp: -------------------------------------------------------------------------------- 1 | // verified: ATC001 C 2 | 3 | using ll = int64_t; 4 | using ld = long double; 5 | using P = complex; 6 | 7 | const ld pi = acos(-1.0); 8 | 9 | vector

FFT(ld theta, const vector

&a) { 10 | const int n = a.size(); 11 | vector

ret = a; 12 | for (int m = n; m >= 2; m >>= 1, theta *= 2) { 13 | REP(i,m/2) { 14 | for (int j = i; j < n; j += m) { 15 | int k = j + m / 2; 16 | P x = ret[j] - ret[k]; 17 | ret[j] += ret[k]; 18 | ret[k] = exp(i * theta * P(0, 1)) * x; 19 | } 20 | } 21 | } 22 | for (int i = 0, j = 1; j < n - 1; j++) { 23 | for (int k = n >> 1; k > (i ^= k); k >>= 1) {;} 24 | if (j < i) swap(ret[i], ret[j]); 25 | } 26 | return ret; 27 | } 28 | 29 | vector convolution(const vector &lhs, const vector &rhs) { 30 | int n = 1, a = lhs.size(), b = rhs.size(); 31 | while (n < max(a, b) * 2) n <<= 1; 32 | vector

temp1(n), temp2(n); 33 | REP(i,n/2) { 34 | if (i < a) temp1[i] = P(lhs[i], 0); 35 | if (i < b) temp2[i] = P(rhs[i], 0); 36 | } 37 | temp1 = FFT(2.0 * pi / n, temp1); 38 | temp2 = FFT(2.0 * pi / n, temp2); 39 | REP(i,n) temp1[i] *= temp2[i]; 40 | temp1 = FFT(-2.0 * pi / n, temp1); 41 | vector ret(n); 42 | REP(i,n) ret[i] = temp1[i].real() / n + 0.5; 43 | return ret; 44 | } 45 | -------------------------------------------------------------------------------- /Graph/LCA(Structure).cpp: -------------------------------------------------------------------------------- 1 | using Weight = int; 2 | struct Edge { int src, dest; }; 3 | using Edges = vector; 4 | using Graph = vector; 5 | 6 | void add_edge(Graph &g, int src, int dest) { 7 | g[src].push_back((Edge){src, dest}); 8 | g[dest].push_back((Edge){dest, src}); 9 | } 10 | 11 | struct LCA { 12 | int V, LOG_V; 13 | vector> parent; 14 | vector depth; 15 | void dfs(const Graph &g, int v, int p, int d) { 16 | parent[0][v] = p; depth[v] = d; 17 | for (Edge e: g[v]) if (e.dest != p) dfs(g, e.dest, v, d + 1); 18 | } 19 | LCA(const Graph &g, int root) : V(g.size()), LOG_V(0), depth(V, 0) { 20 | for (int v = V; v > 0; v >>= 1) ++LOG_V; 21 | parent.assign(LOG_V, vector(V, 0)); 22 | dfs(g, root, -1, 0); 23 | REP(k, LOG_V - 1) REP(v, V) { 24 | if (parent[k][v] < 0) parent[k + 1][v] = -1; 25 | else parent[k + 1][v] = parent[k][parent[k][v]]; 26 | } 27 | } 28 | int lca(int u, int v) { 29 | if (depth[u] > depth[v]) swap(u, v); 30 | REP(k, LOG_V) if (((depth[v] - depth[u]) >> k) & 1) v = parent[k][v]; 31 | if (u == v) return u; 32 | for (int k = LOG_V - 1; k >= 0; k--) { 33 | if (parent[k][u] != parent[k][v]) { 34 | u = parent[k][u]; 35 | v = parent[k][v]; 36 | } 37 | } 38 | return parent[0][u]; 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /Math/Mod.cpp: -------------------------------------------------------------------------------- 1 | const int mod = 1000000007; 2 | 3 | struct Mod { 4 | int n; 5 | Mod () : n(0) {;} 6 | Mod (int m) : n(m) { 7 | if (n >= mod) n %= mod; 8 | else if (n < 0) n = (n % mod + mod) % mod; 9 | } 10 | operator int() { return n; } 11 | }; 12 | 13 | bool operator==(Mod a, Mod b) { return a.n == b.n; } 14 | Mod operator+=(Mod &a, Mod b) { a.n += b.n; if (a.n >= mod) a.n -= mod; return a; } 15 | Mod operator-=(Mod &a, Mod b) { a.n -= b.n; if (a.n < 0) a.n += mod; return a; } 16 | Mod operator*=(Mod &a, Mod b) { a.n = ((long long)a.n * b.n) % mod; return a; } 17 | Mod operator+(Mod a, Mod b) { return a += b; } 18 | Mod operator-(Mod a, Mod b) { return a -= b; } 19 | Mod operator*(Mod a, Mod b) { return a *= b; } 20 | Mod operator^(Mod a, int n) { 21 | if (n == 0) return Mod(1); 22 | Mod res = (a * a) ^ (n / 2); 23 | if (n % 2) res = res * a; 24 | return res; 25 | } 26 | 27 | ll inv(ll a, ll p) { 28 | return (a == 1 ? 1 : (1 - p * inv(p%a, a)) / a + p); 29 | } 30 | Mod operator/(Mod a, Mod b) { return a * Mod(inv(b, mod)); } 31 | 32 | #define MAX_N 1024000 33 | 34 | Mod fact[MAX_N], factinv[MAX_N]; 35 | void init() { 36 | fact[0] = Mod(1); factinv[0] = 1; 37 | REP(i,MAX_N-1) { 38 | fact[i+1] = fact[i] * Mod(i+1); 39 | factinv[i+1] = factinv[i] / Mod(i+1); 40 | } 41 | } 42 | Mod comb(int a, int b) { 43 | return fact[a] * factinv[b] * factinv[a-b]; 44 | } 45 | -------------------------------------------------------------------------------- /Graph/2SAT.cpp: -------------------------------------------------------------------------------- 1 | //Verified SRM464 Div1 550 2 | class SAT { 3 | public: 4 | static const int MAX_V = 2 << 17; 5 | vector g[MAX_V], rg[MAX_V], vs; 6 | bool used[MAX_V]; 7 | int cmp[MAX_V], V, N; 8 | 9 | SAT (int n) : V(2 * n), N(n) {;} 10 | 11 | //(X_2 | !X_5) -> add_closure(2, 1, 5, 0) 12 | void add_closure(int i, bool bi, int j, bool bj) { 13 | add_edge(i + N * !bi, j + N * bj); 14 | add_edge(j + N * !bj, i + N * bi); 15 | } 16 | 17 | void add_edge(int from, int to) { 18 | g[from].push_back(to); 19 | rg[to].push_back(from); 20 | } 21 | 22 | void dfs(int v) { 23 | used[v] = true; 24 | for (int i : g[v]) if (!used[i]) dfs(i); 25 | vs.push_back(v); 26 | } 27 | 28 | void rdfs(int v, int k) { 29 | used[v] = true; cmp[v] = k; 30 | for (int i : rg[v]) if (!used[i]) rdfs(i, k); 31 | } 32 | 33 | //no solution: {}, else {1, 0, 1,...} 34 | vector solve() { 35 | memset(used, 0, sizeof(used)); 36 | vs.clear(); 37 | REP(v, V) if (!used[v]) dfs(v); 38 | memset(used, 0, sizeof(used)); 39 | reverse(ALL(vs)); 40 | int k = 0; 41 | for (int i : vs) if (!used[i]) rdfs(i, k++); 42 | vector res; 43 | REP(i, N) if (cmp[i] == cmp[i + N]) return res; 44 | REP(i, N) { 45 | if (cmp[i] < cmp[N + i]) res.push_back(true); 46 | else res.push_back(false); 47 | } 48 | return res; 49 | } 50 | }; 51 | -------------------------------------------------------------------------------- /Graph/StronglyConnectedComponents.cpp: -------------------------------------------------------------------------------- 1 | struct Edge{ int src, dest; }; 2 | 3 | using Edges = vector; 4 | using Graph = vector; 5 | 6 | void add_edge(Graph &g, int from, int to) { 7 | g[from].push_back((Edge){from, to}); 8 | } 9 | 10 | int scc(Graph &graph, vector &cmp) { 11 | int V = graph.size(); 12 | vector> g(V), rg(V); 13 | vector vs; 14 | vector used(V, false); 15 | cmp.resize(V); 16 | REP(i,V) { 17 | for (Edge e: graph[i]) { 18 | g[i].push_back(e.dest); 19 | rg[e.dest].push_back(i); 20 | } 21 | } 22 | function dfs = [&g, &vs, &used, &dfs](int v) { 23 | used[v] = true; 24 | for (int i: g[v]) if (!used[i]) dfs(i); 25 | vs.push_back(v); 26 | }; 27 | function rdfs = [&rg, &cmp, &used, &rdfs](int v, int k) { 28 | used[v] = true; cmp[v] = k; 29 | for (int i: rg[v]) if (!used[i]) rdfs(i, k); 30 | }; 31 | REP(v,V) if (!used[v]) dfs(v); 32 | used = vector(V, false); 33 | reverse(ALL(vs)); 34 | int k = 0; 35 | for(int i: vs) if (!used[i]) rdfs(i, k++); 36 | return k; 37 | } 38 | 39 | vector> buildGraph(const Graph &g, const vector &cmp, int K) { 40 | int V = g.size(); 41 | vector> s(K); 42 | vector> res(K); 43 | REP(i,V) for (Edge e: g[i]) s[cmp[i]].insert(cmp[e.dest]); 44 | REP(i,K) for (int j: s[i]) if (i != j) res[i].push_back(j); 45 | return res; 46 | } 47 | -------------------------------------------------------------------------------- /Geometry/Arrangement.cpp: -------------------------------------------------------------------------------- 1 | void add_point(vector

&ps, P p) { 2 | for (P q : ps) if (abs(q - p) < eps) return; 3 | ps.push_back(p); 4 | } 5 | 6 | // Verified: AOJ1279 7 | Graph segmentArrangement(const vector &s, const vector

&p) { 8 | int n = p.size(), m = s.size(); 9 | Graph g(n); 10 | REP(i,m) { 11 | vector> vec; 12 | REP(j,n) if (isis_sp(s[i], p[j])) 13 | vec.emplace_back(abs(s[i].a - p[j]), j); 14 | sort(ALL(vec)); 15 | REP(j,vec.size()-1) { 16 | int src = vec[j].second, dest = vec[j+1].second; 17 | add_edge(g, src, dest, abs(p[src] - p[dest])); 18 | } 19 | } 20 | return g; 21 | } 22 | 23 | // Not Verified Yet 24 | Graph circleArrangement(const vector &c, const vector

&p) { 25 | int n = p.size(), m = c.size(); 26 | Graph g(n); 27 | REP(i,m) { 28 | vector> vec; 29 | REP(j,n) if (abs(abs(c[i].p - p[j]) - c[i].r) < eps) 30 | vec.emplace_back(arg(c[i].p - p[j]), j); 31 | sort(ALL(vec)); 32 | REP(j,vec.size()-1) { 33 | int src = vec[j].second, dest = vec[j+1].second; 34 | ld angle = vec[j+1].first - vec[j].first; 35 | add_edge(g, src, dest, angle * c[i].r); 36 | } 37 | if (vec.size() >= 2) { 38 | int src = vec.back().second, dest = vec.front().first; 39 | ld angle = vec.front().first - vec.back().first; 40 | add_edge(g, src, dest, angle * c[i].r); 41 | } 42 | } 43 | return g; 44 | } 45 | -------------------------------------------------------------------------------- /Structure/FenwickTree.cpp: -------------------------------------------------------------------------------- 1 | // Light version 2 | using Data = int; 3 | const int len = 1 << 18; 4 | 5 | struct BIT { 6 | vector data; 7 | BIT() : data(len, 0) {} 8 | void update(int i, Data value) { 9 | for (; i < len; i |= i+1) data[i] += value; 10 | } 11 | Data query(int i) { 12 | Data s = 0; 13 | for (; i >= 0; i = (i&i+1)-1) s += data[i]; 14 | return s; 15 | } 16 | }; 17 | 18 | struct Data { 19 | int num; 20 | Data() : num(0) {;} 21 | Data(int n) : num(n) {;} 22 | }; 23 | 24 | inline Data Merge(Data left, Data right) { 25 | return Data(left.num + right.num); 26 | } 27 | 28 | struct BIT { 29 | static const int len = 1 << 18; 30 | vector data; 31 | BIT() : data(len, 0) {} 32 | void update(int i, Data value) { 33 | for (; i < len; i |= i+1) data[i] = Merge(data[i], value); 34 | } 35 | Data query(int i) { 36 | Data s = 0; 37 | for (; i >= 0; i = (i&(i+1))-1) s = Merge(s, data[i]); 38 | return s; 39 | } 40 | }; 41 | 42 | // Range Add, Range Sum 43 | struct RARS { 44 | BIT bit1, bit2; 45 | void add(int fr, int to, Data val) { 46 | bit1.update(fr, Data(-val.num * fr)); 47 | bit1.update(to, Data(val.num * to)); 48 | bit2.update(fr, val); 49 | bit2.update(to, Data(-val.num)); 50 | } 51 | Data sum(int fr, int to) { 52 | Data s1 = bit1.query(to).num + bit2.query(to).num * to; 53 | Data s2 = bit1.query(fr).num + bit2.query(fr).num * fr; 54 | return Data(s1.num - s2.num); 55 | } 56 | }; 57 | -------------------------------------------------------------------------------- /Graph/Dinic.cpp: -------------------------------------------------------------------------------- 1 | #define MAX_V 500 2 | 3 | struct Edge{ 4 | int src, dest; 5 | int cap, rev; 6 | }; 7 | 8 | using Edges = vector; 9 | using Graph = vector; 10 | 11 | int d[MAX_V]; 12 | int iter[MAX_V]; 13 | 14 | void add_edge(Graph &g, int src, int dest, int cap) { 15 | g[src].push_back((Edge){src, dest, cap, (int)g[dest].size()}); 16 | g[dest].push_back((Edge){dest, src, 0, (int)g[src].size() - 1}); 17 | } 18 | 19 | void bfs(Graph &g, int s) { 20 | memset(d, -1, sizeof(d)); 21 | queue que; 22 | d[s] = 0; 23 | que.push(s); 24 | while(!que.empty()) { 25 | int v = que.front(); que.pop(); 26 | REP(i, g[v].size()) { 27 | Edge &e = g[v][i]; 28 | if (e.cap > 0 && d[e.dest] < 0) { 29 | d[e.dest] = d[v] + 1; 30 | que.push(e.dest); 31 | } 32 | } 33 | } 34 | } 35 | 36 | int dfs(Graph &g, int v, int t, int f) { 37 | if (v == t) return f; 38 | for (int &i = iter[v]; i < g[v].size(); i++) { 39 | Edge &e = g[v][i]; 40 | if (e.cap > 0 && d[v] < d[e.dest]) { 41 | int d = dfs(g, e.dest, t, min(f, e.cap)); 42 | if (d > 0) { 43 | e.cap -= d; 44 | g[e.dest][e.rev].cap += d; 45 | return d; 46 | } 47 | } 48 | } 49 | return 0; 50 | } 51 | 52 | int max_flow(Graph g, int s, int t) { 53 | int flow = 0; 54 | for (;;) { 55 | bfs(g, s); 56 | if (d[t] < 0) return flow; 57 | memset(iter, 0, sizeof(iter)); 58 | int f; 59 | while ((f = dfs(g, s, t, INF)) > 0) flow += f; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Structure/SkewHeapDijkstra.cpp: -------------------------------------------------------------------------------- 1 | using Weight = int; 2 | using Data = pair; 3 | 4 | Weight INF = 1000000000; 5 | struct Edge{ 6 | int src, dest; Weight weight; 7 | bool operator < (const Edge &rhs) const {return weight > rhs.weight;} 8 | }; 9 | 10 | using Edges = vector; 11 | using Graph = vector; 12 | using Array = vector; 13 | using Matrix = vector; 14 | 15 | void add_edge(Graph &g, int src, int dest, Weight weight) { 16 | g[src].push_back((Edge){src, dest, weight}); 17 | g[dest].push_back((Edge){dest, src, weight}); 18 | } 19 | 20 | //O(V)-space dijkstra 21 | //G: function object 22 | template 23 | void dijkstra(G &g, Array &d, int s) { 24 | int n=g.size(); 25 | d.assign(n, INF); 26 | d[s] = 0; 27 | shared_ptr que; 28 | vector> nodes(n); 29 | auto p = push(que, Data(0, s)); 30 | que = p.first; 31 | nodes[s] = p.second; 32 | while (que) { 33 | Weight dist = que->top().first; 34 | int v = que->top().second; 35 | que = pop(que); 36 | nodes[v].reset(); 37 | if (d[v] < dist) continue; 38 | REP(i, g(v).size()) { 39 | Edge e = g(v)[i]; 40 | if (d[e.dest] > d[v] + e.weight) { 41 | d[e.dest] = d[v] + e.weight; 42 | if (!nodes[e.dest]) { 43 | auto p = push(que, Data(d[e.dest], e.dest)); 44 | que = p.first; 45 | nodes[e.dest] = p.second; 46 | } else { 47 | que = reduce(nodes[e.dest], que, Data(d[e.dest], e.dest)); 48 | } 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Structure/SegmentTreePersistent.cpp: -------------------------------------------------------------------------------- 1 | // Persistent Segment Tree 2 | // Range add Range sum 3 | // Verified : AOJ2563 4 | 5 | using Data = ll; 6 | 7 | struct PST { 8 | Data val, lazy; 9 | PST *l, *r; 10 | PST() : val(0), lazy(0), l(nullptr), r(nullptr) {} 11 | PST(Data val, Data lazy, PST *l, PST *r) : val(val), lazy(lazy), l(l), r(r) {} 12 | }; 13 | 14 | Data value(PST* ptr) { if (ptr) return ptr->val; else return 0; } 15 | Data lazy(PST* ptr) { if (ptr) return ptr->lazy; else return 0; } 16 | PST *left(PST* ptr) { if (ptr) return ptr->l; else return nullptr; } 17 | PST *right(PST* ptr) { if (ptr) return ptr->r; else return nullptr; } 18 | 19 | PST *add(PST *ptr, int lpos, int rpos, Data val, int la, int ra) { 20 | if (rpos <= la || ra <= lpos) return ptr; 21 | if (lpos <= la && ra <= rpos) { 22 | return new PST(value(ptr), lazy(ptr) + val, left(ptr), right(ptr)); 23 | } 24 | int mid = (la + ra) / 2; 25 | PST *l = add(left(ptr), lpos, rpos, val, la, mid); 26 | PST *r = add(right(ptr), lpos, rpos, val, mid, ra); 27 | int c = min(ra, rpos) - max(la, lpos); 28 | return new PST(value(ptr) + c * val, lazy(ptr), l, r); 29 | } 30 | 31 | Data sum(PST *ptr, int lpos, int rpos, int la, int ra) { 32 | if (!ptr || rpos <= la || ra <= lpos) return Data(0); 33 | if (lpos <= la && ra <= rpos) return ptr->val + ptr->lazy * (ra - la); 34 | int mid = (la + ra) / 2; 35 | Data res = ptr->lazy * (min(rpos, ra) - max(lpos, la)); 36 | res += sum(ptr->l, lpos, rpos, la, mid); 37 | res += sum(ptr->r, lpos, rpos, mid, ra); 38 | return res; 39 | } 40 | -------------------------------------------------------------------------------- /Structure/Treap.cpp: -------------------------------------------------------------------------------- 1 | struct Treap { 2 | Data value; 3 | int pri; 4 | Treap *left; 5 | Treap *right; 6 | int cnt; 7 | int sum; 8 | Treap(Data v) 9 | : value(v), pri(rand()), 10 | left(nullptr), right(nullptr), 11 | cnt(1), sum(v) {} 12 | }; 13 | 14 | int count(Treap *t) { return !t ? 0 : t->cnt; } 15 | int sum(Treap *t) { return !t ? 0 : t->sum; } 16 | 17 | Treap *update(Treap *t) { 18 | t->cnt = count(t->left) + count(t->right) + 1; 19 | t->sum = sum(t->left) + sum(t->right) + t->value; 20 | return t; 21 | } 22 | 23 | Treap *merge(Treap *l, Treap *r){ 24 | if(!l || !r) return !l ? r : l; 25 | 26 | if(l->pri > r->pri){ 27 | l->right = merge(l->right, r); 28 | return update(l); 29 | } else { 30 | r->left = merge(l, r->left); 31 | return update(r); 32 | } 33 | } 34 | 35 | pair split(Treap *t, int k) { 36 | if(!t) return make_pair(nullptr, nullptr); 37 | 38 | if(k <= count(t->left)) { 39 | auto s = split(t->left, k); 40 | t->left = s.second; 41 | return make_pair(s.first, update(t)); 42 | } else { 43 | auto s = split(t->right, k - count(t->left) - 1); 44 | t->right = s.first; 45 | return make_pair(update(t), s.second); 46 | } 47 | } 48 | 49 | Treap *insert(Treap *t, int k, Data v) { 50 | auto s = split(t, k); 51 | return merge(s.first, merge(new Treap(v), s.second)); 52 | } 53 | 54 | Treap *erase(Treap *t, int k) { 55 | auto s1 = split(t, k); 56 | auto s2 = split(s1.second, 1); 57 | delete s2.first; 58 | return merge(s1.first, s2.second); 59 | } 60 | -------------------------------------------------------------------------------- /Structure/RBST.cpp: -------------------------------------------------------------------------------- 1 | struct RBST { 2 | Data value; 3 | RBST *left; 4 | RBST *right; 5 | int cnt; 6 | Data sum; 7 | RBST(Data v) 8 | : value(v), left(nullptr), right(nullptr), 9 | cnt(1), sum(v) {} 10 | }; 11 | 12 | int count(RBST *t) { return !t ? 0 : t->cnt; } 13 | Data sum(RBST *t) { return !t ? 0 : t->sum; } 14 | RBST *update(RBST *t) { 15 | t->cnt = count(t->left) + count(t->right) + 1; 16 | t->sum = sum(t->left) + sum(t->right) + t->value; 17 | return t; 18 | } 19 | 20 | RBST *merge(RBST *l, RBST *r) { 21 | if (!l || !r) return !l ? r : l; 22 | 23 | int cnt_sum = count(l) + count(r); 24 | // rand()だと小さい値しか返さない実装になっていることがあるので、適当な実装を使う 25 | if ((my_rand() % cnt_sum) < count(l)) { 26 | l->right = merge(l->right, r); 27 | return update(l); 28 | } else { 29 | r->left = merge(l, r->left); 30 | return update(r); 31 | } 32 | } 33 | 34 | pair split(RBST *t, int k) { 35 | if (!t) return make_pair(nullptr, nullptr); 36 | 37 | if (k <= count(t->left)) { 38 | auto s = split(t->left, k); 39 | t->left = s.second; 40 | return make_pair(s.first, update(t)); 41 | } else { 42 | auto s = split(t->right, k - count(t->left) - 1); 43 | t->right = s.first; 44 | return make_pair(update(t), s.second); 45 | } 46 | } 47 | 48 | RBST *insert(RBST *t, int k, Data v) { 49 | auto s = split(t, k); 50 | return merge(s.first, merge(new RBST(v), s.second)); 51 | } 52 | 53 | RBST *erase(RBST *t, int k) { 54 | auto s1 = split(t, k); 55 | auto s2 = split(s1.second, 1); 56 | delete s2.first; 57 | return merge(s1.first, s2.second); 58 | } 59 | -------------------------------------------------------------------------------- /Graph/ArticulationPoints.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using Weight = int; 5 | struct Edge{ 6 | int src, dest; 7 | bool operator < (const Edge &rhs) const { 8 | return make_pair(src, dest) < make_pair(rhs.src, rhs.dest); 9 | } 10 | }; 11 | 12 | using Edges = vector; 13 | using Graph = vector; 14 | 15 | set art; 16 | vector > connect; 17 | vector st; 18 | vector order, low; 19 | int cnt; 20 | 21 | void artDfs(const Graph &g, int from, int parent) { 22 | low[from] = order[from] = cnt++; 23 | for (Edge e : g[from]) { 24 | int to = e.dest; 25 | if (to != parent && order[to] < order[from]) st.push_back(e); 26 | if (order[to] == -1) { 27 | artDfs(g, to, from); 28 | low[from] = min(low[from], low[to]); 29 | if ((order[from] == 0 && order[to] != 1) || (order[from] != 0 && low[to] >= order[from])) 30 | art.insert(from); 31 | if (low[to] >= order[from]) { 32 | connect.push_back(set()); 33 | while (true) { 34 | Edge edge = st.back(); 35 | st.pop_back(); 36 | connect.back().insert(edge); 37 | if (edge.src == from && edge.dest == to) break; 38 | } 39 | } 40 | } 41 | else { 42 | low[from] = min(low[from], order[to]); 43 | } 44 | } 45 | } 46 | 47 | set articulationPoints(const Graph &g) { 48 | const int n = g.size(); 49 | art.clear(); connect.clear(); st.clear(); 50 | order.assign(n, -1); low.assign(n, -1); 51 | for (int i = 0; i < n; i++) { 52 | if (order[i] != -1) continue; 53 | cnt = 0; 54 | artDfs(g, i, i); 55 | } 56 | return art; 57 | } 58 | -------------------------------------------------------------------------------- /Graph/MinimumArborescence.cpp: -------------------------------------------------------------------------------- 1 | void clearScc() { 2 | REP(i,MAX_V) g[i].clear(); 3 | REP(i,MAX_V) rg[i].clear(); 4 | } 5 | 6 | Weight MinimumArborescence(const Graph &g, int root) { 7 | const int n = g.size(); 8 | Weight res = 0; 9 | vector c(n, INF); 10 | vector p(n, -1); 11 | for (int from = 0; from < n; from++) { 12 | for (Edge e : g[from]) { 13 | if (e.dest == from) continue; 14 | if (e.weight < c[e.dest]) p[e.dest] = from, c[e.dest] = e.weight; 15 | c[e.dest] = min(c[e.dest], e.weight); 16 | } 17 | } 18 | Graph ng(n); 19 | clearScc(); 20 | for (int i = 0; i < n; i++) { 21 | if (i == root) continue; 22 | if (p[i] == -1) return INF; 23 | ng[p[i]].push_back((Edge){p[i], i, 0}); 24 | add_edge(p[i], i); 25 | res += c[i]; 26 | } 27 | int V = scc(n); 28 | vector> connect(V); 29 | REP(i,n) connect[cmp[i]].push_back(i); 30 | int m = connect.size(); 31 | if (m == n) return res; 32 | vector mapto(n, -1); 33 | vector cycle(n, 0); 34 | res = 0; 35 | REP(i,m) { 36 | REP(j,connect[i].size()) { 37 | mapto[connect[i][j]] = i; 38 | if (connect[i].size() != 1) 39 | cycle[connect[i][j]] = 1, res += c[connect[i][j]]; 40 | } 41 | } 42 | ng = Graph(m); 43 | for (int from = 0; from < n; from++) { 44 | for (Edge e : g[from]) { 45 | Weight cost = e.weight; 46 | if (e.dest == root || mapto[from] == mapto[e.dest]) continue; 47 | if (cycle[e.dest]) cost -= c[e.dest]; 48 | ng[mapto[from]].push_back((Edge){mapto[from], mapto[e.dest], cost}); 49 | } 50 | } 51 | return min(INF, res + MinimumArborescence(ng, mapto[root])); 52 | } 53 | -------------------------------------------------------------------------------- /Geometry/CircleRange.cpp: -------------------------------------------------------------------------------- 1 | using Range = vector>; 2 | 3 | Range make_range(ld from, ld to) { 4 | Range v; 5 | if (to < from) swap(from , to); 6 | if (to - from > pi) { 7 | v.emplace_back(-pi, from); 8 | v.emplace_back(to, pi); 9 | } 10 | else { 11 | v.emplace_back(from, to); 12 | } 13 | return v; 14 | } 15 | 16 | void print_range(const Range &r) { 17 | for (auto p: r) 18 | cout << "(" << p.first << ", " << p.second << ")"; 19 | cout << endl; 20 | } 21 | 22 | Range operator*(const Range &lhs, const Range &rhs) { 23 | Range res; 24 | for (auto x: lhs) { 25 | for (auto y: rhs) { 26 | ld l = max(x.first, y.first); 27 | ld r = min(x.second, y.second); 28 | if (l < r - eps) res.emplace_back(l, r); 29 | } 30 | } 31 | sort(ALL(res)); 32 | return res; 33 | } 34 | 35 | Range operator+(const Range &lhs, const Range &rhs) { 36 | Range v = lhs; 37 | v.insert(begin(v), ALL(rhs)); 38 | if (v.empty()) return v; 39 | Range res; 40 | sort(ALL(v)); 41 | auto x = v.front(); 42 | for (int i = 1; i < (int)v.size(); ++i) { 43 | if (x.second < v[i].first - eps) { 44 | res.push_back(x); 45 | x = v[i]; 46 | } 47 | else { 48 | x.second = max(x.second, v[i].second); 49 | } 50 | } 51 | res.push_back(x); 52 | return res; 53 | } 54 | 55 | Range operator-(const Range &r) { 56 | Range res; 57 | ld x = 0; 58 | for (auto p: r) { 59 | if (p.first > eps) res.emplace_back(x, p.first); 60 | x = p.second; 61 | } 62 | if (x < 2 * pi - eps) res.emplace_back(x, 2 * pi); 63 | return res; 64 | } 65 | 66 | Range operator-(const Range &lhs, const Range &rhs) { return lhs * (-rhs); } 67 | -------------------------------------------------------------------------------- /String/SuffixArray.cpp: -------------------------------------------------------------------------------- 1 | struct SuffixArray { 2 | struct SAComp { 3 | const int h; 4 | const vector &g; 5 | SAComp(int h, vector &g) : h(h), g(g) {;} 6 | bool operator() (int a, int b) { 7 | return a != b && (g[a] != g[b] ? g[a] < g[b] : g[a + h] < g[b + h]); 8 | } 9 | }; 10 | 11 | int n; 12 | char *str; 13 | vector sa, lcp; 14 | 15 | SuffixArray(const string &t) : n(t.size()), sa(n+1), lcp(n+1) { 16 | str = new char[n+1]; 17 | strcpy(str, t.c_str()); 18 | 19 | // build SA 20 | vector g(n+1, 0), b(n+1, 0); 21 | REP(i,n+1) { sa[i] = i; g[i] = str[i]; } 22 | sort(begin(sa), end(sa), SAComp(0, g)); 23 | for (int h = 1; b[n] != n; h *= 2) { 24 | SAComp comp(h, g); 25 | sort(sa.begin(), sa.end(), comp); 26 | REP(i,n) b[i+1] = b[i] + comp(sa[i], sa[i+1]); 27 | REP(i,n+1) g[sa[i]] = b[i]; 28 | } 29 | 30 | // build LCP 31 | int h = 0; 32 | REP(i,n+1) b[sa[i]] = i; 33 | REP(i,n+1) { 34 | if (b[i]) { 35 | for (int j = sa[b[i]-1]; j+h 0) --h; 42 | } 43 | } 44 | ~SuffixArray() { delete []str; } 45 | 46 | int find(string t) { 47 | int m = t.size(); 48 | char p[m+1]; 49 | strcpy(p, t.c_str()); 50 | int left = -1, right = n + 1; 51 | while (left + 1 < right) { 52 | int mid = (left + right) / 2; 53 | if (strncmp(str + sa[mid], p, m) < 0) left = mid; 54 | else right = mid; 55 | } 56 | return strncmp(str + sa[right], p, m) == 0 ? sa[right] : -1; 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /Geometry/Convex.cpp: -------------------------------------------------------------------------------- 1 | VP ConvexHull(VP ps) { 2 | int n = ps.size(); 3 | int k = 0; 4 | sort(ps.begin(), ps.end()); 5 | VP ch(2 * n); 6 | for (int i = 0; i < n; ch[k++] = ps[i++]) 7 | while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k; 8 | for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--]) 9 | while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k; 10 | ch.resize(k - 1); 11 | return ch; 12 | } 13 | 14 | VP ConvexCut(const VP &ps, L l) { 15 | VP Q; 16 | for (int i = 0; i < (int)ps.size(); i++) { 17 | P A = ps[i], B = ps[(i+1)%ps.size()]; 18 | if (ccw(l.a, l.b, A) != -1) Q.push_back(A); 19 | if (ccw(l.a, l.b, A) * ccw(l.a, l.b, B) < 0) 20 | Q.push_back(is_ll((L){A, B}, l)); 21 | } 22 | return Q; 23 | } 24 | 25 | ld max_distance(const VP &ps) { 26 | assert (ps.size() > 1); 27 | VP g = ConvexHull(ps); 28 | int n = g.size(), a = 0, b = 1; 29 | ld res = abs(g[0] - g[1]); 30 | while (a < n) { 31 | P p1 = g[a%n], p2 = g[(a+1)%n]; 32 | P q1 = g[b%n], q2 = g[(b+1)%n]; 33 | if (arg((p2 - p1) / (q1 - q2)) > 0) ++b; else ++a; 34 | res = max(res, abs(p1 - q1)); 35 | } 36 | return res; 37 | } 38 | 39 | // line expression of ax+by+c<0 40 | L make_line(ld a, ld b, ld c) { 41 | P p1, p2; 42 | if (abs(a) < eps) { 43 | if (abs(b) < eps) { 44 | if (c < 0) return (L){P(1e9, 0), P(1e9, 1e9)}; 45 | return (L){P(1e9, 1e9), P(1e9, 0)}; 46 | } 47 | p1 = P(0, -c/b); p2 = P(1, -c/b); 48 | } 49 | else { 50 | p1 = P(-c/a, 0); p2 = P((-b-c)/a, 1); 51 | } 52 | P p = (p2 - p1) * P(0, 1) + p1; 53 | ld x = real(p), y = imag(p); 54 | if (a * x + b * y + c < 0) return (L){p1, p2}; 55 | else return (L){p2, p1}; 56 | } 57 | -------------------------------------------------------------------------------- /Math/Math.cpp: -------------------------------------------------------------------------------- 1 | using ll=long long; 2 | 3 | ll gcd(ll a,ll b){if(a min 8 | // x <= y 9 | ll extgcd(ll a, ll b, ll& x, ll& y) { 10 | ll g = a; x = 1; y = 0; 11 | if (b) g = extgcd(b, a%b, y, x), y -= (a / b) * x; 12 | return g; 13 | } 14 | 15 | // cond: a>b 16 | // ax+by=c 17 | ll extgcd2(ll a, ll b, ll c, ll& x, ll& y) { 18 | ll g = a; x = c / a; y = 0; 19 | if (b) g = extgcd2(b, a%b, c%b, y, x), y += (c / b) - (a / b) * x; 20 | return g; 21 | } 22 | 23 | // a^-1 mod p 24 | ll inv(ll a,ll p){ 25 | return ( a == 1 ? 1 : (1 - p*inv(p%a,a)) / a + p ); 26 | } 27 | 28 | // A[i] * x = B (mod M[i]) 29 | pair linear_congruence(const vector& A, const vector& B, const vector& M) { 30 | ll x = 0, m = 1; 31 | for(ll i = 0; i < (int)M.size(); i++){ 32 | ll a = A[i] * m, b = B[i] - A[i] * x, d = __gcd(M[i], a); 33 | if (b % d != 0) return make_pair(0, -1); 34 | ll t = b / d * inv(a / d, M[i] / d) % (M[i] / d); 35 | x = x + m * t; 36 | m *= M[i] / d; 37 | } 38 | return make_pair(x % m, m); 39 | } 40 | 41 | // Combination (MOD) 42 | int combin[][]; 43 | void init(int N) { 44 | combin[0][0] = 1; 45 | for (int i = 1; i < N; ++i) { 46 | combin[i][0] = combin[i][i] = 1; 47 | for (int j = 1; j < i-1; ++j) 48 | combin[i][j] = (combin[i-1][j-1] + combin[i-1][j]) % MOD; 49 | } 50 | } 51 | 52 | vector primes(int n) { 53 | vector p(n+1, 1); 54 | for (int i = 2; i*i <= n; ++i) 55 | if (p[i]) 56 | for (int j = i*i; j <= n; j += i) 57 | p[j] = 0; 58 | vector res; 59 | for (int i = 2; i <= n; ++i) 60 | if (p[i]) 61 | res.push_back(i); 62 | return res; 63 | } 64 | -------------------------------------------------------------------------------- /Graph/EulerPath.cpp: -------------------------------------------------------------------------------- 1 | //Verified(Code Forces Round 295 Div.1 C) 2 | class UndirectedEulerPath { 3 | public: 4 | int N; 5 | vector path; 6 | vector > g; 7 | 8 | UndirectedEulerPath(int n) : N(n), g(n) {} 9 | void add_edge(int x, int y) { g[x].insert(y); g[y].insert(x); } 10 | 11 | void dfs(int v) { 12 | while(g[v].size()) { 13 | int nv = *g[v].begin(); 14 | g[v].erase(g[v].begin()); 15 | g[nv].erase(g[nv].find(v)); 16 | dfs(nv); 17 | } 18 | path.push_back(v); 19 | } 20 | 21 | vector GetPath() { 22 | int start = 0, odd = 0, cnt = 0; 23 | REP(i, N) { 24 | cnt += g[i].size(); 25 | if(g[i].size() % 2) { 26 | odd++; 27 | start = i; 28 | } 29 | } 30 | if(odd != 0 && odd != 2) return vector(); 31 | dfs(start); 32 | reverse(path.begin(), path.end()); 33 | return path.size() == cnt / 2 + 1 ? path : vector(); 34 | } 35 | }; 36 | 37 | //Not Verified 38 | class DirectedEulerPath { 39 | public: 40 | int N; 41 | vector path; 42 | vector > g; 43 | 44 | DirectedEulerPath(int n) : N(n), g(n) {} 45 | void add_edge(int x, int y) { g[x].push_back(y); } 46 | 47 | void dfs(int v) { 48 | while(g[v].size()) { 49 | int nv = g[v].back(); 50 | g[v].pop_back(); 51 | dfs(nv); 52 | } 53 | path.push_back(v); 54 | } 55 | 56 | vector GetPath() { 57 | int start = 0, odd = 0, cnt = 0; 58 | REP(i, N) { 59 | cnt += g[i].size(); 60 | if(g[i].size() % 2) { 61 | odd++; 62 | start = i; 63 | } 64 | } 65 | if(odd != 0 && odd != 2) return vector(); 66 | dfs(start); 67 | reverse(path.begin(), path.end()); 68 | return path.size() == cnt + 1 ? path : vector(); 69 | } 70 | }; 71 | -------------------------------------------------------------------------------- /Structure/PartitionTree.cpp: -------------------------------------------------------------------------------- 1 | using Data = int; 2 | struct PartitionTree { 3 | static const int size = 15; 4 | int n; 5 | Data ordered[1< 0)) { 18 | s[level + 1][j++] = s[level][i]; 19 | ++toLeft[level][i]; 20 | if (s[level][i] == mid) --cnt; 21 | } 22 | else { 23 | s[level + 1][k++] = s[level][i]; 24 | } 25 | } 26 | build(level + 1, l, m); 27 | build(level + 1, m, r); 28 | } 29 | 30 | PartitionTree(const vector &a) { 31 | n = a.size(); 32 | REP(i,n) s[0][i] = a[i]; 33 | REP(i,n) ordered[i] = a[i]; 34 | sort(ordered, ordered + n); 35 | build(0, 0, n); 36 | } 37 | 38 | // query the k-th(1-based) smallest element in [lpos, rpos) 39 | Data query(int lpos, int rpos, int k) { 40 | int level = 0, l = 0, r = n; 41 | for (; r - l > 1; ++level) { 42 | int m = l + (r - l) / 2; 43 | int cntL = lpos == l ? 0 : toLeft[level][lpos - 1]; 44 | int cntR = toLeft[level][rpos - 1]; 45 | if (cntR - cntL >= k) { 46 | lpos = l + cntL; 47 | rpos = l + cntR; 48 | r = m; 49 | } 50 | else { 51 | lpos = m + lpos - l - cntL; 52 | rpos = m + rpos - l - cntR; 53 | k -= cntR - cntL; 54 | l = m; 55 | } 56 | } 57 | return s[level][l]; 58 | } 59 | }; 60 | -------------------------------------------------------------------------------- /Geometry/DualGraph.cpp: -------------------------------------------------------------------------------- 1 | // Verified: AOJ0273 2 | // any two segments must not cross 3 | 4 | vector> polygon; 5 | vector seg2p[1024][1024]; 6 | 7 | Graph dual_graph(const vector &s, const VP &p) { 8 | int N = p.size(); 9 | polygon.clear(); 10 | REP(i,1024) REP(j,1024) seg2p[i][j].clear(); 11 | vector>> tup(N); 12 | REP(i,s.size()) { 13 | int a = -1, b = -1; 14 | REP(j,N) if (abs(s[i].a - p[j]) < eps) a = j; 15 | REP(j,N) if (abs(s[i].b - p[j]) < eps) b = j; 16 | assert(a >= 0 && b >= 0); 17 | tup[a].emplace_back(arg(s[i].b - s[i].a), b, false); 18 | tup[b].emplace_back(arg(s[i].a - s[i].b), a, false); 19 | } 20 | REP(i,N) sort(ALL(tup[i])); 21 | REP(i,N) { 22 | REP(j,tup[i].size()) { 23 | ld angle; int pos = j, src = i, dest; bool flag; 24 | tie(angle, dest, flag) = tup[i][j]; 25 | if (flag) continue; 26 | vector ps; 27 | while (!flag) { 28 | ps.push_back(src); 29 | get<2>(tup[src][pos]) = true; 30 | seg2p[src][dest].push_back(polygon.size()); 31 | seg2p[dest][src].push_back(polygon.size()); 32 | angle += pi + eps; 33 | if (angle > pi) angle -= 2 * pi; 34 | auto it = lower_bound(ALL(tup[dest]), make_tuple(angle, 0, false)); 35 | if (it == tup[dest].end()) it = tup[dest].begin(); 36 | src = dest; tie(angle, dest, flag) = *it; 37 | pos = it - tup[src].begin(); 38 | } 39 | polygon.push_back(ps); 40 | } 41 | } 42 | Graph g(polygon.size()); 43 | REP(i,N) REP(j,i) { 44 | if (seg2p[i][j].size() == 2) { 45 | int src = seg2p[i][j][0], dest = seg2p[i][j][1]; 46 | g[src].push_back((Edge){src, dest}); 47 | g[dest].push_back((Edge){dest, src}); 48 | } 49 | } 50 | return g; 51 | } 52 | -------------------------------------------------------------------------------- /Others/Dice.cpp: -------------------------------------------------------------------------------- 1 | struct Dice{ 2 | int t, r, f; 3 | int top() { return t; } 4 | int bottom() { return 7 - t; } 5 | int right() { return r; } 6 | int left() { return 7 - r; } 7 | int front() { return f; } 8 | int back() { return 7 - f; } 9 | void toFront() { swap(f, t); t = 7 - t; } 10 | void toBack() { toFront(); toFront(); toFront(); } 11 | void toRight() { swap(t, r); t = 7 - t; } 12 | void toLeft() { toRight(); toRight(); toRight(); } 13 | void toClock() { swap(f, r); r = 7 - r; } 14 | void toConter() { toClock(); toClock(); toClock(); } 15 | int roll(int tt, int ff) { 16 | REP(i,30) { 17 | if (i % 10 == 0) toRight(); 18 | else if (i % 10 == 5) toFront(); 19 | else toClock(); 20 | if (tt == t && ff == f) return r; 21 | } 22 | return 0; 23 | } 24 | }; 25 | 26 | struct Dice{ 27 | int t, f, r, face[6]; 28 | Dice(void) { t = 0; f = 1; r = 2; } 29 | int top() { return face[t]; } 30 | int bottom() { return face[5 - t]; } 31 | int right() { return face[r]; } 32 | int left() { return face[5 - r]; } 33 | int front() { return face[f]; } 34 | int back() { return face[5 - f]; } 35 | void toFront() { swap(f, t); t = 5 - t; } 36 | void toBack() { swap(f, t); f = 5 - f; } 37 | void toRight() { swap(t, r); t = 5 - t; } 38 | void toLeft() { swap(t, r); r = 5 - r; } 39 | void toClock() { swap(f, r); r = 5 - r; } 40 | void toConter(){ swap(f, r); f = 5 - f; } 41 | vector toVector() { 42 | return {face[t], face[f], face[r], face[5-r], face[5-f], face[5-t]}; 43 | } 44 | vector toVector2() { 45 | vector res = {999}; 46 | REP(i,30) { 47 | if (i % 10 == 0) toRight(); 48 | else if (i % 10 == 5) toFront(); 49 | else toClock(); 50 | res = min(res, toVector()); 51 | } 52 | return res; 53 | } 54 | }; 55 | -------------------------------------------------------------------------------- /Others/Poker.cpp: -------------------------------------------------------------------------------- 1 | // Verified : AOJ2535 2 | struct card { 3 | int suit, rank; 4 | card(const string& s) { 5 | suit = string("CDHS").find(s[0]); 6 | rank = string("0A23456789TJQK").find(s[1]); 7 | } 8 | bool operator<(const card& o) const { 9 | return rank != o.rank ? rank < o.rank : suit < o.suit; 10 | } 11 | }; 12 | 13 | int poker_hand(const vector& hand) { 14 | vector X(27), Y(4); 15 | for (card i : hand) { 16 | ++X[i.rank]; ++Y[i.suit]; 17 | if (i.rank == 1) ++X[i.rank+13]; // for wrapping 18 | } 19 | bool straight = false; 20 | for (int i = 1; i+4 < 27; ++i) // wrapping range 21 | if (X[i+0] && X[i+1] && X[i+2] && X[i+3] && X[i+4]) straight = true; 22 | X[1] = 0; sort(X.rbegin(), X.rend()); sort(Y.rbegin(), Y.rend()); 23 | bool flush = (Y[0] == 5); 24 | if (straight) return (flush ? 8 : 4); 25 | if (flush) return 5; 26 | if (X[0] == 4) return 7; 27 | if (X[0] == 3) return (X[1] == 2 ? 6 : 3); 28 | if (X[0] == 2) return (X[1] == 2 ? 2 : 1); 29 | return 0; 30 | } 31 | 32 | vector sort_hands(const vector& hand, bool ace) { 33 | int N = hand.size(); 34 | vector> vec(N); 35 | REP(i,N) { 36 | int cnt = 0, num = hand[i].rank; 37 | for (card c : hand) if (num == c.rank) ++cnt; 38 | vec[i] = make_pair(cnt, num); 39 | } 40 | REP(i,N) if (vec[i].second == 1 && ace) vec[i].second = 14; 41 | sort(vec.rbegin(), vec.rend()); 42 | vector res(N); 43 | REP(i,N) res[i] = vec[i].second; 44 | return res; 45 | } 46 | 47 | int poker(const vector& hand) { 48 | int a = poker_hand(hand); 49 | bool flag = ((a != 4 && a != 8) || hand[0].rank > 8 || hand[1].rank > 8); 50 | vector vec = sort_hands(hand, flag); 51 | int res = (a << 20); 52 | REP(i,5) res += (vec[i] << ((4 - i) * 4)); 53 | return res; 54 | } 55 | -------------------------------------------------------------------------------- /Structure/SkewHeap.cpp: -------------------------------------------------------------------------------- 1 | // no reduce 2 | struct Heap { 3 | shared_ptr l,r; 4 | Data val; 5 | Heap(Data v) : val(v) {} 6 | Data top() { return val; } 7 | }; 8 | shared_ptr meld(shared_ptr a, shared_ptr b) { 9 | if (!a) return b; 10 | if (!b) return a; 11 | if (a->val > b->val) swap(a, b); 12 | a->r = meld(a->r, b); 13 | swap(a->l, a->r); 14 | return a; 15 | } 16 | shared_ptr push(shared_ptr h, Data v) { 17 | return meld(h, make_shared(v)); 18 | } 19 | shared_ptr pop(shared_ptr h) { 20 | return meld(h->l, h->r); 21 | } 22 | 23 | // enable reduce 24 | struct Heap { 25 | shared_ptr l,r,p; 26 | Data val; 27 | Heap(Data v) : val(v) {} 28 | Data top() { return val; } 29 | }; 30 | shared_ptr meld( 31 | shared_ptr a, shared_ptr b, shared_ptr p = nullptr) { 32 | if (!a) { 33 | if (b) b->p = p; 34 | return b; 35 | } 36 | if (!b) { 37 | if (a) a->p = p; 38 | return a; 39 | } 40 | if (a->val > b->val) swap(a, b); 41 | a->p = p; 42 | a->r = meld(a->r, b, a); 43 | swap(a->l, a->r); 44 | return a; 45 | } 46 | pair, shared_ptr> push(shared_ptr h, Data v) { 47 | auto n = make_shared(v); 48 | return make_pair(meld(h, n), n); 49 | } 50 | shared_ptr pop(shared_ptr h) { 51 | if (h->l) h->l->p.reset(); 52 | if (h->r) h->r->p.reset(); 53 | return meld(h->l, h->r); 54 | } 55 | shared_ptr reduce(shared_ptr h, shared_ptr root, Data v) { 56 | if (v > h->val) return root; 57 | h->val = v; 58 | if (!h->p) return root; 59 | if (h->val < h->p->val) { 60 | if (h->p->l && h->p->l == h) { 61 | h->p->l.reset(); 62 | return meld(h, root); 63 | } else { 64 | h->p->r.reset(); 65 | return meld(h, root); 66 | } 67 | } else return root; 68 | } 69 | -------------------------------------------------------------------------------- /Tex/src/Structure.tex: -------------------------------------------------------------------------------- 1 | \section{Structure} 2 | 3 | \subsection{Union-Find Tree} 4 | 互いに素な集合を扱うためのデータ構造であり,計算量は $O(\alpha(N))$ である. 5 | 経路圧縮のみを行い実装を軽くした場合,計算量は $O(\log N)$ である. 6 | \lstinputlisting{../Structure/UnionFind.cpp} 7 | 8 | \subsection{Segment Tree} 9 | デフォルトは Range Minimum Query.区間は半開区間で指定すること. 10 | \lstinputlisting{../Structure/SegmentTree.cpp} 11 | デフォルトは区間に足せる Range Sum Query と Range Minimum Query.遅延伝播セグメント木である. 12 | \lstinputlisting{../Structure/SegmentTreeLazy.cpp} 13 | 遅延伝播セグメント木の強いバージョン 14 | \lstinputlisting{../Structure/SegmentTreeLazyUniversal.cpp} 15 | 必要な頂点だけ作って処理する RMQ.デフォルトでは $i$ 番目の要素は $i+1$ で初期化されている. 16 | \lstinputlisting{../Structure/BigRangeQuery.cpp} 17 | 二次元セグメント木 18 | \lstinputlisting{../Structure/SegmentTree2D.cpp} 19 | 20 | \subsection{Fenwick Tree} 21 | FenwickTree.デフォルトは Range Sum Query であり, 22 | 引数として与えられるindex以下の部分の和を求める. 23 | \lstinputlisting{../Structure/FenwickTree.cpp} 24 | 25 | \subsection{Square Root Decomposition} 26 | 平方分割によるRMQ.区間の回転や値の挿入や削除ができる. 27 | 区間は閉区間で指定すること. 28 | \lstinputlisting{../Structure/SqrtDecomposition.cpp} 29 | 30 | \subsection{Slide-Min} 31 | スライド最小値.コンストラクタでスライド幅を指定すると,各クエリについて直前$w$個の最小値をO(1)で返す. 32 | \lstinputlisting{../Structure/SlideMin.cpp} 33 | 34 | \subsection{Convex Hull Trick} 35 | \lstinputlisting{../Structure/ConvexHullTrick.cpp} 36 | 37 | \subsection{Skew Heap} 38 | meldが $O(\log N)$ でできる priority queue. 39 | \lstinputlisting{../Structure/SkewHeap.cpp} 40 | 41 | \subsection{Treap} 42 | Treap.乱択アルゴリズムを用いた平衡二分木である. 43 | \lstinputlisting{../Structure/Treap.cpp} 44 | 45 | \subsection{Partition Tree} 46 | $O(N \log^2 N)$ の前処理で,区間のk-th elementを $O(\log^2 N)$ で求めることができる. 47 | \lstinputlisting{../Structure/PartitionTree.cpp} 48 | 49 | \subsection{kD-Tree} 50 | $O(N \log N)$ の前処理で,各クエリに対して $O(\log N)$ で与えられた点に最も近い点を求めることができる. 51 | 与えられた領域内の点の列挙を行うこともできる. 52 | \lstinputlisting{../Structure/kdTree.cpp} 53 | -------------------------------------------------------------------------------- /Structure/UnionFindPersistent.cpp: -------------------------------------------------------------------------------- 1 | // Verified yosupo library-checker (Persistent UnionFind) 2 | 3 | struct PA { 4 | int p, rank; 5 | PA *l, *r; 6 | PA(int p, PA *l, PA *r) : p(p), rank(0), l(l), r(r) {} 7 | PA(int p, int rank, PA *l, PA *r) : p(p), rank(rank), l(l), r(r) {}; 8 | }; 9 | 10 | PA *create(int n, int a = 1, int b = 0) { 11 | if (n == 0) { return nullptr; } 12 | int ln = n >> 1, rn = n - ln - 1; 13 | PA *res = new PA(b, create(ln, a * 2, a + b), create(rn, a * 2, a * 2 + b)); 14 | return res; 15 | } 16 | 17 | PA *get_(PA *uf, int n) { 18 | if (n == 0) return uf; 19 | return get_((n & 1) ? uf->l : uf->r, (n - 1) >> 1); 20 | } 21 | 22 | PA *set_(PA *uf, int n, int x, int rank) { 23 | if (n == 0) return new PA(x, rank, uf->l, uf->r); 24 | if (n & 1) { 25 | PA *p = set_(uf->l, (n - 1) >> 1, x, rank); 26 | return new PA(uf->p, uf->rank, p, uf->r); 27 | } 28 | else { 29 | PA *p = set_(uf->r, (n - 1) >> 1, x, rank); 30 | return new PA(uf->p, uf->rank, uf->l, p); 31 | } 32 | } 33 | 34 | PA *root(PA *uf, int x) { 35 | PA *p = get_(uf, x); 36 | return p->p == x ? p : root(uf, p->p); 37 | } 38 | 39 | PA *merge(PA *uf, int x, int y) { 40 | PA *l = root(uf, x), *r = root(uf, y); 41 | if (l->p == r->p) return uf; 42 | if (l->rank < r->rank) swap(l, r); 43 | int rank = l->rank + (l->rank == r->rank); 44 | PA *res = set_(uf, r->p, l->p, rank); 45 | res = set_(res, l->p, l->p, rank); 46 | return res; 47 | } 48 | 49 | //int main() { 50 | // int n, q; 51 | // cin >> n >> q; 52 | // vector vuf(q+1, nullptr); 53 | // vuf[0] = create(n); 54 | // for (int i = 0; i < q; ++i) { 55 | // int t,k,u,v; 56 | // cin >> t >> k >> u >> v; 57 | // ++k; 58 | // if (t == 0) { 59 | // vuf[i+1] = merge(vuf[k], u, v); 60 | // } else { 61 | // cout << (root(vuf[k], u) == root(vuf[k], v)) << endl; 62 | // } 63 | // } 64 | // return 0; 65 | //} 66 | -------------------------------------------------------------------------------- /Tex/Main.tex: -------------------------------------------------------------------------------- 1 | \documentclass[titlepage, landscape, a4paper, twocolumn, 12pt]{ltjsarticle} 2 | \usepackage[top=15truemm,bottom=15truemm,left=10truemm,right=10truemm]{geometry} 3 | 4 | \usepackage{luatexja-otf} 5 | 6 | \usepackage{ascmac,here,txfonts} 7 | \usepackage{listings} 8 | \usepackage{color} 9 | 10 | \usepackage{bm} 11 | \usepackage{mathrsfs} 12 | \usepackage{amssymb} 13 | 14 | \definecolor{dkgreen}{rgb}{0,0.5,0} 15 | \definecolor{purple}{rgb}{0.5,0,0.5} 16 | \definecolor{comcol}{rgb}{0.8,0.4,0} 17 | 18 | \lstset{ 19 | % language={C++}, 20 | basicstyle={\footnotesize\ttfamily}, 21 | identifierstyle={\footnotesize}, 22 | commentstyle={\footnotesize\itshape\color{red}}, 23 | keywordstyle={\footnotesize\bfseries\color{blue}}, 24 | ndkeywordstyle={\footnotesize\bfseries\color{comcol}}, 25 | morekeywords={void, bool, char, int, short, long, double, auto}, 26 | morekeywords={vector, string, priority\_queue, pair, set, map}, 27 | morekeywords={Data, Weight, Edge, Edges, Graph, Array, Matrix}, 28 | morekeywords={ld, P, L, C, VP}, 29 | morendkeywords={if, else, while, for, do, break, continue, return}, 30 | morendkeywords={operator, const, struct, class, private, public, typedef}, 31 | morendkeywords={using, namespace}, 32 | morendkeywords={REP, ALL}, 33 | stringstyle={\footnotesize\color{purple}}, 34 | frame={tb}, 35 | breaklines=true, 36 | columns=[l]{fullflexible}, 37 | numbers=left, 38 | xrightmargin=0ex, 39 | xleftmargin=3ex, 40 | numberstyle={\scriptsize}, 41 | stepnumber=1, 42 | numbersep=1ex, 43 | lineskip=-0.5ex 44 | } 45 | 46 | \title{Primasta チームライブラリ} 47 | \author{asi1024, primenumber, TakiTakiTakise} 48 | \date{\today} 49 | 50 | \begin{document} 51 | \maketitle 52 | 53 | \include{src/Template} 54 | \include{src/Structure} 55 | \include{src/Graph} 56 | \include{src/Math} 57 | \include{src/Geometry} 58 | \include{src/String} 59 | \include{src/Others} 60 | \include{src/Tips} 61 | 62 | \end{document} 63 | -------------------------------------------------------------------------------- /library.sh: -------------------------------------------------------------------------------- 1 | #/#!/bin/bash 2 | 3 | cat Geometry/Geometry.cpp >> Geometry.cpp 4 | cat Geometry/Intersect.cpp >> Geometry.cpp 5 | cat Geometry/Convex.cpp >> Geometry.cpp 6 | 7 | cat Graph/ShortestPath.cpp >> Graph.cpp 8 | cat Graph/MinimumSpanningTree.cpp >> Graph.cpp 9 | cat Graph/FordFulkerson.cpp >> Graph.cpp 10 | cat Graph/Dinic.cpp >> Graph.cpp 11 | cat Graph/MinCostFlow.cpp >> Graph.cpp 12 | cat Graph/BipartiteMatching.cpp >> Graph.cpp 13 | cat Graph/StronglyConnectedComponents.cpp >> Graph.cpp 14 | cat Graph/2SAT.cpp >> Graph.cpp 15 | cat Graph/LCA\(BinarySearch\).cpp >> Graph.cpp 16 | cat Graph/LCA\(RMQ\).cpp >> Graph.cpp 17 | cat Graph/ShortestHamiltonPath.cpp >> Graph.cpp 18 | cat Graph/ArticulationPoints.cpp >> Graph.cpp 19 | cat Graph/Bridge.cpp >> Graph.cpp 20 | 21 | cat Math/Math.cpp >> Math.cpp 22 | cat Math/Matrix.cpp >> Math.cpp 23 | cat Math/SquareMatrix.cpp >> Math.cpp 24 | 25 | cat Others/Compressor.cpp >> Others.cpp 26 | cat Others/LIS.cpp >> Others.cpp 27 | cat Others/Dice.cpp >> Others.cpp 28 | cat Others/RegularOctahedron.cpp >> Others.cpp 29 | 30 | cat Structure/UnionFind.cpp >> Structure.cpp 31 | cat Structure/SegmentTree.cpp >> Structure.cpp 32 | cat Structure/FenwickTree.cpp >> Structure.cpp 33 | cat Structure/SqrtDecomposition.cpp >> Structure.cpp 34 | cat Structure/Treap.cpp >> Structure.cpp 35 | 36 | OPT="--highlight=cpp --color --landscape --columns=2" 37 | enscript $OPT -o Geometry.ps Geometry.cpp 38 | enscript $OPT -o Graph.ps Graph.cpp 39 | enscript $OPT -o Math.ps Math.cpp 40 | enscript $OPT -o Others.ps Others.cpp 41 | enscript $OPT -o Structure.ps Structure.cpp 42 | enscript $OPT -o Template.ps Template.cpp 43 | enscript --highlight=elisp --color --landscape --columns=2 -o Emacs.ps .emacs 44 | 45 | rm -f Geometry.cpp 46 | rm -f Graph.cpp 47 | rm -f Math.cpp 48 | rm -f Others.cpp 49 | rm -f Structure.cpp 50 | -------------------------------------------------------------------------------- /Math/SquareMatrix.cpp: -------------------------------------------------------------------------------- 1 | Matrix scalar(int size, Data k) { 2 | Matrix mat(size, Array(size, 0)); 3 | REP(i,size) mat[i][i] = k; 4 | return mat; 5 | } 6 | 7 | Matrix operator^(const Matrix &lhs, const int n) { 8 | if (n == 0) return scalar(lhs.size(), 1); 9 | Matrix res = (lhs * lhs) ^ (n / 2); 10 | if (n % 2) res = res * lhs; 11 | return res; 12 | } 13 | 14 | Data det(Matrix A) { 15 | const int n = A.size(); 16 | Data D = Data(1); 17 | for (int i = 0; i < n; ++i) { 18 | int pivot = i; 19 | for (int j = i+1; j < n; ++j) 20 | if (abs(A[j][i]) > abs(A[pivot][i])) pivot = j; 21 | swap(A[pivot], A[i]); 22 | D = D * A[i][i] * Data(i != pivot ? -1 : 1); 23 | if (is_zero(A[i][i])) break; 24 | for(int j = i+1; j < n; ++j) 25 | for(int k = n-1; k >= i; --k) 26 | A[j][k] = A[j][k] - A[i][k] * A[j][i] / A[i][i]; 27 | } 28 | return D; 29 | } 30 | 31 | // LUP Decomposition 32 | // PA = LU 33 | // |1 0 0| 34 | // L=|* 1 0| 35 | // |* * 1| 36 | // 37 | // |* * *| 38 | // U=|0 * *| 39 | // |0 0 *| 40 | // 41 | // |U U U| 42 | //ret=|L U U| P:permutation 43 | // |L L U|, 44 | pair> LUPDecomposition(Matrix A) { 45 | int n=A.size(); 46 | vector perm(n); 47 | iota(begin(perm),end(perm),0); 48 | REP(i,n){ 49 | int pivot = i; 50 | for(int j = i+1; j < n; ++j) 51 | if(abs(A[j][i]) > abs(A[pivot][i])) pivot = j; 52 | swap(A[pivot], A[i]); 53 | swap(perm[pivot], perm[i]); 54 | for(int j=i+1; j < n; ++j) { 55 | A[j][i] /= A[i][i]; 56 | for (int k = i+1; k < n; ++k) 57 | A[j][k] = fma(-A[i][k], A[j][i], A[j][k]); 58 | } 59 | } 60 | return make_pair(A, perm); 61 | } 62 | 63 | Array LUPBackSubstitution(Matrix& LU, vector& perm, Array a) { 64 | int n=LU.size(); 65 | Array tmp(n); 66 | REP(i,n) tmp[i] = a[perm[i]]; 67 | swap(tmp, a); 68 | REP(i,n) { 69 | REP(j,i) a[i] = fma(-a[j], LU[i][j], a[i]); 70 | } 71 | for(int i=n-1; i >= 0; --i) { 72 | for(int j=i+1; j < n; ++j) 73 | a[i] = fma(-a[j], LU[i][j], a[i]); 74 | a[i] /= LU[i][i]; 75 | } 76 | return a; 77 | } 78 | -------------------------------------------------------------------------------- /Graph/MinCostFlow.cpp: -------------------------------------------------------------------------------- 1 | #define MAX_V 10000 2 | int V; 3 | 4 | using Weight = int; 5 | const Weight INF = 1000000000; 6 | // const Weight eps = 1e-8; 7 | 8 | struct Edge{ 9 | int src, dest; 10 | int cap, rev; 11 | Weight weight; 12 | bool operator < (const Edge &rhs) const {return weight > rhs.weight;} 13 | }; 14 | 15 | using Edges = vector; 16 | using Graph = vector; 17 | using Array = vector; 18 | using Matrix = vector; 19 | 20 | Weight h[MAX_V]; // potential 21 | Weight dist[MAX_V]; // minimum distance 22 | int prevv[MAX_V], preve[MAX_V]; // previous vertex and edge 23 | 24 | void add_edge(Graph &g, int src, int dest, int cap, Weight weight) { 25 | g[src].push_back((Edge){src, dest, cap, (int)g[dest].size(), weight}); 26 | g[dest].push_back((Edge){dest, src, 0, (int)g[src].size() - 1, -weight}); 27 | } 28 | 29 | Weight min_cost_flow(Graph &g, int s, int t, int f) { 30 | Weight res = 0; V = g.size(); 31 | memset(h, 0, sizeof(h)); 32 | using P = pair; 33 | while (f > 0) { 34 | priority_queue, greater

> que; 35 | fill(dist, dist + V, INF); 36 | dist[s] = 0; 37 | que.push(P(0, s)); 38 | while (!que.empty()) { 39 | P p = que.top(); que.pop(); 40 | int v = p.second; 41 | if (dist[v] < p.first) continue; 42 | REP(i, g[v].size()) { 43 | Edge &e = g[v][i]; 44 | if (e.cap > 0 && dist[e.dest] > dist[v] + e.weight + h[v] - h[e.dest] /* + eps */) { 45 | dist[e.dest] = dist[v] + e.weight + h[v] - h[e.dest]; 46 | prevv[e.dest] = v; 47 | preve[e.dest] = i; 48 | que.push(P(dist[e.dest], e.dest)); 49 | } 50 | } 51 | } 52 | if (dist[t] == INF) return -1; 53 | REP(v, V) h[v] += dist[v]; 54 | 55 | int d = f; 56 | for (int v = t; v != s; v = prevv[v]) d = min(d, g[prevv[v]][preve[v]].cap); 57 | f -= d; 58 | res += d * h[t]; 59 | for (int v = t; v != s; v = prevv[v]) { 60 | Edge &e = g[prevv[v]][preve[v]]; 61 | e.cap -= d; 62 | g[v][e.rev].cap += d; 63 | } 64 | } 65 | return res; 66 | } 67 | -------------------------------------------------------------------------------- /Tex/src/Tips.tex: -------------------------------------------------------------------------------- 1 | \section{Tips} 2 | 3 | \subsection{定理} 4 | \subsubsection{双対定理} 5 | \[ \min\{ \bm{c}^\top \bm{x} \, | \, \bm{A} \bm{x} = \bm{b}, \bm{x} \geq \bm{0} \} 6 | = \max\{ \bm{b}^\top \bm{w} \, | \, \bm{A}^\top \bm{w} \leq \bm{c} \} \] 7 | \[ \min\{ \bm{c}^\top \bm{x} \, | \, \bm{A} \bm{x} \geq \bm{b}, \bm{x} \geq \bm{0} \} 8 | = \max\{ \bm{b}^\top \bm{w} \, | \, \bm{A}^\top \bm{w} \leq \bm{c}, w \geq \bm{0} \} \] 9 | 10 | \subsubsection{ヤング図形} 11 | 12 | \subsection{STL-Algorithm} 13 | \subsubsection{header: algorithm} 14 | \begin{lstlisting}[caption=辞書順比較] 15 | lexicographical_compare(begin(a),end(a),begin(b)); 16 | \end{lstlisting} 17 | aとbを辞書順比較する。第四引数に比較関数を渡せる。 18 | \begin{lstlisting}[caption=最大値、最小値] 19 | max_element(begin(a),end(a)); 20 | min_element(begin(a),end(a)); 21 | minmax_element(begin(a),end(a)); 22 | \end{lstlisting} 23 | 最大値のイテレータ、最小値のイテレータ、そのペアをそれぞれ返す。第三引数に比較関数を渡せる。 24 | \begin{lstlisting}[caption=順列] 25 | is_permutation(begin(a),end(a),begin(b)); 26 | \end{lstlisting} 27 | aがbの並べ替えになっていればtrueを返す。長さが違うことがある場合は第4引数にend(b)を渡す。最後の引数に等号比較関数を渡せる。 28 | \begin{lstlisting}[caption=ソート済みコンテナ操作] 29 | merge(begin(a),end(a),begin(b),end(b),begin(c)); 30 | inplace_merge(begin(a),middle,end(a),begin(b)); 31 | includes(begin(a),end(a),begin(b),end(b)); 32 | set_difference(begin(a),end(a),begin(b),end(b),begin(c)); 33 | set_intersection(begin(a),end(a),begin(b),end(b),begin(c)); 34 | set_symmetric_difference(begin(a),end(a),begin(b),end(b),begin(c)); 35 | \end{lstlisting} 36 | \subsubsection{header: numeric} 37 | \begin{lstlisting}[caption=和] 38 | accumlate(begin(a),end(a),0); 39 | \end{lstlisting} 40 | 第三引数に初期値、第四引数に演算を渡せる 41 | \begin{lstlisting}[caption=累積和] 42 | partial_sum(begin(a),end(a),begin(s)+1); 43 | \end{lstlisting} 44 | sにはaの累積和が入る。sはaより1長いこと。 45 | \begin{lstlisting}[caption=階差数列] 46 | adjacent_difference(begin(a),end(a),begin(s)); 47 | \end{lstlisting} 48 | \begin{lstlisting}[caption=内積] 49 | inner_product(begin(a),end(a),begin(s),0); 50 | \end{lstlisting} 51 | 第四引数に初期値を渡す。第五引数に加法、第六引数に乗法に相当する演算を渡してやることもできる 52 | \begin{lstlisting}[caption=連続した数列] 53 | iota(begin(a),end(a),0); 54 | \end{lstlisting} 55 | この例だとaは[0,1,2,\ldots]となる 56 | -------------------------------------------------------------------------------- /String/AhoCorasick.cpp: -------------------------------------------------------------------------------- 1 | struct AhoCorasick { 2 | static const int SIZE = 128; 3 | struct State { 4 | int index, next[SIZE]; 5 | vector accept; 6 | State(int index) : index(index) { memset(next, -1, sizeof(next)); } 7 | }; 8 | 9 | vector pma; 10 | vector lens; 11 | 12 | AhoCorasick(const vector &str) { 13 | pma.clear(); 14 | pma.push_back(State(0)); 15 | lens.clear(); 16 | 17 | REP(i,str.size()) { 18 | int t = 0; 19 | for (char c : str[i]) { 20 | if (pma[t].next[(int)c] == -1) { 21 | int m = pma.size(); 22 | pma[t].next[(int)c] = m; 23 | pma.push_back(State(m)); 24 | } 25 | t = pma[t].next[(int)c]; 26 | } 27 | pma[t].accept.push_back(lens.size()); 28 | lens.push_back(str[i].size()); 29 | } 30 | 31 | queue que; 32 | for (int c = 1; c < SIZE; c++) { 33 | if (pma[0].next[c] != -1) { 34 | pma[pma[0].next[c]].next[0] = 0; 35 | que.push(pma[0].next[c]); 36 | } 37 | else { 38 | pma[0].next[c] = 0; 39 | } 40 | } 41 | while (!que.empty()) { 42 | int t = que.front(); 43 | que.pop(); 44 | for (int c = 1; c < SIZE; c++) { 45 | if (pma[t].next[c] != -1) { 46 | que.push(pma[t].next[c]); 47 | int r = pma[t].next[0]; 48 | while (pma[r].next[c] == -1) r = pma[r].next[0]; 49 | pma[pma[t].next[c]].next[0] = pma[r].next[c]; 50 | for (int i : pma[pma[r].next[c]].accept) 51 | pma[pma[t].next[c]].accept.push_back(i); 52 | } 53 | } 54 | } 55 | } 56 | 57 | int sub(int index, int c) { 58 | return pma[index].next[c] != -1 ? 59 | pma[index].next[c] : 60 | pma[index].next[c] = sub(pma[index].next[0], c); 61 | } 62 | 63 | vector query(string &t) { 64 | int index = 0; 65 | vector ret(lens.size(), -1); 66 | REP(i,t.size()) { 67 | int c = t[i]; 68 | index = sub(index, c); 69 | for (int j : pma[index].accept) { 70 | if (ret[j] != -1) continue; 71 | ret[j] = i - lens[j] + 1; 72 | } 73 | } 74 | return ret; 75 | } 76 | }; 77 | -------------------------------------------------------------------------------- /Math/SparseMatrix.cpp: -------------------------------------------------------------------------------- 1 | using Data = long double; 2 | using Array = vector; 3 | using Matrix = vector; 4 | using Elem = pair, Data>; 5 | using SpMat = vector; 6 | 7 | bool is_zero(Data dat) { return (abs(dat) < eps); } 8 | 9 | SpMat operator-(SpMat mat) { 10 | for(auto& v:mat) 11 | get<2>(p) = -get<2>(p); 12 | return mat; 13 | } 14 | 15 | SpMat operator+(const SpMat& lhs, const SpMat &rhs) { 16 | SpMat res; 17 | auto itr = begin(rhs); 18 | for (auto t : lhs) { 19 | while (itr != end(rhs) && itr->first < t.first) { 20 | res.push_back(*itr); 21 | ++itr; 22 | } 23 | Data val = t.second; 24 | if (itr != end(rhs) && t.first == itr->first) val += itr->second; 25 | res.emplace_back(t.first, val); 26 | } 27 | return res; 28 | } 29 | 30 | SpMat operator-(const SpMat& lhs, const SpMat &rhs) { 31 | SpMat res; 32 | auto itr = begin(rhs); 33 | for (auto t : lhs) { 34 | while (itr != end(rhs) && itr->first < t.first) { 35 | res.push_back(*itr); 36 | ++itr; 37 | } 38 | Data val = t.second; 39 | if (itr != end(rhs) && t.first == itr->first) val -= itr->second; 40 | res.emplace_back(t.first, val); 41 | } 42 | return res; 43 | } 44 | 45 | SpMat transpose(const SpMat &A) { 46 | SpMat res; 47 | for (auto t : A) { 48 | res.emplace_back(make_pair(t.first.second, t.first.first), t.second); 49 | } 50 | sort(ALL(res), [](Elem l, Elem r) { return l.first < r.first; }); 51 | return res; 52 | } 53 | 54 | Matrix to_mat(const SpMat &spmat, int row, int col) { 55 | Matrix res(row, Array(col, 0)); 56 | for (auto t : A) { 57 | int i, j; 58 | Data v; 59 | tie(tie(i, j), v) = t; 60 | res[i][j] = v; 61 | } 62 | return res; 63 | } 64 | 65 | Array mult(const SpMat &lhs, const Array &rhs, int len) { 66 | Array res(len, 0); 67 | for (auto t : lhs) { 68 | int i, j; 69 | Data v; 70 | tie(tie(i, j), v) = t; 71 | res[i] += v * rhs[j]; 72 | } 73 | return res; 74 | } 75 | 76 | Array mult(const Array &lhs, const SpMat &rhs, int len) { 77 | Array res(len, 0); 78 | for (auto t : lhs) { 79 | int i, j; 80 | Data v; 81 | tie(tie(i, j), v) = t; 82 | res[j] += rhs[i] * v; 83 | } 84 | return res; 85 | } 86 | 87 | //rankmat for SparseMatrix is none 88 | -------------------------------------------------------------------------------- /Structure/BigRangeQuery.cpp: -------------------------------------------------------------------------------- 1 | // Big Range Query 2 | // (verified : KOJ0042) 3 | 4 | // initialize : [0, 1, 2, ...] 5 | // update(t, p, v) : set value v in t[p] 6 | // query(t, x, y) : min[x, y) and max[x, y) of t 7 | 8 | struct Data { 9 | int mi, ma; 10 | Data() : mi(0x7FFFFFFF), ma(0x80000000) {;} 11 | Data(int n) : mi(n), ma(n) {;} 12 | Data(int n, int m) : mi(n), ma(m) {;} 13 | }; 14 | 15 | inline Data Merge(Data left, Data right) { 16 | return Data(min(left.mi, right.mi), max(left.ma, right.ma)); 17 | } 18 | 19 | inline Data init(int left, int right) { return Data(left, right - 1); } 20 | 21 | struct BigRMQ { 22 | int lpos, rpos; 23 | Data value; 24 | BigRMQ *left, *right; 25 | BigRMQ() 26 | : lpos(0), rpos(1<<30), value(Data()), 27 | left(nullptr), right(nullptr) {} 28 | BigRMQ(int l, int r) 29 | : lpos(l), rpos(r), value(init(l, r)), 30 | left(nullptr), right(nullptr) {} 31 | }; 32 | 33 | Data val(BigRMQ *t, int l, int r) { 34 | if (!t) return init(l, r); else return t->value; 35 | } 36 | 37 | void update(BigRMQ *t, int pos, Data value) { 38 | if (t->rpos - t->lpos <= 1) { t->value = value; return; } 39 | int lpos = t->lpos, rpos = t->rpos; 40 | int mid = (t->lpos + t->rpos) / 2; 41 | if (pos < mid) { 42 | if (!(t->left)) t->left = new BigRMQ(lpos, mid); 43 | update(t->left, pos, value); 44 | } 45 | else { 46 | if (!(t->right)) t->right = new BigRMQ(mid, rpos); 47 | update(t->right, pos, value); 48 | } 49 | t->value = Merge(val(t->left, lpos, mid), val(t->right, mid, rpos)); 50 | } 51 | 52 | Data query(BigRMQ *t, int fr, int to) { 53 | if (fr >= to) return Data(); 54 | if (!t) return init(fr, to); 55 | if (t->rpos <= fr || to <= t->lpos) return Data(); 56 | if (fr <= t->lpos && t->rpos <= to) return t->value; 57 | int mid = (t->lpos + t->rpos) / 2; 58 | Data vl = query(t->left, fr, min(to, mid)); 59 | Data vr = query(t->right, max(fr, mid), to); 60 | return Merge(vl, vr); 61 | } 62 | 63 | // main 64 | 65 | int main() { 66 | int N, Q; 67 | cin >> N >> Q; 68 | BigRMQ seg(0, N+1); 69 | REP(i,Q) { 70 | int a, b, c; 71 | cin >> a >> b >> c; 72 | if (a == 1) cout << query(&seg, b, c+1).mi << endl; 73 | if (a == 2) cout << query(&seg, b, c+1).ma << endl; 74 | if (a == 3) update(&seg, b, Data(c)); 75 | } 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /Tex/src/Graph.tex: -------------------------------------------------------------------------------- 1 | \section{Graph} 2 | 3 | \subsection{最短経路} 4 | 上から順に,ダイクストラ,経路復元付きダイクストラ,ベルマンフォード,ワーシャルフロイド,辺のコストが0か1のときのみ使える幅優先探索である. 5 | \lstinputlisting{../Graph/ShortestPath.cpp} 6 | 7 | \subsection{最小全域木} 8 | クラスカルを用いるときは,比較演算子をの大小関係を変える必要がある.また,頂点数をNに入れておくこと. 9 | \lstinputlisting{../Graph/MinimumSpanningTree.cpp} 10 | 11 | \subsection{最大流} 12 | Ford-Fulkerson 13 | \lstinputlisting{../Graph/FordFulkerson.cpp} 14 | Dinic 15 | \lstinputlisting{../Graph/Dinic.cpp} 16 | 17 | \subsection{最小費用流} 18 | \lstinputlisting{../Graph/MinCostFlow.cpp} 19 | 20 | \subsection{二部グラフの最大マッチング} 21 | \lstinputlisting{../Graph/BipartiteMatching.cpp} 22 | \lstinputlisting{../Graph/HopcroftKarp.cpp} 23 | 24 | \subsection{ハンガリアン法} 25 | \begin{itemize} 26 | \item 二部完全グラフ$K_{n,n}$の最大重みマッチングを求める 27 | \item \verb#m[i][j]#で左側頂点iと右側頂点jの間のコストを与える 28 | \item x: 左側頂点に対応する右側頂点, y: 右側頂点に対応する左側頂点 29 | \item 返り値は最大重みマッチングの重みの合計 30 | \end{itemize} 31 | \lstinputlisting{../Graph/Hungarian.cpp} 32 | 33 | \subsection{強連結成分分解} 34 | \begin{itemize} 35 | \item \verb#vector g[], rg[]# : グラフと逆辺のグラフ.\verb#add_edge#関数で作る 36 | \item cmp[] : DAGのトポロジカル順序.srcから順に番号が付けられる. 37 | \item scc(int) : グラフの頂点数を引数にとり,強連結成分分解を行う.返り値はDAGの頂点数. 38 | \item グラフの頂点数とDAGの頂点数を引数にとり,DAGを生成する.頂点番号はcmpと同じ. 39 | \end{itemize} 40 | \lstinputlisting{../Graph/StronglyConnectedComponents.cpp} 41 | 42 | \subsection{2-SAT} 43 | \lstinputlisting{../Graph/2SAT.cpp} 44 | 45 | \subsection{最小共通祖先} 46 | 二分探索バージョン 47 | \lstinputlisting{../Graph/LCA(BinarySearch).cpp} 48 | RMQバージョン 49 | \lstinputlisting{../Graph/LCA(RMQ).cpp} 50 | データ構造バージョン 51 | \lstinputlisting{../Graph/LCA(Structure).cpp} 52 | 53 | \subsection{重軽分解} 54 | \lstinputlisting{../Graph/HLD.cpp} 55 | 56 | \subsection{最短ハミルトン路} 57 | \lstinputlisting{../Graph/ShortestHamiltonPath.cpp} 58 | 59 | \subsection{彩色数} 60 | \lstinputlisting{../Graph/ChromaticNumber.cpp} 61 | 62 | \subsection{間接点} 63 | \lstinputlisting{../Graph/ArticulationPoints.cpp} 64 | 65 | \subsection{橋} 66 | \lstinputlisting{../Graph/Bridge.cpp} 67 | 68 | \subsection{オイラー路} 69 | \lstinputlisting{../Graph/EulerPath.cpp} 70 | 71 | \subsection{最大独立集合} 72 | \lstinputlisting{../Graph/MaximumIndependentSet.cpp} 73 | 74 | \subsection{最小全域有向木} 75 | \lstinputlisting{../Graph/MinimumArborescence.cpp} 76 | 77 | \subsection{一般グラフの最小カット} 78 | \lstinputlisting{../Graph/GlobalMinimumCut.cpp} 79 | 80 | \subsection{ZDD} 81 | \lstinputlisting{../Graph/ZDD.cpp} 82 | -------------------------------------------------------------------------------- /Structure/SegmentTreeLazy.cpp: -------------------------------------------------------------------------------- 1 | struct SegTreeLazy { 2 | static const int MAX_DEPTH = 18; 3 | static const int STsize = 1 << MAX_DEPTH; 4 | Data data[STsize]; 5 | Data lazy[STsize]; int n; 6 | SegTreeLazy(void) : n(STsize / 2) { 7 | REP(i,STsize){ 8 | data[i]=lazy[i]=0; 9 | } 10 | } 11 | void add(int fr, int to, Data val) { upd_sub(fr, to, 2*n-2, 0, n, val); } 12 | Data sum(int fr, int to) { return sum_sub(fr, to, 2*n-2, 0, n); } 13 | private: 14 | void upd_sub(int fr, int to, int node, int la, int ra, Data val) { 15 | if (ra<=fr || to<=la) return; 16 | if (fr<=la && ra<=to) { 17 | lazy[node] += val; return; 18 | } 19 | data[node] += (min(to, ra) - max(fr, la)) * val; 20 | upd_sub(fr, to, (node-n)*2+0, la, (la+ra)/2, val); 21 | upd_sub(fr, to, (node-n)*2+1, (la+ra)/2, ra, val); 22 | } 23 | Data sum_sub(int fr, int to, int node, int la, int ra) { 24 | if (ra<=fr || to<=la) return Data(); 25 | if (fr<=la && ra<=to) return data[node] + lazy[node]*(ra-la); 26 | Data res = lazy[node] * (min(to, ra) - max(fr, la)); 27 | res += sum_sub(fr, to, (node-n)*2+0, la, (la+ra)/2); 28 | res += sum_sub(fr, to, (node-n)*2+1, (la+ra)/2, ra); 29 | return res; 30 | } 31 | }; 32 | 33 | // Verified : KOJ0093 34 | 35 | using Data = int; 36 | 37 | struct StarrySky { 38 | static const int MAX_DEPTH = 18; 39 | static const int STsize = 1 << MAX_DEPTH; 40 | Data data[STsize]; 41 | Data lazy[STsize]; int n; 42 | StarrySky(void) : n(STsize / 2) { 43 | REP(i,STsize) data[i] = lazy[i] = 0; 44 | } 45 | void add(int fr, int to, Data val) { upd_sub(fr, to, 2*n-2, 0, n, val); } 46 | Data minimum(int fr, int to) { return min_sub(fr, to, 2*n-2, 0, n); } 47 | private: 48 | void upd_sub(int fr, int to, int node, int la, int ra, Data val) { 49 | if (ra<=fr || to<=la) return; 50 | if (fr<=la && ra<=to) { lazy[node] += val; return; } 51 | int left = (node - n) * 2, right = left + 1; 52 | upd_sub(fr, to, left, la, (la+ra)/2, val); 53 | upd_sub(fr, to, right, (la+ra)/2, ra, val); 54 | data[node] = min(data[left] + lazy[left], data[right] + lazy[right]); 55 | } 56 | Data min_sub(int fr, int to, int node, int la, int ra) { 57 | if (ra<=fr || to<=la) return 0x7FFFFFFF; 58 | if (fr<=la && ra<=to) return data[node] + lazy[node]; 59 | Data vl = min_sub(fr, to, (node-n)*2+0, la, (la+ra)/2); 60 | Data vr = min_sub(fr, to, (node-n)*2+1, (la+ra)/2, ra); 61 | return lazy[node] + min(vl, vr); 62 | } 63 | }; 64 | -------------------------------------------------------------------------------- /Structure/kdTree.cpp: -------------------------------------------------------------------------------- 1 | // Point:valarray 2 | ld dist_pc(const Point &p_, const Point &top, const Point &btm) { 3 | ld dist = 0.0; 4 | REP(i,3) { 5 | if (top[i] < p_[i]) dist += (p_[i] - top[i]) * (p_[i] - top[i]); 6 | if (p_[i] < btm[i]) dist += (p_[i] - btm[i]) * (p_[i] - btm[i]); 7 | } 8 | return sqrt(dist); 9 | } 10 | 11 | #define DIM 3 12 | struct kdTree { 13 | Point p; 14 | kdTree *l, *r; 15 | kdTree(const Point &p_) : p(p_), l(nullptr), r(nullptr) {} 16 | kdTree *insert(const Point &p_, int dep = 0) { 17 | if (p[dep] > p_[dep]) { 18 | if (l == nullptr) return l = new kdTree(p_); 19 | else return l->insert(p_, (dep+1)%DIM); 20 | } else { 21 | if (r == nullptr) return r = new kdTree(p_); 22 | else return r->insert(p_, (dep+1)%DIM); 23 | } 24 | } 25 | kdTree *nearer(const Point &p_, kdTree *x, kdTree *y) { 26 | ld dx = dist(p_ - x->p); 27 | ld dy = dist(p_ - y->p); 28 | return (dx < dy) ? x : y; 29 | } 30 | // init: top = {INF, INF, INF}, btm = {-INF, -INF, -INF} 31 | kdTree *nearest(const Point &p_, const Point &top, const Point &btm, int dep = 0) { 32 | Point ltop = top, rbtm = btm; 33 | ltop[dep] = p[dep]; 34 | rbtm[dep] = p[dep]; 35 | if (l == nullptr) { 36 | if (r == nullptr) return this; 37 | return nearer(p_, this, r->nearest(p_, top, rbtm, (dep+1)%DIM)); 38 | } else if (r == nullptr) { 39 | return nearer(p_, this, l->nearest(p_, ltop, btm, (dep+1)%DIM)); 40 | } else if (p[dep] > p_[dep]) { 41 | kdTree *near = l->nearest(p_, ltop, btm, (dep+1)%DIM); 42 | ld dist_now = dist(near->p - p_); 43 | ld dist_another = dist_pc(p_, top, rbtm); 44 | if (dist_another < dist_now) { 45 | kdTree *near2 = r->nearest(p_, top, rbtm, (dep+1)%DIM); 46 | ld dist2 = dist(near2->p - p_); 47 | if (dist2 < dist_now) return nearer(p_, this, near2); 48 | else return nearer(p_, this, near); 49 | } else { 50 | return nearer(p_, this, near); 51 | } 52 | } else { 53 | kdTree *near = r->nearest(p_, top, rbtm, (dep+1)%DIM); 54 | ld dist_now = dist(near->p - p_); 55 | ld dist_another = dist_pc(p_, ltop, btm); 56 | if (dist_another < dist_now) { 57 | kdTree *near2 = l->nearest(p_, ltop, btm, (dep+1)%DIM); 58 | ld dist2 = dist(near2->p - p_); 59 | if (dist2 < dist_now) return nearer(p_, this, near2); 60 | else return nearer(p_, this, near); 61 | } else { 62 | return nearer(p_, this, near); 63 | } 64 | } 65 | } 66 | }; 67 | -------------------------------------------------------------------------------- /Structure/SqrtDecomposition.cpp: -------------------------------------------------------------------------------- 1 | using Data = int; 2 | 3 | const int num = 500; 4 | 5 | const Data identity = 1000000000; 6 | Data merge(Data a, Data b) { 7 | return min(a, b); 8 | } 9 | 10 | class RangeMinimumQuery { 11 | private: 12 | int renewCount; 13 | vector> dat; 14 | vector mindat; 15 | void renew(int n) { 16 | Data mi = identity; 17 | for (int i = 0; i < dat[n].size(); i++) 18 | mi = merge(mi, dat[n][i]); 19 | mindat[n] = mi; 20 | } 21 | void smooth(void) { 22 | vector v; 23 | for (int i = 0; i < num; i++) 24 | for (int j = 0; j < dat[i].size(); j++) 25 | v.push_back(dat[i][j]); 26 | dat = vector>(num); 27 | for (int i = 0; i < v.size(); i++) dat[i/num].push_back(v[i]); 28 | for (int i = 0; i < num; i++) renew(i); 29 | } 30 | pair place(int n) { 31 | int cnt = 0; 32 | for (int i = 0; i < num; i++) { 33 | if (cnt + dat[i].size() > n) 34 | return make_pair(i, n - cnt); 35 | cnt += dat[i].size(); 36 | } 37 | assert(false); 38 | return make_pair(0, 0); 39 | } 40 | public: 41 | RangeMinimumQuery(const vector &v) { 42 | dat.resize(num); mindat.resize(num); 43 | dat[0] = v; smooth(); 44 | renewCount = num; 45 | } 46 | void update(int pos, int val) { 47 | pair p = place(pos); 48 | dat[p.first][p.second] = val; 49 | renew(p.first); 50 | } 51 | void insert(int p, Data val) { 52 | pair pos = place(p); 53 | dat[pos.first].insert(dat[pos.first].begin() + pos.second, val); 54 | if (--renewCount <= 0) { smooth(); renewCount = num; } 55 | else { renew(pos.first); } 56 | } 57 | void erase(int p) { 58 | pair pos = place(p); 59 | dat[pos.first].erase(dat[pos.first].begin() + pos.second); 60 | if (--renewCount <= 0) { smooth(); renewCount = num; } 61 | else { renew(pos.first); } 62 | } 63 | void rotate(int l, int r) { // closed interval 64 | pair lpos = place(l), rpos = place(r); 65 | Data val = dat[rpos.first][rpos.second]; 66 | dat[rpos.first].erase(dat[rpos.first].begin() + rpos.second); 67 | dat[lpos.first].insert(dat[lpos.first].begin() + lpos.second, val); 68 | if (--renewCount <= 0) { smooth(); renewCount = num; } 69 | else { renew(lpos.first); renew(rpos.first); } 70 | } 71 | Data value(int pos) { 72 | pair p = place(pos); 73 | return dat[p.first][p.second]; 74 | } 75 | Data minimum(int l, int r) { // closed interval 76 | pair lpos = place(l), rpos = place(r); 77 | Data mi = identity; 78 | if (lpos.first == rpos.first) { 79 | for (int i = lpos.second; i <= rpos.second; i++) 80 | mi = merge(mi, dat[lpos.first][i]); 81 | } 82 | else { 83 | for (int i = lpos.second; i < dat[lpos.first].size(); i++) 84 | mi = merge(mi, dat[lpos.first][i]); 85 | for (int i = lpos.first + 1; i < rpos.first; i++) 86 | mi = merge(mi, mindat[i]); 87 | for (int i = 0; i <= rpos.second; i++) 88 | mi = merge(mi, dat[rpos.first][i]); 89 | } 90 | return mi; 91 | } 92 | }; 93 | -------------------------------------------------------------------------------- /Graph/HLD.cpp: -------------------------------------------------------------------------------- 1 | struct HeavyLightDecomposition { 2 | struct Chain { 3 | int depth; 4 | pair parent; // chain number, index 5 | vector > child; // child chain number, parent index 6 | vector mapfrom; 7 | // SegmentTree stree; 8 | Chain() {;} 9 | // Chain (int N) : stree(N) {;} 10 | }; 11 | Graph baseG; 12 | vector chains; 13 | vector> mapto; // raw index -> chain number & index 14 | vector> mapfrom; // chain number & index -> raw index 15 | 16 | HeavyLightDecomposition() {;} 17 | HeavyLightDecomposition(const Graph &g) { 18 | baseG = g; 19 | const int n = baseG.size(); 20 | mapto = vector>(n, make_pair(-1, -1)); 21 | mapfrom.clear(); 22 | vector size(n, 0); 23 | int start = -1; 24 | REP(i,n) if (baseG[i].size() <= 1) { start = i; break; } 25 | assert(start != -1); 26 | size_check_bfs(start, size); 27 | decomposition(start, start, 0, 0, 0, size); 28 | } 29 | 30 | /* 31 | int depth(int t) { 32 | return chains[mapto[t].first].depth; 33 | } 34 | */ 35 | 36 | private: 37 | int decomposition(int from, int parent, int depth, int pnumber, int pindex, const vector &size) { 38 | vector seq; 39 | bfs(from, parent, seq, size); 40 | const int c = chains.size(); 41 | // chains.push_back(Chain((int)seq.size())); 42 | chains.push_back(Chain()); 43 | chains[c].depth = depth; 44 | chains[c].parent = make_pair(pnumber, pindex); 45 | REP(i,seq.size()) { 46 | mapto[seq[i]] = make_pair(c, i); 47 | chains[c].mapfrom.push_back(seq[i]); 48 | } 49 | mapfrom.push_back(chains[c].mapfrom); 50 | REP(i,seq.size()) { 51 | for (Edge e: baseG[seq[i]]) { 52 | if (mapto[e.dest].first != -1) continue; 53 | int nc = decomposition(e.dest, seq[i], depth + 1, c, i, size); 54 | chains[c].child.push_back(make_pair(nc, i)); 55 | } 56 | } 57 | return c; 58 | } 59 | void size_check_bfs(int start, vector &size) { 60 | const int n = baseG.size(); 61 | queue> que; 62 | que.push(make_pair(start, start)); 63 | int cnt = 0; 64 | vector order(n, -1); 65 | while (!que.empty()) { 66 | int from, parent; tie(from, parent) = que.front(); que.pop(); 67 | order[cnt++] = from; 68 | for (Edge e: baseG[from]) { 69 | if (e.dest == parent) continue; 70 | que.push(make_pair(e.dest, from)); 71 | } 72 | } 73 | assert(cnt == n); 74 | reverse(ALL(order)); 75 | REP(i,n) { 76 | int from = order[i]; 77 | size[from] = 1; 78 | for (Edge e: baseG[from]) size[from] += size[e.dest]; 79 | } 80 | } 81 | void bfs(int from, int parent, vector &seq, const vector &size) { 82 | for (;;) { 83 | seq.push_back(from); 84 | int best = -1, next = -1; 85 | for (Edge e: baseG[from]) { 86 | if (e.dest == parent) continue; 87 | if (best < size[e.dest]) { best = size[e.dest]; next = e.dest; } 88 | } 89 | if (next == -1) break; 90 | parent = from; from = next; 91 | } 92 | } 93 | }; 94 | -------------------------------------------------------------------------------- /Math/Matrix.cpp: -------------------------------------------------------------------------------- 1 | using Data = long double; 2 | using Array = vector; 3 | using Matrix = vector; 4 | 5 | bool is_zero(Data dat) { return (abs(dat) < eps); } 6 | 7 | Matrix operator-(Matrix mat) { 8 | REP(i,mat.size()) REP(j,mat[0].size()) mat[i][j] = -mat[i][j]; 9 | return mat; 10 | } 11 | 12 | Matrix operator+(Matrix lhs, const Matrix &rhs) { 13 | REP(i,lhs.size()) REP(j,lhs[0].size()) lhs[i][j] = lhs[i][j] + rhs[i][j]; 14 | return lhs; 15 | } 16 | 17 | Matrix operator-(Matrix lhs, const Matrix &rhs) { 18 | REP(i,lhs.size()) REP(j,lhs[0].size()) lhs[i][j] = lhs[i][j] - rhs[i][j]; 19 | return lhs; 20 | } 21 | 22 | Matrix operator*(const Matrix &lhs, const Matrix &rhs) { 23 | Matrix res(lhs.size(), Array(rhs[0].size(), 0)); 24 | REP(i,lhs.size()) REP(j,rhs[0].size()) REP(k,rhs.size()) 25 | res[i][j] = fma(lhs[i][k], rhs[k][j], res[i][j]); 26 | return res; 27 | } 28 | 29 | Array operator+(const Array &lhs, const Array &rhs) { 30 | Array res = lhs; 31 | REP(i,rhs.size()) res[i] = res[i] + rhs[i]; 32 | return res; 33 | } 34 | 35 | Array operator*(const Matrix &lhs, const Array &rhs) { 36 | Array res(lhs.size()); 37 | REP(i,lhs.size()) 38 | res[i] = inner_product(begin(lhs[i]),end(lhs[i]),begin(rhs),Data(0)); 39 | return res; 40 | } 41 | 42 | Array operator*(Data scalar, const Array &rhs) { 43 | Array res(rhs.size()); 44 | REP(i,rhs.size()) 45 | res[i] = scalar * rhs[i]; 46 | return res; 47 | } 48 | 49 | Matrix transpose(const Matrix &A) { 50 | const int n = A[0].size(), m = A.size(); 51 | Matrix res(n, Array(m, 0)); 52 | REP(i,n)REP(j,m) res[i][j] = A[j][i]; 53 | return res; 54 | } 55 | 56 | Data inner_product_ex(const Array& a, const Array& b, const Matrix& m) { 57 | Array b_prime = m*b; 58 | return inner_product(begin(a),end(a),begin(b_prime),Data(0)); 59 | } 60 | 61 | Data norm(const Array &a) { 62 | return inner_product(begin(a),end(a),begin(a),Data(0)); 63 | } 64 | 65 | Data norm(const Array &a, const Matrix &M) { 66 | return inner_product_ex(a,a,M); 67 | } 68 | 69 | int rankMat(Matrix A) { 70 | const int n = A.size(), m = A[0].size(); 71 | int r = 0; 72 | for (int i = 0; r < n && i < m; ++i) { 73 | int pivot = r; 74 | for (int j = r+1; j < n; ++j) 75 | if (abs(A[j][i]) > abs(A[pivot][i])) pivot = j; 76 | swap(A[pivot], A[r]); 77 | if (is_zero(A[r][i])) continue; 78 | for (int k = m-1; k >= i; --k) 79 | A[r][k] = A[r][k] / A[r][i]; 80 | for(int j = r+1; j < n; ++j) 81 | for(int k = m-1; k >= i; --k) 82 | A[j][k] = fma(-A[r][k], A[j][i], A[j][k]); 83 | ++r; 84 | } 85 | return r; 86 | } 87 | 88 | Data det(Matrix A) { 89 | const int n = A.size(); 90 | Data D = Data(1); 91 | for (int i = 0; i < n; ++i) { 92 | int pivot = i; 93 | for (int j = i+1; j < n; ++j) 94 | if (abs(A[j][i]) > abs(A[pivot][i])) pivot = j; 95 | swap(A[pivot], A[i]); 96 | D = D * A[i][i] * Data(i != pivot ? -1 : 1); 97 | if (is_zero(A[i][i])) break; 98 | for(int j = i+1; j < n; ++j) 99 | for(int k = n-1; k >= i; --k) 100 | A[j][k] = A[j][k] - A[i][k] * A[j][i] / A[i][i]; 101 | } 102 | return D; 103 | } 104 | -------------------------------------------------------------------------------- /Graph/ZDD.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | #include 3 | 4 | #define REP(i,n) for(int i=0;i<(int)(n);i++) 5 | #define ALL(x) (x).begin(),(x).end() 6 | 7 | using namespace std; 8 | 9 | using Mod = long long; 10 | */ 11 | 12 | struct Edge{ int src, dest; }; 13 | 14 | using Edges = vector; 15 | using Graph = vector; 16 | 17 | void add_edge(Graph &g, int src, int dest) { 18 | g[src].push_back((Edge){src, dest}); 19 | g[dest].push_back((Edge){dest, src}); 20 | } 21 | 22 | Mod zdd(const Graph &g, int s, int t) { 23 | int N = g.size(); 24 | vector> tr(N); 25 | vector pos(N, -1); 26 | queue que; 27 | pos[s] = 0; que.push(s); 28 | int cnt = 0; 29 | while (!que.empty()) { 30 | int v = que.front(); que.pop(); 31 | for (Edge e: g[v]) { 32 | int w = e.dest; 33 | if (pos[w] != -1) continue; 34 | que.push(w); 35 | ++cnt; pos[w] = cnt; 36 | } 37 | } 38 | REP(i,N) assert(pos[i] != -1); // assert 39 | REP(i,N) for (Edge e: g[i]) 40 | if (pos[e.src] < pos[e.dest]) 41 | tr[pos[e.src]].push_back(pos[e.dest]); 42 | Mod res = 0; 43 | map>,Mod> memo; 44 | for (int i: tr[0]) { 45 | vector init(N, -1); 46 | init[0] = i; init[i] = 0; 47 | memo[make_pair(1, init)] = Mod(1); 48 | } 49 | for (auto it = memo.begin(); (it->first).first < N; ++it) { 50 | int v = (it->first).first; 51 | vector mate = (it->first).second; 52 | Mod cnt = it->second; 53 | if (mate[v] == -2) { 54 | memo[make_pair(v+1, mate)] += cnt; 55 | } 56 | else if (mate[v] == -1) { 57 | mate[v] = -2; 58 | memo[make_pair(v+1, mate)] += cnt; 59 | for(int a: tr[v]) { 60 | for (int b: tr[v]) { 61 | if (a == b) break; 62 | if (mate[a] == -2 || mate[b] == -2 || mate[a] == b) continue; 63 | vector nx = mate; 64 | nx[v] = -2; 65 | if (nx[a] == -1) { 66 | if (nx[b] == -1) { nx[a] = b; nx[b] = a; } 67 | else { nx[a] = nx[b]; nx[nx[b]] = a; nx[b] = -2; } 68 | } 69 | else { 70 | if (nx[b] == -1) { nx[b] = nx[a]; nx[nx[a]] = b; nx[a] = -2; } 71 | else { swap(nx[nx[a]], nx[nx[b]]); nx[a] = -2; nx[b] = -2; } 72 | } 73 | memo[make_pair(v+1, nx)] += cnt; 74 | } 75 | } 76 | } 77 | else { 78 | if (v == pos[t]) res += cnt; 79 | for(int a: tr[v]) { 80 | if (mate[a] == -2) continue; 81 | if (mate[a] == -1) { 82 | vector nx = mate; 83 | nx[nx[v]] = a; nx[a] = nx[v]; nx[v] = -2; 84 | memo[make_pair(v+1, nx)] += cnt; 85 | } 86 | else { 87 | if (mate[v] == a) continue; 88 | vector nx = mate; 89 | nx[nx[a]] = nx[v]; nx[nx[v]] = nx[a]; 90 | nx[a] = -2; nx[v] = -2; 91 | memo[make_pair(v+1, nx)] += cnt; 92 | } 93 | } 94 | } 95 | } 96 | return res; 97 | } 98 | 99 | /* 100 | int main() { 101 | for (int n = 1; n <= 8; ++n) { 102 | int N = n + 1; 103 | Graph g(N * N); 104 | REP(i,N) REP(j,N-1) add_edge(g, i*N+j, i*N+j+1); 105 | REP(i,N-1) REP(j,N) add_edge(g, i*N+j, (i+1)*N+j); 106 | Mod res = zdd(g, 0, N*N-1); 107 | cout << n << " x " << n << " : " << res << endl; 108 | } 109 | return 0; 110 | } 111 | */ 112 | 113 | -------------------------------------------------------------------------------- /Geometry/Visualize.cpp: -------------------------------------------------------------------------------- 1 | // {filename}.out 2> data.js 2 | 3 | ld zoom = 1; 4 | 5 | const int OFFSET = 400; 6 | 7 | void ChangeColor(int r, int g, int b) { 8 | fprintf(stderr, "c.strokeStyle = 'rgb(%d, %d, %d)';\n", r, g, b); 9 | } 10 | void DrawPoint(const P &p) { 11 | fprintf(stderr, "circle(%d, %d, %d)\n", 12 | (int)(OFFSET+zoom*p.real()), 800-OFFSET-(int)(zoom*p.imag()), 2); 13 | } 14 | void DrawLine(const L &l) { 15 | fprintf(stderr, "line(%d, %d, %d, %d)\n", 16 | (int)(OFFSET+zoom*l.a.real()), 800-OFFSET-(int)(zoom*l.a.imag()), 17 | (int)(OFFSET+zoom*l.b.real()), 800-OFFSET-(int)(zoom*l.b.imag())); 18 | } 19 | void DrawPolygon(const vector

&p) { 20 | const int n = p.size(); 21 | REP(i,n) DrawLine((L){p[i], p[(i + 1) % n]}); 22 | } 23 | void DrawCircle(const C &c) { 24 | fprintf(stderr, "circle(%d, %d, %d)\n", 25 | (int)(OFFSET + zoom * c.p.real()), 26 | 800 - OFFSET - (int)(zoom * c.p.imag()), (int)(zoom * c.r)); 27 | } 28 | 29 | // new version 30 | 31 | const int COL = 8; 32 | 33 | class Visualizer { 34 | // 0: Gray, 1: Yellow, 2: Cyan, 3: Green, 4: Magenta, 5: Blue, 6: Black, 7:Red 35 | const int r[COL] = {160, 255, 160, 160, 255, 0, 0, 255}; 36 | const int g[COL] = {160, 255, 255, 255, 160, 0, 0, 0}; 37 | const int b[COL] = {160, 0, 255, 160, 255, 255, 0, 0}; 38 | vector

points[COL]; 39 | vector lines[COL]; 40 | vector circles[COL]; 41 | vector polygons[COL]; 42 | P center; 43 | int ax, ay, bx, by, offset; 44 | ld left, right, bottom, top, zoom; 45 | P f(P p) { return conj(p-center) * zoom + P((ax+bx)/2, (ay+by)/2); }; 46 | void drawCircle (P p, int r) { 47 | fprintf(stderr, "circle(%d, %d, %d)\n", (int)f(p).real(), (int)f(p).imag(), r); 48 | } 49 | void drawLine (L l) { 50 | fprintf(stderr, "line(%d, %d, %d, %d)\n", 51 | (int)f(l.a).real(), (int)f(l.a).imag(), 52 | (int)f(l.b).real(), (int)f(l.b).imag()); 53 | } 54 | void update (P p, ld r) { 55 | left = min(left, p.real() - r); 56 | right = max(right, p.real() + r); 57 | bottom = min(bottom, p.imag() - r); 58 | top = max(top, p.imag() + r); 59 | } 60 | 61 | public: 62 | P draw(P p, int i) { 63 | if (i >= 0) points[i].push_back(p); 64 | update(p, 0); return p; 65 | } 66 | L draw(L l, int i) { 67 | if (i >= 0) lines[i].push_back(l); 68 | update(l.a, 0); update(l.b, 0); return l; 69 | } 70 | C draw(C c, int i) { 71 | if (i >= 0) circles[i].push_back(c); 72 | update(c.p, c.r); return c; 73 | } 74 | VP draw(VP p, int i) { 75 | int n = p.size(); 76 | REP(j,n) draw((L){p[j], p[(j+1)%n]}, i); 77 | return p; 78 | } 79 | 80 | Visualizer (int ax = 0, int ay = 0, int bx = 800, int by = 800, int offset = 50) : 81 | ax(ax), ay(ay), bx(bx), by(by), offset(offset), 82 | left(1e9), right(-1e9), bottom(1e9), top(-1e9) {} 83 | ~Visualizer () { 84 | center = P((left + right) / 2, (bottom + top) / 2); 85 | zoom = min((bx - ax - offset * 2) / (right - left), 86 | (by - ay - offset * 2) / (top - bottom)); 87 | for (int i = 0; i < COL; ++i) { 88 | fprintf(stderr, "c.strokeStyle = 'rgb(%d, %d, %d)';\n", r[i], g[i], b[i]); 89 | for (P p: points[i]) drawCircle(p, 2); 90 | for (L l: lines[i]) drawLine(l); 91 | for (C c: circles[i]) drawCircle(c.p, (int)(c.r * zoom)); 92 | for (VP p: polygons[i]) { 93 | int n = p.size(); 94 | REP(i,n) drawLine((L){p[i], p[(i+1)%n]}); 95 | } 96 | } 97 | } 98 | }; 99 | -------------------------------------------------------------------------------- /Math/Polynomial.cpp: -------------------------------------------------------------------------------- 1 | using Data = int; 2 | 3 | struct Polynomial { 4 | vector c; 5 | Polynomial() : c(1, 1) {;} 6 | Polynomial(int s, Data i) : c(s, i) {;} 7 | Polynomial(vector v) {c = v;} 8 | int size() const { return c.size(); } 9 | void normalize() { 10 | int s = 1; 11 | for (int i = size() - 1; i >= 0; i--) 12 | if (c[i] != 0) { s = i + 1; break; } 13 | c.resize(s); 14 | } 15 | Data operator[](int index) const { 16 | assert(index >= 0 && index < size()); 17 | return c[index]; 18 | } 19 | Data &operator[](int index) { 20 | assert(index >= 0 && index < size()); 21 | return c[index]; 22 | } 23 | Polynomial operator+(const Polynomial &rhs) const { 24 | Polynomial ret = *this; 25 | ret.c.resize(max(size(), rhs.size())); 26 | REP(i,rhs.size()) ret[i] = ret[i] + rhs[i]; 27 | ret.normalize(); 28 | return ret; 29 | } 30 | Polynomial operator-() const { 31 | Polynomial ret = *this; 32 | REP(i,ret.size()) ret[i] = -ret[i]; 33 | return ret; 34 | } 35 | Polynomial operator-(const Polynomial &rhs) const { return *this + (-rhs); } 36 | Polynomial operator*(const Polynomial &rhs) const { 37 | Polynomial ret(size() + rhs.size(), 0); 38 | REP(i,size()) REP(j,rhs.size()) ret[i+j] += c[i] * rhs[j]; 39 | ret.normalize(); 40 | return ret; 41 | } 42 | Polynomial operator/(const Polynomial &rhs) const { return divmod(rhs).first; } 43 | Polynomial operator%(const Polynomial &rhs) const { return divmod(rhs).second; } 44 | Polynomial operator+=(const Polynomial &rhs) { return *this = *this + rhs; } 45 | Polynomial operator-=(const Polynomial &rhs) { return *this = *this - rhs; } 46 | Polynomial operator*=(const Polynomial &rhs) { return *this = *this * rhs; } 47 | Polynomial operator/=(const Polynomial &rhs) { return *this = *this / rhs; } 48 | Polynomial operator%=(const Polynomial &rhs) { return *this = *this % rhs; } 49 | /* 50 | void reduce() { 51 | int g = abs(c.back()); 52 | if (g > 0) { 53 | for (int j: c) 54 | if (j != 0) g = __gcd(g, abs(j)); 55 | if (c.back() < 0) g = -g; 56 | for (int &j: c) j /= g; 57 | } 58 | } 59 | */ 60 | pair divmod(const Polynomial &rhs) const { 61 | int ls = size(), rs = rhs.size(), s = ls - rs + 1; 62 | if (s < 0) { return make_pair(Polynomial(1, 0), *this); } 63 | Polynomial div(s, 0), rest = *this; 64 | assert(rhs[rs-1] != 0); 65 | REP(i,s) { 66 | /* 67 | if (rest[ls-i-1] % rhs[rs-1] != 0) 68 | for (auto &j: rest.c) j *= rhs[rs-1]; 69 | */ 70 | Data d = rest[ls-i-1] / rhs[rs-1]; 71 | div[s - i - 1] = d; 72 | REP(j,rs) rest[ls-i-j-1] -= rhs[rs-j-1] * d; 73 | } 74 | div.normalize(); rest.normalize(); 75 | // rest.reduce(); 76 | return make_pair(div, rest); 77 | } 78 | Polynomial pow(int power) const { 79 | Polynomial base = *this; 80 | Polynomial ret; 81 | while (power > 0) { 82 | if (power & 1) ret *= base; 83 | base *= base; power >>= 1; 84 | } 85 | return ret; 86 | } 87 | Polynomial differential() const { 88 | if (c.size() == 1) return Polynomial(1, 0); 89 | Polynomial ret(c.size() - 1, 0); 90 | for (int i = 1; i < (int)c.size(); ++i) ret[i-1] = c[i] * i; 91 | return ret; 92 | } 93 | Data calc(Data x) const { 94 | Data ans = 0; 95 | for (int i = c.size() - 1; i >= 0; i--) ans *= x, ans += c[i]; 96 | return ans; 97 | } 98 | }; 99 | 100 | Polynomial PolynomialGCD(Polynomial a, Polynomial b) { 101 | if (b.size() == 1 && b[0] == 0) { a.reduce(); return a; } 102 | return PolynomialGCD(b, a % b); 103 | } 104 | -------------------------------------------------------------------------------- /Geometry/3DGeometry.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using ld = long double; 4 | using Point = valarray; 5 | 6 | const ld eps = 1e-8, inf = 1e12; 7 | 8 | Point make_point(ld x, ld y, ld z) { 9 | Point p(3); 10 | p[0] = x; p[1] = y; p[2] = z; 11 | return p; 12 | } 13 | 14 | ld dot(const Point &a, const Point &b) { 15 | return (a * b).sum(); 16 | } 17 | 18 | Point cross(const Point &a, const Point &b) { 19 | return a.cshift(+1) * b.cshift(-1) - a.cshift(-1) * b.cshift(+1); 20 | } 21 | 22 | ld norm(const Point &a) { return dot(a, a); } 23 | ld dist(const Point &a) { return sqrt(norm(a)); } 24 | 25 | // Line 26 | 27 | struct Line { Point a, b; }; 28 | 29 | bool is_in_segment(Line l, Point p) { 30 | return abs(dist(l.a - p) + dist(l.b - p) - dist(l.a - l.b)) < eps; 31 | } 32 | 33 | Point project_lp(Line l, Point p) { 34 | Point point = l.a, vec = l.b - l.a; 35 | return point + dot(p-point, vec) / norm(vec) * vec; 36 | } 37 | 38 | ld distance_lp(Line l, Point p) { 39 | return dist(p - project_lp(l, p)); 40 | } 41 | 42 | ld distance_sp(Line l, Point p) { 43 | Point proj = project_lp(l, p); 44 | if (dist(l.a - proj) + dist(l.b - proj) < dist(l.b - l.a) + eps) 45 | return dist(p - proj); 46 | else 47 | return min(dist(p - l.a), dist(p - l.b)); 48 | } 49 | 50 | // Verified : AOJ2081 51 | ld distance_ll (Line l, Line m) { 52 | Point v = cross(l.b - l.a, m.b - m.a), p = m.a - l.a; 53 | if (dist(v) < eps) return distance_lp(l, m.a); 54 | return abs(dot(v, p)) / dist(v); 55 | } 56 | 57 | // Plane 58 | 59 | struct Plane { Point a, b, c; }; 60 | 61 | bool is_in_plane(Plane pl, Point p) { 62 | pl.a -= p; pl.b -= p; pl.c -= p; 63 | return abs(dot(pl.a, cross(pl.b, pl.c))) < eps; 64 | } 65 | 66 | bool parallel_pll(Plane pl, Line l) { 67 | Point p = (l.a - l.b) + pl.a; 68 | return is_in_plane(pl, p); 69 | } 70 | 71 | bool is_in_triangle(Plane t, Point p) { 72 | t.a -= p; t.b -= p; t.c -= p; 73 | ld a = dist(cross(t.a, t.b)); 74 | ld b = dist(cross(t.b, t.c)); 75 | ld c = dist(cross(t.c, t.a)); 76 | return abs(a + b + c - dist(cross(t.c - t.a, t.b - t.a))) < eps; 77 | } 78 | 79 | bool is_cross_pll(Plane pl, Line l) { 80 | return !parallel_pll(pl, l) || is_in_plane(pl, l.a); 81 | } 82 | 83 | Point intersect_pll(Plane pl, Line l) { 84 | assert(!parallel_pll(pl, l)); 85 | Point vec = cross(pl.b - pl.a, pl.c - pl.a); 86 | ld s = dot(vec, l.a - pl.a), t = dot(vec, l.b - pl.a); 87 | return (l.b * s - l.a * t) / (s - t); 88 | } 89 | 90 | // Verified : AOJ0115 91 | bool is_cross_tl(Plane t, Line l) { 92 | assert(!parallel_pll(t, l)); // use distance_ll 93 | Point q = intersect_pll(t, l); 94 | return is_in_triangle(t, q); 95 | } 96 | 97 | ld distance_pll(Plane pl, Line l) { 98 | if (is_cross_pll(pl, l)) return 0.0; 99 | return min(distance_ll({pl.a, pl.b}, l), distance_ll({pl.b, pl.c}, l)); 100 | } 101 | 102 | ld distance_tl(Plane t, Line l) { 103 | if (is_cross_tl(t, l)) return 0; 104 | ld res = distance_ll((Line){t.a, t.b}, l); 105 | res = min(res, distance_ll((Line){t.b, t.c}, l)); 106 | res = min(res, distance_ll((Line){t.c, t.a}, l)); 107 | return res; 108 | } 109 | 110 | // new Plane 111 | 112 | struct Plane { Point p, v; }; 113 | 114 | // Verified : AOJ2562 115 | 116 | const Point rnd = make_point(43.123984, 50.230909, 33.929898); 117 | 118 | Line intersect_plpl (Plane a, Plane b) { 119 | Point p = cross(rnd, b.v), q = cross(rnd, a.v); 120 | ld r1 = dot(a.p, a.v) / dot(p, a.v); 121 | p = p * make_point(r1, r1, r1); 122 | ld r2 = dot(b.p, b.v) / dot(q, b.v); 123 | q = q * make_point(r2, r2, r2); 124 | Point po = p + q; 125 | return (Line){po, po + cross(a.v, b.v)}; 126 | } 127 | 128 | // Sphere 129 | 130 | // Verified : AOJ1289 131 | 132 | struct Sphere { Point p; ld r; }; 133 | 134 | vector intersect_lo(Sphere s, Line l) { 135 | vector res; 136 | Point p = project_lp(l, s.p); 137 | ld d = dist(p - s.p); 138 | if (d < s.r + eps){ 139 | ld len = (d > s.r) ? 0.0 : sqrt(s.r * s.r - d * d); 140 | Point nor = (l.a - l.b) / dist(l.a - l.b); 141 | res.push_back(p + len * nor); 142 | res.push_back(p - len * nor); 143 | } 144 | return res; 145 | } 146 | -------------------------------------------------------------------------------- /Structure/SegmentTreeLazyUniversal.cpp: -------------------------------------------------------------------------------- 1 | // Range Add - Range Min (Verified: SPOJ61) 2 | struct Data { 3 | int num; 4 | Data() : num(0) {;} 5 | Data(int n) : num(n) {;} 6 | }; 7 | 8 | const Data identity = Data(1000000000); 9 | 10 | inline Data Merge(Data left, Data right) { return Data(min(left.num, right.num)); } 11 | inline Data Set(Data lazy, Data val) { return Data(lazy.num + val.num); } 12 | inline Data Eval(Data data, Data lazy, int num) { return Data(data.num + lazy.num); } 13 | 14 | // Range Add - Range Sum (Unverified) 15 | struct Data { 16 | int num; 17 | Data() : num(0) {;} 18 | Data(int n) : num(n) {;} 19 | }; 20 | 21 | const Data identity = Data(0); 22 | 23 | inline Data Merge(Data left, Data right) { return Data(left.num + right.num); } 24 | inline Data Set(Data lazy, Data val) { return Data(lazy.num + val.num); } 25 | inline Data Eval(Data data, Data lazy, int num) { return Data(data.num + lazy.num * num); } 26 | 27 | // Range Set - Range Min (Unverified) 28 | struct Data { 29 | int num; 30 | Data() : num(1000000000) {;} 31 | Data(int n) : num(n) {;} 32 | }; 33 | 34 | const Data identity = Data(1000000000); 35 | 36 | inline Data Merge(Data left, Data right) { return Data(min(left.num, right.num)); } 37 | inline Data Set(Data lazy, Data val) { return val; } 38 | inline Data Eval(Data data, Data lazy, int num) { return lazy; } 39 | 40 | // Range Set - Range Sum (Unverified) 41 | struct Data { 42 | int num; 43 | Data() : num(0) {;} 44 | Data(int n) : num(n) {;} 45 | }; 46 | 47 | const Data identity = Data(0); 48 | 49 | inline Data Merge(Data left, Data right) { return Data(left.num + right.num); } 50 | inline Data Set(Data lazy, Data val) { return val; } 51 | inline Data Eval(Data data, Data lazy, int num) { return Data(lazy.num * num); } 52 | 53 | // Range Add, Set - Range Sum (Unverified) 54 | struct Data { 55 | int type; // 0:data, 1:add, 2:set 56 | int num; 57 | Data() : type(0), num(0) {;} 58 | Data(int t, int n) : type(t), num(n) {;} 59 | }; 60 | 61 | const Data identity = Data(0, 0); 62 | 63 | inline Data Merge(Data left, Data right) { return Data(0, left.num + right.num); } 64 | inline Data Set(Data lazy, Data val) { 65 | if (val.type == 2) return val; 66 | lazy.num += val.num; return lazy; 67 | } 68 | inline Data Eval(Data data, Data lazy, int num) { 69 | if (lazy.type == 2) return Data(0, lazy.num * num); 70 | return Data(0, data.num + lazy.num * num); 71 | } 72 | 73 | class SegmentTreeLazy { 74 | int n; 75 | vector data, lazy; 76 | vector flag; 77 | void lazyset(int node, Data val) { 78 | if (flag[node]) lazy[node] = Set(lazy[node], val); 79 | else lazy[node] = val; 80 | flag[node] = true; 81 | } 82 | void evaluate(int node, int num) { 83 | if (!flag[node]) return; 84 | Data val = lazy[node]; 85 | data[node] = Eval(data[node], val, num); flag[node] = false; 86 | if (node < n) return; 87 | lazyset((node-n)*2+0, val); lazyset((node-n)*2+1, val); 88 | } 89 | void update_sub(int fr, int to, int node, int la, int ra, Data val) { 90 | if (ra <= fr || to <= la) { evaluate(node, ra - la); return; } 91 | if (fr <= la && ra <= to) { 92 | lazyset(node, val); evaluate(node, ra - la); return; 93 | } 94 | evaluate(node, ra - la); 95 | int lpos = (node-n)*2+0, rpos = (node-n)*2+1; 96 | update_sub(fr, to, lpos, la, (la+ra)/2, val); 97 | update_sub(fr, to, rpos, (la+ra)/2, ra, val); 98 | data[node] = Merge(data[lpos], data[rpos]); 99 | } 100 | Data query_sub(int fr, int to, int node, int la, int ra) { 101 | if (ra<=fr || to<=la) return identity; 102 | if (fr<=la && ra<=to) { evaluate(node, ra - la); return data[node]; } 103 | evaluate(node, ra - la); 104 | Data l = query_sub(fr, to, (node-n)*2+0, la, (la+ra)/2); 105 | Data r = query_sub(fr, to, (node-n)*2+1, (la+ra)/2, ra); 106 | return Merge(l, r); 107 | } 108 | public: 109 | SegmentTreeLazy(int N) { 110 | for (n = 1; n < N; n *= 2); 111 | data.resize(n * 2), lazy.resize(n * 2); 112 | flag.assign(n * 2, false); 113 | REP(i,n*2) flag[i] = false; 114 | } 115 | void update(int fr, int to, Data val) { update_sub(fr, to, 2*n-2, 0, n, val); } 116 | Data query(int fr, int to) { return query_sub(fr, to, 2*n-2, 0, n); } 117 | }; 118 | -------------------------------------------------------------------------------- /Geometry/Intersect.cpp: -------------------------------------------------------------------------------- 1 | // Intersect 2 | 3 | bool isis_ll(L l, L m) { 4 | return abs(cross(l.b - l.a, m.b - m.a)) > eps; 5 | } 6 | 7 | bool isis_ls(L l, L s) { 8 | ld a = cross(l.b - l.a, s.a - l.a); 9 | ld b = cross(l.b - l.a, s.b - l.a); 10 | return (a * b < eps); 11 | } 12 | 13 | bool isis_lp(L l, P p) { 14 | return abs(cross(l.b - p, l.a - p)) < eps; 15 | } 16 | 17 | bool isis_ss(L s, L t) { 18 | return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && 19 | ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0; 20 | } 21 | 22 | bool isis_ss(L s, L t) { 23 | if (abs(cross(s.b - s.a, t.b - t.a)) < eps) return false; 24 | P p = is_ll(s, t); 25 | return isis_sp(s, p) && isis_sp(t, p); 26 | } 27 | 28 | bool isis_sp(L s, P p) { 29 | return abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps; 30 | } 31 | 32 | P proj(L l, P p) { 33 | ld t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b); 34 | return l.a + t * (l.a - l.b); 35 | } 36 | 37 | P mirror(L l, P p) { 38 | return (ld)2 * proj(l, p) - p; 39 | } 40 | 41 | P is_ll(L s, L t){ 42 | P sv = s.b - s.a, tv = t.b - t.a; 43 | return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv); 44 | } 45 | 46 | ld dist_lp(L l, P p) { 47 | return abs(p - proj(l, p)); 48 | } 49 | 50 | ld dist_ll(L l, L m) { 51 | return isis_ll(l, m) ? 0 : dist_lp(l, m.a); 52 | } 53 | 54 | ld dist_ls(L l, L s) { 55 | if (isis_ls(l, s)) return 0; 56 | return min(dist_lp(l, s.a), dist_lp(l, s.b)); 57 | } 58 | 59 | ld dist_sp(L s, P p) { 60 | P r = proj(s, p); 61 | if (isis_sp(s, r)) return abs(r - p); 62 | return min(abs(s.a - p), abs(s.b - p)); 63 | } 64 | 65 | ld dist_ss(L s, L t) { 66 | if (isis_ss(s, t)) return 0; 67 | ld a = min(dist_sp(s, t.a), dist_sp(t, s.a)); 68 | ld b = min(dist_sp(s, t.b), dist_sp(t, s.b)); 69 | return min(a, b); 70 | } 71 | 72 | VP is_cc(C c1, C c2){ 73 | VP res; 74 | ld d = abs(c1.p - c2.p); 75 | ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d); 76 | ld dfr = c1.r * c1.r - rc * rc; 77 | if (abs(dfr) < eps) dfr = 0.0; 78 | else if (dfr < 0.0) return res; // no intersection 79 | ld rs = sqrt(dfr); 80 | P diff = (c2.p-c1.p)/d; 81 | res.push_back(c1.p + diff * P(rc, rs)); 82 | if (dfr != 0.0) res.push_back(c1.p + diff * P(rc, -rs)); 83 | return res; 84 | } 85 | 86 | bool isis_vc(vector vc) { 87 | VP crs; 88 | int n=vc.size(); 89 | REP(i,n)REP(j,i) 90 | for(P p:is_cc(vc[i],vc[j])) 91 | crs.push_back(p); 92 | REP(i,n) 93 | crs.push_back(vc[i].p); 94 | for(P p:crs){ 95 | bool valid=true; 96 | REP(i,n) 97 | if(abs(p-vc[i].p)>vc[i].r+eps) 98 | valid=false; 99 | if(valid) return true; 100 | } 101 | return false; 102 | } 103 | 104 | VP is_lc(C c, L l){ 105 | VP res; 106 | ld d = dist_lp(l, c.p); 107 | if (d < c.r + eps){ 108 | ld len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d); //safety; 109 | P nor = (l.a - l.b) / abs(l.a - l.b); 110 | res.push_back(proj(l, c.p) + len * nor); 111 | res.push_back(proj(l, c.p) - len * nor); 112 | } 113 | return res; 114 | } 115 | 116 | VP is_sc(C c, L l){ 117 | VP v = is_lc(c, l), res; 118 | for (P p : v) 119 | if (isis_sp(l, p)) res.push_back(p); 120 | return res; 121 | } 122 | 123 | vector tangent_cp(C c, P p) { 124 | vector ret; 125 | P v = c.p - p; 126 | ld d = abs(v); 127 | ld l = sqrt(norm(v) - c.r * c.r); 128 | if (isnan(l)) { return ret; } 129 | P v1 = v * P(l / d, c.r / d); 130 | P v2 = v * P(l / d, -c.r / d); 131 | ret.push_back((L){p, p + v1}); 132 | if (l < eps) return ret; 133 | ret.push_back((L){p, p + v2}); 134 | return ret; 135 | } 136 | 137 | vector tangent_cc(C c1, C c2) { 138 | vector ret; 139 | if (abs(c1.p - c2.p) - (c1.r + c2.r) > -eps) { 140 | P center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r); 141 | ret = tangent_cp(c1, center); 142 | } 143 | if (abs(c1.r - c2.r) > eps) { 144 | P out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r); 145 | vector nret = tangent_cp(c1, out); 146 | ret.insert(ret.end(), ALL(nret)); 147 | } 148 | else { 149 | P v = c2.p - c1.p; 150 | v /= abs(v); 151 | P q1 = c1.p + v * P(0, 1) * c1.r; 152 | P q2 = c1.p + v * P(0, -1) * c1.r; 153 | ret.push_back((L){q1, q1 + v}); 154 | ret.push_back((L){q2, q2 + v}); 155 | } 156 | return ret; 157 | } 158 | -------------------------------------------------------------------------------- /Graph/ShortestPath.cpp: -------------------------------------------------------------------------------- 1 | using Weight = int; 2 | Weight INF = 1000000000; 3 | struct Edge{ 4 | int src, dest; Weight weight; 5 | bool operator < (const Edge &rhs) const {return weight > rhs.weight;} 6 | }; 7 | 8 | using Edges = vector; 9 | using Graph = vector; 10 | using Array = vector; 11 | using Matrix = vector; 12 | 13 | void add_edge(Graph &g, int src, int dest, Weight weight) { 14 | g[src].push_back((Edge){src, dest, weight}); 15 | } 16 | 17 | // Dijkstra (Verified: AOJ2005) 18 | void dijkstra(Graph &g, Array &d, int s) { 19 | d.assign(g.size(), INF); 20 | d[s] = 0; 21 | using P = pair; 22 | priority_queue, greater

> que; 23 | que.push(P(0, s)); 24 | while (!que.empty()) { 25 | Weight dist = que.top().first; 26 | int v = que.top().second; 27 | que.pop(); 28 | if (d[v] < dist) continue; 29 | REP(i, g[v].size()) { 30 | Edge e = g[v][i]; 31 | if (d[e.dest] > d[v] + e.weight) { 32 | d[e.dest] = d[v] + e.weight; 33 | que.push(P(d[e.dest], e.dest)); 34 | } 35 | } 36 | } 37 | } 38 | 39 | // Dijkstra (build path version) 40 | vector dijkstra(Graph &g, int s, vector &prev) { 41 | vector dist(g.size(), INF); dist[s]=0; 42 | prev.assign(g.size(), -1); 43 | priority_queue q; 44 | for(q.push(Edge{-1, s, 0}); !q.empty();) { 45 | Edge e = q.top(); q.pop(); 46 | if (prev[e.dest] != -1) continue; 47 | prev[e.dest] = e.src; 48 | for(Edge f : g[e.dest]) { 49 | if(dist[f.dest] > e.weight + f.weight) { 50 | dist[f.dest] = e.weight + f.weight; 51 | q.push((Edge){f.src, f.dest, e.weight + f.weight}); 52 | } 53 | } 54 | } 55 | return dist; 56 | } 57 | 58 | vector buildPath(const vector &prev, int t) { 59 | vector path; 60 | for(int u=t;u>=0;u=prev[u]) path.push_back(u); 61 | reverse(path.begin(), path.end()); 62 | return path; 63 | } 64 | 65 | // BellmanFord (Verified: AOJ2005) 66 | void bellman_ford(const Edges &es, Array &d, int s) { 67 | fill(ALL(d), INF); 68 | d[s] = 0; 69 | REP(i, es.size()) { 70 | Edge e = es[i]; 71 | if (d[e.dest] > d[e.src] + e.weight) { 72 | d[e.dest] = d[e.src] + e.weight; 73 | i = -1; 74 | } 75 | } 76 | } 77 | 78 | // BellmanFord (Negative Cycle) 79 | bool bellman_ford(const Edges &es, Array &d, int s) { 80 | fill(ALL(d), INF); d[s] = 0; 81 | REP(i, d.size()) { 82 | bool updated = false; 83 | for (Edge e : es) { 84 | if (d[e.src] < INF && d[e.dest] > d[e.src] + e.weight) { 85 | d[e.dest] = d[e.src] + e.weight; 86 | if (i == d.size() - 1) return false; 87 | updated = true; 88 | } 89 | } 90 | if (!updated) return true; 91 | } 92 | return true; 93 | } 94 | 95 | // WarshallFloyd 96 | void warshall_floyd(Matrix &g) { 97 | int n = g.size(); 98 | REP(k,n) REP(i,n) REP(j,n) 99 | g[i][j] = min(g[i][j], g[i][k] + g[k][j]); 100 | } 101 | 102 | // Shortest Path Faster Algorithm 103 | bool SPFA(const Graph &g, Array &d, int s) { 104 | const int n = g.size(); 105 | d.assign(n, INF); d[s] = 0; 106 | vector updated(n, 0); 107 | vector inque(n, false); 108 | queue que; 109 | que.push(s); 110 | while (!que.empty()) { 111 | int from = que.front(); 112 | que.pop(); 113 | inque[from] = false; 114 | updated[from]++; 115 | if (updated[from] == n) return false; // negative cycle 116 | for (Edge e : g[from]) { 117 | int to = e.dest; 118 | Weight cost = d[from] + e.weight; 119 | if (cost < d[to]) { 120 | d[to] = cost; 121 | if (!inque[to]) { 122 | que.push(to); 123 | inque[to] = true; 124 | } 125 | } 126 | } 127 | } 128 | return true; 129 | } 130 | 131 | // The costs of edges must be 0 or 1 (Verified: TCO 2014 Round 2C Medium) 132 | void bfs01(Graph &g, vector &d, int s) { 133 | d.assign(g.size(), INF); 134 | d[s] = 0; 135 | using P = pair; 136 | deque

que; 137 | que.push_back(P(0, s)); 138 | while (!que.empty()) { 139 | P top = que.front(); que.pop_front(); 140 | Weight dist = top.first; int v = top.second; 141 | if (d[v] < dist) continue; 142 | REP(i, g[v].size()) { 143 | Edge e = g[v][i]; 144 | if (d[e.dest] > d[v] + e.weight) { 145 | d[e.dest] = d[v] + e.weight; 146 | if (e.weight) que.push_back(P(d[e.dest], e.dest)); 147 | else que.push_front(P(d[e.dest], e.dest)); 148 | } 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /Others/Subsets.cpp: -------------------------------------------------------------------------------- 1 | template 2 | vector sum_over_supersets(const vector& v, const size_t N, BinaryOperation op) { 3 | auto ans = v; 4 | for (size_t i = 0; i < N; ++i) { 5 | for (size_t T = 0; T < (size_t(1) << N); ++T) { 6 | if (((T >> i) & 1) == 0) { 7 | ans[T] = op(ans[T], ans[T | (1 << i)]); 8 | } 9 | } 10 | } 11 | return ans; 12 | } 13 | 14 | template 15 | vector sum_over_subsets(const vector& v, const size_t N, BinaryOperation op) { 16 | auto ans = v; 17 | for (size_t i = 0; i < N; ++i) { 18 | for (size_t T = 0; T < (size_t(1) << N); ++T) { 19 | if (((T >> i) & 1) == 1) { 20 | ans[T] = op(ans[T], ans[T ^ (1 << i)]); 21 | } 22 | } 23 | } 24 | return ans; 25 | } 26 | 27 | template 28 | vector inverse_sum_over_supersets(const vector& v, const size_t N, BinaryOperation op) { 29 | return sum_over_supersets(v, N, [&] (const auto& lhs, const auto &rhs) { 30 | return op(lhs, -rhs); 31 | }); 32 | } 33 | 34 | template 35 | vector inverse_sum_over_subsets(const vector& v, const size_t N, BinaryOperation op) { 36 | return sum_over_subsets(v, N, [&] (const auto& lhs, const auto &rhs) { 37 | return op(lhs, -rhs); 38 | }); 39 | } 40 | 41 | size_t pop_count(size_t x) { 42 | // GCC builtins: 43 | // return __builtin_popcount(x); 44 | 45 | // Intel intrinsics (need to include x86intrin.h) 46 | // return _mm_popcnt_u64(x); 47 | 48 | // C++20 standard 49 | // retrun std::popcount(x); 50 | 51 | // Generic implementation for 64bit integer 52 | x = ((x >> 1) & 0x5555'5555'5555'5555) + (x & 0x5555'5555'5555'5555); 53 | x = ((x >> 2) & 0x3333'3333'3333'3333) + (x & 0x3333'3333'3333'3333); 54 | x = ((x >> 4) & 0x0f0f'0f0f'0f0f'0f0f) + (x & 0x0f0f'0f0f'0f0f'0f0f); 55 | x = ((x >> 8) & 0x00ff'00ff'00ff'00ff) + (x & 0x00ff'00ff'00ff'00ff); 56 | x = ((x >> 16) & 0x0000'ffff'0000'ffff) + (x & 0x0000'ffff'0000'ffff); 57 | x = ((x >> 32) & 0x0000'0000'ffff'ffff) + (x & 0x0000'0000'ffff'ffff); 58 | return x; 59 | } 60 | 61 | template 62 | vector> ranked_sum_over_subsets(const vector& v, const size_t N, BinaryOperation op) { 63 | vector ans(N+1, vector(1<> i) & 1) == 1) { 71 | ans[k][T] = op(ans[k][T], ans[k][T ^ (1 << i)]); 72 | } 73 | } 74 | } 75 | } 76 | return ans; 77 | } 78 | 79 | template 80 | vector inverse_ranked_sum_over_subsets(const vector>& v, const size_t N, BinaryOperation op) { 81 | auto tmp = v; 82 | for (size_t k = 0; k <= N; ++k) { 83 | for (size_t i = 0; i < N; ++i) { 84 | for (size_t T = 0; T < (size_t(1) << N); ++T) { 85 | if (((T >> i) & 1) == 1) { 86 | tmp[k][T] = op(tmp[k][T], -tmp[k][T ^ (1 << i)]); 87 | } 88 | } 89 | } 90 | } 91 | vector ans(1 << N); 92 | for (size_t i = 0; i < (size_t(1) << N); ++i) { 93 | ans[i] = tmp[pop_count(i)][i]; 94 | } 95 | return ans; 96 | } 97 | 98 | template 99 | vector subset_conv(const vector& f, const vector& g, const size_t N, RingAdd op_add, RingMul op_mul) { 100 | auto f_hat = ranked_sum_over_subsets(f, N, op_add); 101 | auto g_hat = ranked_sum_over_subsets(g, N, op_add); 102 | vector tmp(N+1, vector(1 << N)); 103 | for (size_t k = 0; k <= N; ++k) { 104 | for (size_t i = 0; i < (size_t(1) << N); ++i) { 105 | for (size_t j = 0; j <= k; ++j) { 106 | tmp[k][i] = op_add(tmp[k][i], op_mul(f_hat[j][i], g_hat[k-j][i])); 107 | } 108 | } 109 | } 110 | return inverse_ranked_sum_over_subsets(tmp, N, op_add); 111 | } 112 | 113 | // test code 114 | // 115 | //#include 116 | //#include 117 | //#include 118 | // 119 | //using namespace std; 120 | // 121 | //int main() { 122 | // size_t N = 18; 123 | // size_t len = 1 << N; 124 | // random_device rd; 125 | // mt19937 mt(rd()); 126 | // uniform_int_distribution<> dis(-1024, 1023); 127 | // vector u(len); 128 | // vector v(len); 129 | // for(size_t i = 0; i < len; ++i) { 130 | // u[i] = dis(mt); 131 | // v[i] = dis(mt); 132 | // } 133 | // auto sosup = sum_over_supersets(v, N, std::plus<>()); 134 | // auto sosub = sum_over_subsets(v, N, std::plus<>()); 135 | // auto inv_sup = inverse_sum_over_supersets(sosup, N, std::plus<>()); 136 | // cout << (inv_sup == v) << endl; 137 | // auto inv_sub = inverse_sum_over_subsets(sosub, N, std::plus<>()); 138 | // cout << (inv_sub == v) << endl; 139 | // auto conv_uv = subset_conv(u, v, N, std::plus<>(), std::multiplies<>()); 140 | // bool ok = true; 141 | // //for (size_t i = 0; i < len; ++i) { 142 | // // int64_t sum = 0; 143 | // // for (int U = (1 << N) - 1; U >= 0; --U) { 144 | // // U &= i; 145 | // // sum += u[U] * v[i^U]; 146 | // // } 147 | // // if (sum != conv_uv[i]) ok = false; 148 | // //} 149 | // cout << ok << endl; 150 | // return 0; 151 | //} 152 | -------------------------------------------------------------------------------- /Structure/check/checker.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | #define REP(i,n) for(int i = 0; i < (int)(n); ++i) 6 | #include "stlu_check1.cpp" 7 | 8 | class SegmentTreeLazy { 9 | static const int MAX_DEPTH = 17; 10 | static const int STsize = 1 << MAX_DEPTH; 11 | Data data[STsize], lazy[STsize]; 12 | bool flag[STsize]; int n; 13 | void lazyset(int node, Data val) { 14 | if (flag[node]) lazy[node] = Set(lazy[node], val); 15 | else lazy[node] = val; 16 | flag[node] = true; 17 | } 18 | void evaluate(int node, int num) { 19 | if (!flag[node]) return; 20 | Data val = lazy[node]; 21 | data[node] = Eval(data[node], val, num); flag[node] = false; 22 | if (node < n) return; 23 | lazyset((node-n)*2+0, val); lazyset((node-n)*2+1, val); 24 | } 25 | void update_sub(int fr, int to, int node, int la, int ra, Data val) { 26 | if (ra <= fr || to <= la) { evaluate(node, ra - la); return; } 27 | if (fr <= la && ra <= to) { 28 | lazyset(node, val); evaluate(node, ra - la); return; 29 | } 30 | evaluate(node, ra - la); 31 | int lpos = (node-n)*2+0, rpos = (node-n)*2+1; 32 | update_sub(fr, to, lpos, la, (la+ra)/2, val); 33 | update_sub(fr, to, rpos, (la+ra)/2, ra, val); 34 | data[node] = Merge(data[lpos], data[rpos]); 35 | } 36 | Data query_sub(int fr, int to, int node, int la, int ra) { 37 | if (ra<=fr || to<=la) return identity; 38 | if (fr<=la && ra<=to) { evaluate(node, ra - la); return data[node]; } 39 | evaluate(node, ra - la); 40 | Data l = query_sub(fr, to, (node-n)*2+0, la, (la+ra)/2); 41 | Data r = query_sub(fr, to, (node-n)*2+1, (la+ra)/2, ra); 42 | return Merge(l, r); 43 | } 44 | public: 45 | SegmentTreeLazy(void) : n(STsize / 2) { REP(i,STsize) flag[i] = false; } 46 | void update(int fr, int to, Data val) { update_sub(fr, to, 2*n-2, 0, n, val); } 47 | Data query(int fr, int to) { return query_sub(fr, to, 2*n-2, 0, n); } 48 | }; 49 | 50 | class Naive { 51 | static const int N = 1024; 52 | Data data[N]; 53 | public: 54 | void update(int fr, int to, Data val) { 55 | for (int i = fr; i < to; ++i) 56 | data[i] = Set(data[i], val); 57 | } 58 | Data query(int fr, int to) { 59 | Data res = identity; 60 | for (int i = fr; i < to; ++i) 61 | res = Merge(res, data[i]); 62 | return res; 63 | } 64 | }; 65 | 66 | /* (range set, add range sum) 67 | int main() { 68 | Naive naive; 69 | SegmentTreeLazy seg; 70 | int n,m,l; 71 | cin>>n>>m>>l; 72 | cout << "Phase 1: N <= 1024, Compare with naive structure" << endl; 73 | REP(i,n) { 74 | int c = rand() % 3; 75 | int fr = rand() % 1024; 76 | int to = rand() % (1024 - fr) + fr; 77 | if (c != 0) { 78 | int v; 79 | v = rand() % 1000 - 500; 80 | naive.update(fr, to, Data(c, v)); 81 | seg.update(fr, to, Data(c, v)); 82 | } else { 83 | Data n = naive.query(fr, to); 84 | Data s = seg.query(fr, to); 85 | if (n.num != s.num) { 86 | cout << "bug" << endl; 87 | cout << fr << ' ' << to << endl; 88 | cout << i << endl; 89 | cout << n.num << ' ' << s.num << endl; 90 | } 91 | } 92 | } 93 | cout << "Phase 2: N <= 60000, Check time" << endl; 94 | SegmentTreeLazy seg2; 95 | REP(i,m) { 96 | int c = rand() % 3; 97 | int fr = rand() % 60000; 98 | int to = rand() % (60000- fr) + fr; 99 | Data s; 100 | if (c != 0) { 101 | int v; 102 | v = rand() % 1000 - 500; 103 | seg2.update(fr, to, Data(c, v)); 104 | } else { 105 | s = Merge(s, seg2.query(fr, to)); 106 | } 107 | } 108 | cout << "Phase 3: N <= 10, Check corner cases" << endl; 109 | SegmentTreeLazy seg3; 110 | Naive naive3; 111 | REP(i,l) { 112 | int c = rand() % 3; 113 | int fr = rand() % 1024; 114 | int to = rand() % (1024 - fr) + fr; 115 | if (c != 0) { 116 | int v; 117 | v = rand() % 1000 - 500; 118 | naive3.update(fr, to, Data(c, v)); 119 | seg3.update(fr, to, Data(c, v)); 120 | } else { 121 | Data n = naive3.query(fr, to); 122 | Data s = seg3.query(fr, to); 123 | if (n.num != s.num) { 124 | cout << "bug" << endl; 125 | cout << fr << ' ' << to << endl; 126 | cout << i << endl; 127 | cout << n.num << ' ' << s.num << endl; 128 | } 129 | } 130 | } 131 | return 0; 132 | } 133 | */ 134 | 135 | int main() { 136 | Naive naive; 137 | SegmentTreeLazy seg; 138 | int n,m,l; 139 | cin>>n>>m>>l; 140 | cout << "Phase 1: N <= 1024, Compare with naive structure" << endl; 141 | REP(i,n) { 142 | int c = rand() % 2; 143 | int fr = rand() % 1024; 144 | int to = rand() % (1024 - fr) + fr; 145 | if (c != 0) { 146 | int v; 147 | v = rand() % 1000 - 500; 148 | naive.update(fr, to, Data(v)); 149 | seg.update(fr, to, Data(v)); 150 | } else { 151 | Data n = naive.query(fr, to); 152 | Data s = seg.query(fr, to); 153 | if (n.num != s.num) { 154 | cout << "bug" << endl; 155 | cout << fr << ' ' << to << endl; 156 | cout << i << endl; 157 | cout << n.num << ' ' << s.num << endl; 158 | } 159 | } 160 | } 161 | cout << "Phase 2: N <= 60000, Check time" << endl; 162 | SegmentTreeLazy seg2; 163 | REP(i,m) { 164 | int c = rand() % 2; 165 | int fr = rand() % 60000; 166 | int to = rand() % (60000- fr) + fr; 167 | Data s; 168 | if (c != 0) { 169 | int v; 170 | v = rand() % 1000 - 500; 171 | seg2.update(fr, to, Data(v)); 172 | } else { 173 | s = Merge(s, seg2.query(fr, to)); 174 | } 175 | } 176 | cout << "Phase 3: N <= 10, Check corner cases" << endl; 177 | SegmentTreeLazy seg3; 178 | Naive naive3; 179 | REP(i,l) { 180 | int c = rand() % 2; 181 | int fr = rand() % 1024; 182 | int to = rand() % (1024 - fr) + fr; 183 | if (c != 0) { 184 | int v; 185 | v = rand() % 1000 - 500; 186 | naive3.update(fr, to, Data(v)); 187 | seg3.update(fr, to, Data(v)); 188 | } else { 189 | Data n = naive3.query(fr, to); 190 | Data s = seg3.query(fr, to); 191 | if (n.num != s.num) { 192 | cout << "bug" << endl; 193 | cout << fr << ' ' << to << endl; 194 | cout << i << endl; 195 | cout << n.num << ' ' << s.num << endl; 196 | } 197 | } 198 | } 199 | return 0; 200 | } 201 | --------------------------------------------------------------------------------