├── AdHoc ├── Bit Hacks.cpp ├── FastIO.cpp ├── Gray Code.cpp ├── Infinite Grid.cpp ├── Josephus Problem.cpp ├── Knight Distance.cpp ├── RandomShuffle.cpp ├── U128.cpp └── __int128.cpp ├── DP ├── DP Optimization │ ├── Alien Trick.cpp │ ├── CHT (Dynamic).cpp │ ├── CHT (Offline).cpp │ ├── Divide & Conquer Optimization.cpp │ ├── Knuth Optimization.cpp │ ├── Li-Chao Segment Tree.cpp │ ├── Li-Chao Tree (Sparse).cpp │ └── SOS DP.cpp ├── Sequence DP.cpp └── Special DP │ ├── LCS (Faster).cpp │ └── SteinerTree.cpp ├── DS ├── BIT │ ├── BIT (1D).cpp │ ├── BIT (2D - Point).cpp │ ├── BIT (2D - Range).cpp │ └── BIT (3D).cpp ├── Closest Pair.cpp ├── HashTable.cpp ├── KD Tree.cpp ├── MO │ ├── MO (Basic).cpp │ ├── MO on Tree.cpp │ └── MOs algo with updates.cpp ├── OrderedSet.cpp ├── Parallel Binary Search.cpp ├── Segment Tree │ ├── MergeSortTree.cpp │ ├── SegTreeBeats.cpp │ ├── Segment Tree (2D).cpp │ ├── Segment Tree (Iterative).cpp │ ├── Segment Tree (Persistent).cpp │ ├── Segment Tree (Recursive).cpp │ ├── Segment Tree (Sparse).cpp │ └── Wavelet Tree.cpp ├── Sliding RMQ.cpp ├── SparseTable │ ├── SparseTable (1D).cpp │ ├── SparseTable (Rectangle Query).cpp │ └── SparseTable (Square Query).cpp ├── Treap │ ├── Treap (Implicit).cpp │ └── Treap (Persistent).cpp └── Trie │ ├── Trie (Basic).cpp │ └── Trie (Persistent).cpp ├── Debug.cpp ├── Game Theory ├── Green Hackenbush.cpp └── Red-Blue Hackenbush.cpp ├── Geometry ├── 2D Geo.cpp ├── 3D Geo.cpp ├── Area of Union Of CIrcles.cpp ├── Integer Tricks.cpp ├── IntegerGeo.cpp ├── Radial Sweep.cpp └── RotationMatrix.cpp ├── Graph ├── Connectivity │ ├── ArticulationBridge.cpp │ ├── ArticulationPoint.cpp │ ├── Block-CutVertexTree.cpp │ ├── LinkCutTree(rooted).cpp │ └── LinkCutTree.cpp ├── Flow │ ├── Dinic.cpp │ ├── FasterMaxflowButWeird.cpp │ ├── GlobalMinCut.cpp │ ├── Gomuri-Hu Tree.cpp │ ├── Kth Minimum Cut.cpp │ ├── MinCostMaxFlow.cpp │ ├── MinimumCostCirculation.cpp │ └── ___FlowNotes.cpp ├── Matching │ ├── Bipartite Matching (Hopcroft Karp).cpp │ ├── Bipartite Matching(Kuhn).cpp │ ├── General Matching (Edmonds Blossom ).cpp │ ├── StableMarriage.cpp │ ├── Weighted Bipartite Matching(Hungarian).cpp │ ├── Weighted Bipartite Matching2(Hungarian).cpp │ └── Weighted General Matching.cpp ├── MinimumSpanningTree │ ├── DMST.cpp │ ├── DMSTwithSolution.cpp │ ├── ManhattonMST.cpp │ └── PrimsBorukuvaMST.cpp ├── Miscellaneous │ ├── ChromaticNumber.cpp │ ├── CycleEnumeration.cpp │ ├── EdgeColoring.cpp │ ├── EulerWalk.cpp │ ├── MatrixTreeTheorem.cpp │ ├── MaxClique.cpp │ ├── MinimumMeanCycle.cpp │ └── TwoSat.cpp ├── Tree │ ├── Centroid Decomposition on Edge.cpp │ ├── Centroid Decompostion.cpp │ ├── CompressTree.cpp │ ├── DSU.cpp │ ├── DominatorTree (for Any Directed Graph).cpp │ ├── DominatorTree.cpp │ ├── F(x) * x <=N Trick.cpp │ ├── HLD.cpp │ ├── LCA (using SparseTable).cpp │ ├── LCA,O(VlogV+Q).cpp │ ├── MO on Tree.cpp │ └── Path Path Intersection.cpp └── shortestPath │ ├── 0-1BFS.cpp │ ├── BellmanFord.cpp │ ├── Dijkstra(V^2).cpp │ ├── Dijkstra(VlogV+E).cpp │ ├── FloydWarshall.cpp │ └── JohnsonAlgorithm.cpp ├── Math ├── Combinatorial Summation Formulas.pdf ├── Combinatorics │ ├── Fibonacci Combination Sums.cpp │ ├── Partition Function.cpp │ ├── Stirling Number (via NTT).cpp │ └── nCr mod M.cpp ├── Linear Equation - Matrix │ ├── Gaussian Elimination.cpp │ ├── Matrix.cpp │ ├── Maximum Xor Subset.cpp │ ├── SImplex.cpp │ └── Thomas Algorithm.cpp ├── Number Theory │ ├── Baby Step Giant Step (Any modulo).cpp │ ├── Baby Step Giant Step (Only Prime Modulo).cpp │ ├── Continued Fraction.cpp │ ├── Diophantine Equation.cpp │ ├── Fast Fibonacci.cpp │ ├── Faulhaber's Formua.cpp │ ├── Fraction Binary Search.cpp │ ├── General CRT.cpp │ ├── Geometric Sum.cpp │ ├── Integration (Romberg).cpp │ ├── Integration (Simpson).cpp │ ├── Interpolation (Lagrange - Optimized).cpp │ ├── Interpolation (Lagrange).cpp │ ├── Interpolation (Newton).cpp │ ├── Lehmer Prime Counting.cpp │ ├── Maximum Divisors in Range.cpp │ ├── Pollard's Rho.cpp │ ├── Primitive root for Prime.cpp │ ├── Range Congruence.cpp │ ├── Schreier–Sims Group Test.cpp │ └── Sieve (Linear).cpp └── Polynomial │ ├── FFT (Faster).cpp │ ├── FFT (Slow, but short).cpp │ ├── FWHT.cpp │ ├── KaratSuva.cpp │ ├── NTT Applications.cpp │ ├── NTT.cpp │ ├── Online FFT Trick.cpp │ ├── Polynomial Root Check.cpp │ └── Polynomial.cpp ├── Matroid ├── colorGraphicMatroid.cpp ├── colorLinearMatroid.cpp └── graphicGraphicMatroid.cpp ├── Notes ├── Bernoulli.cpp ├── Catalan.cpp ├── Euler's Therorem ├── Eulerian.cpp ├── Linear Algebra.pdf ├── Notebook (KTH).pdf ├── Notebook (NTU).pdf └── Stirling.cpp ├── README.md └── String ├── Aho Corasick.cpp ├── Dynamic Aho-Corasick.cpp ├── Hashing (1D).cpp ├── Hashing (2D).cpp ├── KMP Fail + Z-Algo.cpp ├── Minimum Lexicographical Rotation.cpp ├── Palindromic Tree.cpp ├── Suffix Array (O(n logn)).cpp └── Suffix Automata.cpp /AdHoc/Bit Hacks.cpp: -------------------------------------------------------------------------------- 1 | #define ll long long int 2 | 3 | // Only for non-negative integers 4 | // Returns the immediate next number 5 | // with same count of one bits, -1 on failure 6 | ll NextSamePop(ll n){ 7 | if(n == 0) return -1; ll x = (n & -n); 8 | ll left = (x + n);ll right = ((n ^ left) / x) >> 2; 9 | ll res = (left | right); return res; 10 | } 11 | 12 | // Returns the immediate previous number 13 | // with same count of one bits, -1 on failure 14 | ll PrevSamePop(ll n){ 15 | if (n == 0 || n == 1) return -1; 16 | ll res = ~NextSamePop(~n); return (res == 0) ? -1 : res; 17 | } 18 | 19 | unsigned int reverse_bits(unsigned int v){ 20 | v = ((v >> 1) & 0x55555555) | ((v & 0x55555555) << 1); 21 | v = ((v >> 2) & 0x33333333) | ((v & 0x33333333) << 2); 22 | v = ((v >> 4) & 0x0F0F0F0F) | ((v & 0x0F0F0F0F) << 4); 23 | v = ((v >> 8) & 0x00FF00FF) | ((v & 0x00FF00FF) << 8); 24 | return ((v >> 16) | (v << 16)); 25 | } 26 | -------------------------------------------------------------------------------- /AdHoc/FastIO.cpp: -------------------------------------------------------------------------------- 1 | inline int getint(){ 2 | char ch = getchar(); int x = 0; 3 | while(ch < '0' || ch > '9') ch = getchar(); 4 | while(ch >= '0' && ch <= '9'){ 5 | x = x * 10 + ch - '0'; ch = getchar(); 6 | } 7 | return x; 8 | } 9 | -------------------------------------------------------------------------------- /AdHoc/Gray Code.cpp: -------------------------------------------------------------------------------- 1 | #define ll long long int 2 | ll gray_code(ll x){return x ^ (x >> 1);} 3 | ll inverse_gray_code(ll x){ 4 | ll h = 1, res = 0; 5 | do{ 6 | if (x & 1) res ^= h; 7 | x >>= 1, h = (h << 1) + 1; 8 | } while (x); 9 | return res; 10 | } 11 | -------------------------------------------------------------------------------- /AdHoc/Infinite Grid.cpp: -------------------------------------------------------------------------------- 1 | //infinite grid formed by replication of initial n*m grid 2 | //All co-ordinates are 0-indexed 3 | //Answer rectangular queries (x1,y1,x2,y2) 4 | 5 | int n, m; 6 | ll F(int x,int y){ 7 | if(x < 0 || y < 0) return 0; 8 | 9 | //12 10 | //34 11 | int r = x / n; int c = y / m; 12 | int X = x % n; int Y = y % m; 13 | 14 | //Case 1 : r * c Full blocks) 15 | if(r && c){ 16 | //Add contribution of g(0,0,n-1,m-1) 17 | //in range row[0,r-1] and col[0,c-1] 18 | } 19 | 20 | //Case 2 : c partial (row-wise) blocks 21 | if(c){ 22 | //Add contribution of g(0,0,X,m-1) 23 | //in range col[0,c-1] 24 | } 25 | 26 | //Case 3 : r partial (col-wise) blocks 27 | if(r){ 28 | //Add contribution of g(0,0,n-1,Y) 29 | //in range row[0,r-1] 30 | } 31 | 32 | //Case 4 : only partial (both row and col-wise) block(r,c) 33 | //Add contribution of g(0,0,X,Y) for block(r,c) 34 | } 35 | 36 | ll Solve(int x1,int y1,int x2,int y2){ 37 | return F(x2,y2) - F(x1-1,y2) - F(x2,y1-1) + F(x1-1,y1-1); 38 | } 39 | -------------------------------------------------------------------------------- /AdHoc/Josephus Problem.cpp: -------------------------------------------------------------------------------- 1 | // Tested : Gym 101955K - Let the Flames Begin 2 | 3 | #include 4 | using namespace std; 5 | #define ll long long int 6 | // Complexity : O(min(k log(n), m)) 7 | // People 1 to n in a circle, counting starts from 1, every k'th 8 | // people dies, returns the position of the m'th killed people 9 | ll Josephus(ll n, ll k, ll m){ 10 | m = n - m; 11 | if (k <= 1) return n - m; 12 | ll i = m; 13 | while (i < n){ 14 | ll r = (i - m + k - 2) / (k - 1); 15 | if ((i + r) > n) r = n - i; 16 | else if (!r) r = 1; 17 | i += r; 18 | m = (m + (r * k)) % i; 19 | } 20 | return m + 1; 21 | } 22 | -------------------------------------------------------------------------------- /AdHoc/Knight Distance.cpp: -------------------------------------------------------------------------------- 1 | #define ll long long int 2 | // Minimum number of knight moves from (x,y) to 3 | // (0,0) in non-negative infinite chessboard 4 | ll knight_move(ll x, ll y){ 5 | ll cnt = max({(x+1)/2, (y+1)/2, (x+y+2)/3}); 6 | while((cnt%2) != (x+y)%2) cnt++; 7 | if(x == 1 && !y) return 3; 8 | if(y == 1 && !x) return 3; 9 | if(x == y && x == 2) return 4; 10 | return cnt; 11 | } 12 | -------------------------------------------------------------------------------- /AdHoc/RandomShuffle.cpp: -------------------------------------------------------------------------------- 1 | mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); 2 | vector permutation(N); 3 | shuffle(permutation.begin(), permutation.end(), rng); 4 | -------------------------------------------------------------------------------- /AdHoc/__int128.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main(){ 5 | int n = 100; 6 | __int128 Ans = n; 7 | 8 | vector vec; 9 | vec.clear(); 10 | while(Ans) vec.push_back(Ans % 10 | 48), Ans /= 10; 11 | reverse(vec.begin(),vec.end()); 12 | for(char x : vec) printf("%c",x); 13 | printf("\n"); 14 | } 15 | -------------------------------------------------------------------------------- /DP/DP Optimization/Alien Trick.cpp: -------------------------------------------------------------------------------- 1 | Lets say we need to divide n elements into k groups and 2 | minimize the sum of a specific function for each group. 3 | Normally this kind of problem can be solved by CHT or D&C. 4 | Alien trick comes into use when N, K <= 10^5. 5 | 6 | We can use alien trick if the following conditions holds: 7 | Here, Fn(K) = The value of dividing N elements into K groups 8 | 1. Fn(K) >= Fn(K + 1) (FOR MINIMIZE , For maximum it's reverse) 9 | It means its always optimal to use (K+1) groups than K groups 10 | 2. Fn(K - 1) - Fn(K) >= Fn(K) - Fn(K + 1) (FOR Minimize) 11 | 12 | It means with the increase of K, ans becomes more optimal, 13 | but the rate of becoming optimal slows down. 14 | 15 | If a function satisfies the above 2 conditions : then 16 | we define G(n) = Fn(k) + kC 17 | That means we need to add an extra C for each group we use. 18 | Now this G(n) function will follow a convex property. 19 | 20 | So now we can do binary search on C. Inside the binary search. 21 | For each mid, we find the optmial value of G(n) and the 22 | corresponding k for that value. This k decreases when C increases. 23 | 24 | We find the lowest C for which corresponding k is <= given K. 25 | This trick may apply for problems other than DP as well. 26 | -------------------------------------------------------------------------------- /DP/DP Optimization/CHT (Dynamic).cpp: -------------------------------------------------------------------------------- 1 | //Dynamic CHT 2 | //Tested : CF 455E - Function 3 | 4 | #define ll long long int 5 | #define ld long double 6 | ll inf = 9e18 + 5; 7 | 8 | struct HullDynamic{ // Max Query 9 | struct line { 10 | ll m, b; ld x; 11 | ll val; bool isQuery; 12 | line(ll _m = 0, ll _b = 0) : 13 | m(_m), b(_b), val(0), x(-inf), isQuery(false) {} 14 | 15 | ll eval(ll x) const { return m * x + b; } 16 | bool parallel(const line &l) const { return m == l.m; } 17 | ld intersect(const line &l) const { 18 | return parallel(l) ? inf : 1.0 * (l.b - b) / (m - l.m); 19 | } 20 | bool operator < (const line &l) const { 21 | if(l.isQuery) return x < l.val; 22 | else return m < l.m; 23 | } 24 | }; 25 | 26 | set hull; 27 | typedef set :: iterator iter; 28 | 29 | bool cPrev(iter it) { return it != hull.begin(); } 30 | bool cNext(iter it) { return it != hull.end() && next(it) != hull.end(); } 31 | 32 | bool bad(const line &l1, const line &l2, const line &l3) { 33 | return l1.intersect(l3) <= l1.intersect(l2); 34 | } 35 | bool bad(iter it) { 36 | return cPrev(it) && cNext(it) && bad(*prev(it), *it, *next(it)); 37 | } 38 | 39 | iter update(iter it) { 40 | if(!cPrev(it)) return it; 41 | ld x = it -> intersect(*prev(it)); 42 | line tmp(*it); tmp.x = x; 43 | it = hull.erase(it); 44 | return hull.insert(it, tmp); 45 | } 46 | 47 | void Add(ll m, ll b) { 48 | line l(m, b); 49 | iter it = hull.lower_bound(l); 50 | if(it != hull.end() && l.parallel(*it)) { 51 | if(it -> b < b) it = hull.erase(it); 52 | else return; 53 | } 54 | 55 | it = hull.insert(it, l); 56 | if(bad(it)) return (void) hull.erase(it); 57 | 58 | while(cPrev(it) && bad(prev(it))) hull.erase(prev(it)); 59 | while(cNext(it) && bad(next(it))) hull.erase(next(it)); 60 | 61 | it = update(it); 62 | if(cPrev(it)) update(prev(it)); 63 | if(cNext(it)) update(next(it)); 64 | } 65 | 66 | ll Query(ll x) const { 67 | if(hull.empty()) return -inf; 68 | line q; q.val = x, q.isQuery = 1; 69 | iter it = --hull.lower_bound(q); 70 | return it -> eval(x); 71 | } 72 | }; 73 | -------------------------------------------------------------------------------- /DP/DP Optimization/CHT (Offline).cpp: -------------------------------------------------------------------------------- 1 | //Offline CHT 2 | struct Line{ 3 | ll m,c; 4 | Line(ll x,ll y){m=x; c=y;} 5 | ll Get(ll x) {return m*x+c;} 6 | bool operator<(const Line &other) const {return m < other.m;} 7 | }; 8 | 9 | bool Bad(Line &P,Line &C,Line &N){ 10 | return (P.c-C.c) * 1.0L * (N.m-P.m) > (P.c-N.c) * 1.0L * (C.m - P.m); 11 | } 12 | 13 | //This Convex Hull always maintains lower convex hull 14 | //m1 >= m2 >= m3 .... >= mk 15 | //For Min Query : Add(m,c) 16 | //For Max Query : Add(-m,-c) 17 | 18 | struct ConvexHull{ 19 | vectorhull; 20 | 21 | void Add(ll m,ll c){ 22 | //always maintaining the minimum c in case multiple equal m 23 | if(hull.size()>0 && hull.back().m==m) { 24 | if(hull.back().c>c) hull.pop_back(); 25 | else return; 26 | } 27 | 28 | hull.push_back(Line(m, c)); 29 | int sz=hull.size(); 30 | while(sz>2 && Bad(hull[sz-3],hull[sz-2],hull[sz-1])){ 31 | swap(hull[sz-2],hull[sz-1]); hull.pop_back(); sz--; 32 | } 33 | } 34 | 35 | ll Query(ll x){ 36 | int lo=-1; 37 | int hi=hull.size()-1; 38 | while(hi-lo>1) { 39 | int mid=(lo+hi)/2; 40 | if(hull[mid].Get(x)>=hull[mid+1].Get(x)) lo=mid; 41 | else hi=mid; 42 | } 43 | if(hi<0 || hi>=hull.size()) return INF; 44 | return hull[hi].Get(x); 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /DP/DP Optimization/Divide & Conquer Optimization.cpp: -------------------------------------------------------------------------------- 1 | // Complexity : O(n log n) 2 | // dp[i][j] = min(dp[i-1][k-1] + C[k][j]) [ k <= j ] 3 | // To use D&Q, its sufficient to prove the following : 4 | // Cost(L + 1 , j + 1) - Cost(L + 1, j) <= Cost(k + 1, j + 1) - Cost(k + 1, j) for any(L < k < j) For Max Query 5 | // Cost(L + 1 , j + 1) - Cost(L + 1, j) >= Cost(k + 1, j + 1) - Cost(k + 1, j) for any(L < k < j) For Min Query 6 | 7 | #include 8 | using namespace std; 9 | #define ll long long int 10 | const int MAX = 5005; 11 | 12 | int ara[MAX]; 13 | ll dp[2][MAX]; 14 | ll C[MAX][MAX]; 15 | 16 | void compute(int K, int L, int R, int OptL, int OptR){ 17 | if(L > R) return; 18 | int mid = (L + R) / 2; 19 | 20 | int optNow = -1; 21 | dp[K & 1][mid] = 0; 22 | for(int i=OptL; i<=min(OptR, mid); i++){ 23 | ll tmp = dp[(K & 1) ^ 1][i - 1] + C[i][mid]; 24 | if(tmp >= dp[K & 1][mid]){ 25 | dp[K & 1][mid] = tmp; 26 | optNow = i; 27 | } 28 | } 29 | compute(K, L, mid - 1, OptL, optNow); 30 | compute(K, mid + 1, R, optNow, OptR); 31 | } 32 | 33 | int main(){ 34 | int t; 35 | scanf("%d",&t); 36 | 37 | while(t--){ 38 | int n, K; 39 | scanf("%d %d", &n, &K); 40 | for(int i=1; i<=n; i++) scanf("%d",&ara[i]); 41 | 42 | for(int i=1; i<=n; i++){ 43 | for(int j=i; j<=n; j++){ 44 | if(i==j) C[i][j] = ara[j]; 45 | else C[i][j] = C[i][j-1] | ara[j]; 46 | } 47 | } 48 | 49 | for(int i=1; i<=n; i++) dp[1][i] = C[1][i]; 50 | for(int i=2; i<=K; i++) compute(i, 1, n, 1, n); 51 | printf("%lld\n", dp[K & 1][n]); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /DP/DP Optimization/Knuth Optimization.cpp: -------------------------------------------------------------------------------- 1 | //Complexity : O(n^2) for any k <= n 2 | #include 3 | using namespace std; 4 | #define MAX 5005 5 | #define ll long long int 6 | 7 | ll M[MAX]; 8 | const ll INVALID = LLONG_MIN; 9 | ll C[MAX][MAX],dp[MAX][MAX],Opt[MAX][MAX]; 10 | //Recurrence : dp[i][j] = min/max i <= k <= j (dp[i-1][k-1] + C[k][j]) 11 | //Condition : Opt[i-1][j] <= Opt[i][j] <= Opt[i][j+1] 12 | 13 | int main(){ 14 | int N,K; 15 | scanf("%d %d",&N,&K); 16 | for(int i=1;i<=N;i++) scanf("%lld",&M[i]); 17 | for(int i=1;i<=N;i++) for(int j=i;j<=N;j++) C[i][j]=C[i][j-1] | M[j]; 18 | 19 | for(int i=0;i<=K;i++) dp[i][0]=0; 20 | for(int i=0;i<=K;i++) for(int j=1;j<=N;j++) dp[i][j]=INVALID; 21 | for(int i=1;i<=N;i++) {Opt[0][i]=1; Opt[i][N+1]=N;} 22 | 23 | for(int i=1;i<=K;i++){ 24 | for(int j=N;j>=1;j--){ 25 | for(int k=Opt[i-1][j];k<=Opt[i][j+1];k++){ 26 | if(dp[i-1][k-1]== INVALID) continue; 27 | if(dp[i][j] 2 | using namespace std; 3 | #define ll long long int 4 | const int MAX_X = 100005; 5 | //domain of f(x) = [1, MAX_X-1] 6 | 7 | struct Poly{ 8 | vector co; 9 | Poly(){} 10 | void add(ll c) {co.push_back(c);} 11 | ll f(ll x){ 12 | ll ans = 0; 13 | ll mul = 1; 14 | for(ll c : co) {ans += mul * c; mul = mul * x;} 15 | return ans; 16 | } 17 | }; 18 | 19 | #define Left (node*2) 20 | #define Right (node*2+1) 21 | #define mid ((lo+hi)/2) 22 | Poly tree[4 * MAX_X]; 23 | 24 | void build(int node, int lo, int hi){ 25 | tree[node].co.clear(); 26 | tree[node].add(LLONG_MAX); 27 | if(lo == hi) return; 28 | build(Left, lo, mid); 29 | build(Right, mid+1, hi); 30 | } 31 | 32 | void addLine(int node, int lo, int hi, Poly upd){ 33 | bool bame = upd.f(lo) < tree[node].f(lo); 34 | bool majhe = upd.f(mid) < tree[node].f(mid); 35 | if(majhe) swap(tree[node], upd); 36 | 37 | if(lo == hi) return; 38 | if(bame != majhe) addLine(Left, lo, mid, upd); 39 | else addLine(Right, mid+1, hi, upd); 40 | } 41 | 42 | ll query(int node, int lo, int hi, ll x){ 43 | ll Curr = tree[node].f(x); 44 | if(lo == hi) return Curr; 45 | if(x <= mid) return min(Curr, query(Left, lo, mid, x)); 46 | else return min(Curr, query(Right, mid+1, hi, x)); 47 | } 48 | 49 | // Comments : 50 | // 1. Applies directly to lines in any domain space 51 | // 2. In positive domain space, polynomials behave 52 | // like lines after a certain threshold value MAGIC. 53 | // Add a function as addLine(1,Magic,MAX_X-1, cur_poly) 54 | // For query x < MAGIC, brute-force to calculate minimum 55 | // For query x >= MAGIC, return query(1,Magic,MAX_X-1,x) 56 | -------------------------------------------------------------------------------- /DP/DP Optimization/Li-Chao Tree (Sparse).cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define ll long long int 4 | 5 | const int maxk = 105; 6 | const int maxn = 10005; 7 | const int maxX = 1000005; 8 | const ll inf = 1e12; 9 | 10 | struct Poly{ 11 | vector co; 12 | Poly() {} 13 | void add(ll c) {co.push_back(c);} 14 | ll f(ll x){ 15 | if(co.size() == 0) return inf; 16 | 17 | ll ans = 0; 18 | ll mul = 1; 19 | for(ll c : co) {ans += mul * c; mul = mul * x;} 20 | return ans; 21 | } 22 | }; 23 | 24 | struct lc{ 25 | Poly S; 26 | lc *lft, *rgt; 27 | 28 | lc() {lft = rgt = NULL; S = Poly();} 29 | 30 | void Del(){ 31 | if(lft) lft->Del(); 32 | if(rgt) rgt->Del(); 33 | delete this; 34 | } 35 | 36 | void add(int lo, int hi, Poly upd){ 37 | if(upd.f(lo) > S.f(lo) && upd.f(hi) > S.f(hi)) return; 38 | 39 | int mid = (lo + hi) / 2; 40 | bool bame = upd.f(lo) < S.f(lo); 41 | bool majhe = upd.f(mid) < S.f(mid); 42 | if(majhe) swap(S, upd); 43 | if(lo == hi) return; 44 | 45 | if(bame != majhe){ 46 | if(!lft) lft = new lc(); 47 | lft->add(lo, mid, upd); 48 | } 49 | else{ 50 | if(!rgt) rgt = new lc(); 51 | rgt->add(mid+1, hi, upd); 52 | } 53 | } 54 | 55 | ll query(int lo, int hi, ll x){ 56 | ll Curr = S.f(x); 57 | if(lo == hi) return Curr; 58 | int mid = (lo + hi) / 2; 59 | if(x <= mid) return min(Curr, lft ? lft->query(lo, mid, x) : inf); 60 | else return min(Curr, rgt ? rgt->query(mid+1, hi, x) : inf); 61 | } 62 | }; 63 | -------------------------------------------------------------------------------- /DP/DP Optimization/SOS DP.cpp: -------------------------------------------------------------------------------- 1 | //SOS DP 2 | 3 | for(int mask = 0; mask < (1<> 63; 30 | x &= ~(y << 1); 31 | if(v) x &= ~1ULL; 32 | } 33 | res += __builtin_popcountll(x); 34 | } 35 | return res; 36 | } 37 | -------------------------------------------------------------------------------- /DP/Special DP/SteinerTree.cpp: -------------------------------------------------------------------------------- 1 | struct edge{ 2 | int t , v; 3 | edge(int t=0 ,int v=0):t(t),v(v){} 4 | }; 5 | // f[u][v] = shortest Path between u to v 6 | // D[r][mask] = minimum cost stainer tree with root r and covering all the nodes in the mask. 7 | 8 | struct StreinerTree{ 9 | int n; 10 | int f[maxn][maxn] , d[maxn][1<n = n; 13 | for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f[i][j] = INF; 14 | } 15 | 16 | void addEdge(int ff , int t , int v) { 17 | f[ff][t] = min(v , f[ff][t]); 18 | f[t][ff] = min(v , f[t][ff]); 19 | } 20 | 21 | void floyd() { 22 | for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) 23 | f[i][j] = min(f[i][j] , f[i][k]+f[k][j]); 24 | } 25 | 26 | void mincostST(vector s) { 27 | for(int i=1;i<=n;i++) for(int j=0;j<(1<0;ii = (ii-1)&i) 31 | d[j][i] = min(d[j][i] , d[j][ii]+d[j][i-ii]); 32 | for(int j=1;j<=n;j++) for(int k=1;k<=n;k++) d[j][i] = min(d[j][i] , d[k][i]+f[j][k]); 33 | } 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /DS/BIT/BIT (1D).cpp: -------------------------------------------------------------------------------- 1 | //Tested : LightOJ 1164 - Horrible Queries 2 | 3 | #include 4 | using namespace std; 5 | #define ll long long int 6 | const int MAXN = 1000005; 7 | 8 | ll BIT[2][MAXN]; 9 | void update(int cs, int indx, ll val){ 10 | while(indx < MAXN){ 11 | BIT[cs][indx] += val; 12 | indx += (indx & -indx); 13 | } 14 | } 15 | 16 | ll sum(int cs, int indx){ 17 | ll ans = 0; 18 | while(indx != 0) { 19 | ans += BIT[cs][indx]; 20 | indx -= (indx & -indx); 21 | } 22 | return ans; 23 | } 24 | 25 | void updateRange(int l, int r, ll val){ 26 | update(0,l,val); update(0,r+1,-val); 27 | update(1,l,val*(l-1)); update(1,r+1,-val*r); 28 | } 29 | 30 | ll sumRange(int indx) {return sum(0,indx)*indx - sum(1,indx);} 31 | ll QueryRange(int l, int r) {return sumRange(r)-sumRange(l-1);} 32 | 33 | const int LOGN = 20; 34 | int LowerBound(int cs, ll v){ 35 | ll sum = 0; 36 | int indx = 0; 37 | for(int i = LOGN; i >= 0; i--){ 38 | int nPos = indx + (1< 4 | using namespace std; 5 | #define ll long long int 6 | const int MAXN = 1005; 7 | int BIT[MAXN][MAXN]; 8 | 9 | //A[x][y] += val 10 | void update(int x, int y, int val){ 11 | int xx = x; 12 | while(xx < MAXN){ 13 | int yy = y; 14 | while(yy < MAXN){ 15 | BIT[xx][yy] += val; 16 | yy += (yy & -yy); 17 | } 18 | xx += (xx & -xx); 19 | } 20 | } 21 | 22 | //return sum over all A[i][j], where 1 <= i <= x and 1 <= j <= y 23 | int sum(int x, int y){ 24 | int ans = 0; 25 | int xx = x; 26 | while(xx != 0){ 27 | int yy = y; 28 | while(yy != 0){ 29 | ans += BIT[xx][yy]; 30 | yy -= (yy & -yy); 31 | } 32 | xx -= (xx & -xx); 33 | } 34 | return ans; 35 | } 36 | -------------------------------------------------------------------------------- /DS/BIT/BIT (2D - Range).cpp: -------------------------------------------------------------------------------- 1 | //Tested : https://www.spoj.com/problems/USUBQSUB 2 | 3 | #include 4 | using namespace std; 5 | #define ll long long int 6 | const int MAXN = 1005; 7 | 8 | struct BIT2D{ 9 | ll tree[4][MAXN][MAXN]; 10 | BIT2D() {memset(tree,0,sizeof(tree));} 11 | 12 | //Add v to submatrix [i,j] to [inf,inf] 13 | void update(int p, int q, ll v){ 14 | if((p <= 0) || (q <= 0) || (p >= MAXN) || (q >= MAXN)) return; 15 | 16 | int i = p, c = p - 1, d = q - 1; 17 | while(i < MAXN){ 18 | int j = q; 19 | while(j < MAXN){ 20 | tree[0][i][j] += v; tree[1][i][j] += (v * d); 21 | tree[2][i][j] += (v * c); tree[3][i][j] += (v * c * d); 22 | j += (j & -j); 23 | } 24 | i += (i & -i); 25 | } 26 | } 27 | 28 | //returns Sum over submatrix [1,1] to [p,q] 29 | ll query(int p, int q){ 30 | int i, j; 31 | ll x, y, z, c, d, res; 32 | 33 | i = p, x = y = z = 0; 34 | while(i != 0){ 35 | j = q, c = d = 0; 36 | while(j != 0){ 37 | c += tree[0][i][j]; d += tree[1][i][j]; 38 | y += tree[2][i][j]; z += tree[3][i][j]; 39 | j ^= (j & (-j)); 40 | } 41 | i ^= (i & -i); 42 | x += (c * q - d); 43 | } 44 | res = (x * p) - (y * q) + z; 45 | return res; 46 | } 47 | 48 | //Add v to submatrix [i,j] to [k,l] 49 | void update(int i, int j, int k, int l, ll v){ 50 | update(i, j, v); update(k + 1, j, -v); 51 | update(k + 1, l + 1, v); update(i, l + 1, -v); 52 | } 53 | 54 | //returns Sum over submatrix [i,j] to [k,l] 55 | ll query(int i, int j, int k, int l){ 56 | if (i > k || j > l) return 0; 57 | ll res = query(k, l) - query(i - 1, l) + query(i - 1, j - 1) - query(k, j - 1); 58 | return res; 59 | } 60 | }; 61 | -------------------------------------------------------------------------------- /DS/BIT/BIT (3D).cpp: -------------------------------------------------------------------------------- 1 | //Point Update and Range Query similar as 2D BIT 2 | 3 | void update(int x1, int y1, int z1, int x2, int y2, int z2){ 4 | update(x2, y2, z2, 1), update(x1 - 1, y1 - 1, z2, 1); 5 | update(x1 - 1, y2, z1 - 1, 1), update(x2, y1 - 1, z1 - 1, 1); 6 | update(x1 - 1, y2, z2, -1), update(x2, y1 - 1, z2, -1); 7 | update(x2, y2, z1 - 1, -1), update(x1 - 1, y1 - 1, z1 - 1, -1); 8 | } 9 | -------------------------------------------------------------------------------- /DS/Closest Pair.cpp: -------------------------------------------------------------------------------- 1 | // Tested : UVa 10245 - The Closest Pair Problem 2 | 3 | #include 4 | using namespace std; 5 | #define ll long long int 6 | 7 | struct Point{ 8 | ll x, y; 9 | Point() {} 10 | Point(ll _x, ll _y) {x = _x; y = _y;} 11 | bool operator < (const Point &p) const {return x == p.x ? y < p.y : x < p.x;} 12 | Point operator - (Point p) {return Point(x - p.x, y - p.y);} 13 | }; 14 | ll getDot(Point a,Point b) {return a.x * b.x + a.y * b.y;} 15 | ll dist(Point p, Point q) {return getDot(p-q, p-q);} 16 | 17 | vector p; 18 | ll solve(int l, int r) { 19 | if(r - l <= 3) { 20 | ll ret = LLONG_MAX; 21 | for(int i = l; i <= r; i++) 22 | for(int j = i + 1; j <= r; j++) 23 | ret = min(ret, dist(p[i], p[j])); 24 | return ret; 25 | } 26 | 27 | int mid = (l + r) / 2; 28 | ll d = min(solve(l, mid), solve(mid+1, r)); 29 | 30 | vector t; 31 | for(int i = l; i <= r; i++){ 32 | ll dx = p[mid].x - p[i].x; 33 | if(dx * dx <= d) t.push_back({p[i].y, p[i].x}); 34 | } 35 | 36 | sort(t.begin(), t.end()); 37 | for(int i = 0; i < t.size(); i++) { 38 | for(int j = i+1; j < t.size() && j <= i + 15; j++) 39 | d = min(d, dist(t[i], t[j])); 40 | } 41 | return d; 42 | } 43 | 44 | ll closestPair() { 45 | sort(p.begin(), p.end()); 46 | return solve(0, p.size()-1); 47 | } 48 | -------------------------------------------------------------------------------- /DS/HashTable.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | using namespace __gnu_pbds; 5 | 6 | const int RANDOM = chrono::high_resolution_clock::now().time_since_epoch().count(); 7 | unsigned hash_f(unsigned x) { 8 | x = ((x >> 16) ^ x) * 0x45d9f3b; 9 | x = ((x >> 16) ^ x) * 0x45d9f3b; 10 | x = (x >> 16) ^ x; 11 | return x; 12 | } 13 | 14 | unsigned hash_combine(unsigned a, unsigned b) { return a * 31 + b; } 15 | struct chash {int operator()(int x) const { return hash_f(x); }}; 16 | typedef gp_hash_tablegp; 17 | gp table; 18 | -------------------------------------------------------------------------------- /DS/KD Tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 200555, K = 2; 4 | typedef long long ll; 5 | #define sqr(x) ((x) * (x)) 6 | 7 | int k = 2, idx; 8 | // idx = current dimension, k = total dimension 9 | 10 | struct Point{ 11 | int pr, id; 12 | ll x[K]; 13 | bool operator < (const Point &u) const {return x[idx] < u.x[idx];} 14 | }po[N]; 15 | 16 | typedef pair < ll , Point > tp; 17 | priority_queue < tp > nq; 18 | 19 | struct KDtree{ 20 | Point pt[N<<2]; 21 | int son[N<<2], mn[N<<2]; 22 | 23 | void init(){ 24 | memset(son, 0, sizeof(son)); 25 | memset(mn, 0, sizeof(mn)); 26 | } 27 | 28 | void build(int l, int r, int node = 1, int dep = 0) { 29 | if(l > r) return; 30 | son[node] = r - l; 31 | son[node * 2] = son[node * 2 + 1] = -1; 32 | idx = dep % k; 33 | int mid = (l + r) / 2; 34 | nth_element(po + l, po + mid, po + r + 1); 35 | pt[node] = po[mid]; 36 | mn[node] = po[mid].pr; 37 | 38 | build(l, mid - 1, node * 2, dep + 1); 39 | build(mid + 1, r, node * 2 + 1, dep + 1); 40 | 41 | mn[node] = min(mn[node], min(mn[node * 2], mn[node * 2 + 1])); 42 | } 43 | 44 | void query(Point p, int m, int node = 1, int dep = 0){ 45 | if(son[node] == -1) return; 46 | tp nd(0, pt[node]); 47 | for(int i = 0; i < k; i++) nd.first += sqr(nd.second.x[i] - p.x[i]); 48 | int dim = dep % k; 49 | int lft = 2 * node, rgh = 2 * node + 1, fg = 0; 50 | if(p.x[dim] >= pt[node].x[dim]) swap(lft, rgh); 51 | 52 | if(nd.second.pr > p.pr) nd.first = 1e18; 53 | if(~son[lft] && mn[lft] <= p.pr) query(p, m, lft, dep + 1); 54 | 55 | if(nq.size() < m) nq.push(nd), fg = 1; 56 | else{ 57 | if(nd.first < nq.top().first) nq.pop(), nq.push(nd); 58 | else if(nd.first == nq.top().first && nd.second.id < nq.top().second.id) nq.pop(), nq.push(nd); 59 | if(sqr(p.x[dim] - pt[node].x[dim]) <= nq.top().first) fg = 1; 60 | } 61 | if(~son[rgh] && fg && mn[rgh] <= p.pr) query(p, m, rgh, dep + 1); 62 | } 63 | }kdt; 64 | int T, n, m, root; 65 | 66 | int main(){ 67 | cin >> T; 68 | 69 | while(T--){ 70 | scanf("%d %d", &n, &m); 71 | for(int i = 1; i <= n; i++){ 72 | scanf("%lld %lld %lld", &po[i].x[0], &po[i].x[1], &po[i].pr); 73 | po[i].id = i; 74 | } 75 | 76 | kdt.build(1, n); 77 | while(m--){ 78 | Point p; 79 | scanf("%lld %lld %lld", &p.x[0], &p.x[1], &p.pr); 80 | kdt.query(p, 1); 81 | if(nq.empty()){ 82 | printf("-1\n"); 83 | continue; 84 | } 85 | printf("%lld %lld %d\n", nq.top().second.x[0], nq.top().second.x[1], nq.top().second.pr); 86 | while(!nq.empty()) nq.pop(); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /DS/MO/MO (Basic).cpp: -------------------------------------------------------------------------------- 1 | namespace MO{ 2 | const int MAXN = 100005; 3 | const int MAXQ = 100005; 4 | 5 | int Sz; 6 | int A[MAXN]; 7 | int blkId[MAXN]; 8 | bool vis[MAXN]; 9 | 10 | struct Query{ 11 | int L,R,id; 12 | Query(){} 13 | Query(int x,int y,int i){L=x;R=y;id=i;} 14 | bool operator<(const Query other) const{ 15 | int a = blkId[L]; int b = blkId[other.L]; 16 | return a == b ? (a & 1 ? (R > other.R) : (R < other.R)) : a < b; 17 | } 18 | }qry[MAXQ]; 19 | int perQ[MAXQ]; 20 | 21 | int MaxFreq = 0; 22 | int CoC[MAXN]; 23 | int Count[MAXN]; 24 | void Check(int x){ 25 | if(!vis[x]){ 26 | vis[x]=1; 27 | if(Count[A[x]]) CoC[Count[A[x]]]--; 28 | Count[A[x]]++; CoC[Count[A[x]]]++; 29 | if(CoC[MaxFreq + 1]) MaxFreq++; 30 | } 31 | else{ 32 | vis[x]=0; 33 | CoC[Count[A[x]]]--; Count[A[x]]--; 34 | if(Count[A[x]]) CoC[Count[A[x]]]++; 35 | if(CoC[MaxFreq] == 0) MaxFreq--; 36 | } 37 | } 38 | } 39 | using namespace MO; 40 | 41 | int main(){ 42 | int N,Q; 43 | scanf("%d %d",&N,&Q); 44 | 45 | //Initiate Global 46 | Sz=sqrt(N); 47 | memset(vis,0,sizeof(vis)); 48 | memset(Count,0,sizeof(Count)); 49 | for(int i=0;i<=N;i++) blkId[i] = i/Sz; 50 | 51 | for(int i=1;i<=N;i++) scanf("%d",&A[i]); 52 | for(int i=1;i<=Q;i++){ 53 | int l,r; 54 | scanf("%d %d",&l,&r); 55 | qry[i] = Query(l,r,i); 56 | } 57 | sort(qry+1,qry+Q+1); 58 | 59 | int left = qry[1].L; 60 | int right = left-1; 61 | 62 | for(int i=1;i<=Q;i++){ 63 | Query now = qry[i]; 64 | while(leftnow.L) Check(--left); 66 | while(rightnow.R) Check(right--); 68 | perQ[now.id] = MaxFreq; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /DS/MO/MO on Tree.cpp: -------------------------------------------------------------------------------- 1 | //MO on Tree 2 | int Time = 0; 3 | int Euler[2*MAXN]; 4 | vector adj[MAXN]; 5 | int Par[MAXN], D[MAXN], st[MAXN], en[MAXN]; 6 | 7 | void dfs(int u,int p){ 8 | st[u] = ++Time; Euler[Time] = u; 9 | Par[u] = p; 10 | D[u] = D[p] + 1; 11 | 12 | for(int v : adj[u]){ 13 | if(v == p) continue; 14 | dfs(v,u); 15 | } 16 | en[u] = ++Time; Euler[Time] = u; 17 | } 18 | using namespace MO; 19 | using namespace LCA; 20 | 21 | int main(){ 22 | int N,Q; 23 | scanf("%d %d",&N,&Q); 24 | 25 | //Input 26 | Time = 0; 27 | dfs(1,0); 28 | BuildSparse(N); 29 | 30 | for(int i=1;i<=Q;i++){ 31 | int u,v; 32 | scanf("%d %d",&u,&v); 33 | 34 | if(st[u]>st[v]) swap(u,v); 35 | int lca = LCA(u,v); 36 | if(lca == u) qry[i] = Query(st[u],st[v],i); //Case 1 : range(st[u],st[v]) 37 | else qry[i] = Query(en[u],st[v],i); //Case 2 : range(en[u],st[v]) and LCA(u,v) 38 | } 39 | 40 | Sz = sqrt(N); 41 | sort(qry+1,qry+Q+1); 42 | 43 | int left = qry[1].L; 44 | int right = left-1; 45 | for(int i=1;i<=Q;i++){ 46 | Query now = qry[i]; 47 | while(leftnow.L) Check(Euler[--left]); 49 | while(rightnow.R) Check(Euler[right--]); 51 | 52 | int lca = LCA(Euler[left],Euler[right]); 53 | if(Euler[left]!=lca && Euler[right]!=lca) Check(lca); //Adding LCA(u,v) for Case 2 54 | Ans[now.id]=MaxFreq; 55 | if(Euler[left]!=lca && Euler[right]!=lca) Check(lca); //Discarding the Addition 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /DS/OrderedSet.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include // Common file 3 | #include // Including tree_order_statistics_node_update 4 | #include 5 | using namespace std; 6 | using namespace __gnu_pbds; 7 | 8 | typedef tree< 9 | int,null_type,less, 10 | rb_tree_tag, 11 | tree_order_statistics_node_update> 12 | ordered_set; 13 | ordered_set xx; 14 | -------------------------------------------------------------------------------- /DS/Parallel Binary Search.cpp: -------------------------------------------------------------------------------- 1 | //Tested : Atcoder - Stamp Rally 2 | 3 | #include 4 | using namespace std; 5 | 6 | const int MAXN = 100005; 7 | const int MAXM = 100005; 8 | const int MAXQ = 100005; 9 | 10 | TYPE ds; //Size MAXN 11 | TYPE Update[MAXM]; 12 | TYPE Query[MAXQ]; 13 | vector Check[MAXM]; 14 | int lo[MAXQ], hi[MAXQ]; 15 | 16 | // For each qry in Query, find minimum upd such that condistions 17 | // for qry are satisfied after applying Update[1....upd] to ds 18 | void Solve(int n, int m, int q){ 19 | for(int qry=1; qry<=q; qry++) lo[qry] = 1, hi[qry] = m; 20 | 21 | bool Changed = true; 22 | while(Changed){ 23 | Changed = false; 24 | // Clear and Re-initialize ds upto size n 25 | for(int upd=1; upd<=m; upd++) Check[upd].clear(); 26 | 27 | for(int qry=1; qry<=q; qry++){ 28 | if(lo[qry] == hi[qry]) continue; 29 | Changed = true; 30 | int mid = (lo[qry] + hi[qry]) / 2; 31 | Check[mid].push_back(qry); 32 | } 33 | 34 | for(int upd=1; upd<=m; upd++){ 35 | //Apply Update[upd] 36 | for(int qry : Check[upd]){ 37 | bool ok = [conditions for Query[qry] is satisfied] 38 | if(ok) hi[qry] = upd; 39 | else lo[qry] = upd + 1; 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /DS/Segment Tree/MergeSortTree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAXN = 100005; 4 | 5 | int A[MAXN]; 6 | vectortree[MAXN*5]; 7 | 8 | #define Left (node*2) 9 | #define Right (node*2+1) 10 | #define mid ((lo+hi)/2) 11 | 12 | void build(int node, int lo, int hi){ 13 | if(lo==hi) {tree[node].push_back(A[lo]); return;} 14 | build(Left,lo,mid); 15 | build(Right,mid+1,hi); 16 | merge(tree[Left].begin(),tree[Left].end(),tree[Right].begin(),tree[Right].end(),back_inserter(tree[node])); 17 | } 18 | 19 | int query(int node, int lo, int hi, int i, int j, int x){ 20 | if(i>hi || j=i && hi<=j) return lower_bound(tree[node].begin(),tree[node].end(),x) - tree[node].begin(); 22 | int p1 = query(Left,lo,mid,i,j,x); 23 | int p2 = query(Right,mid+1,hi,i,j,x); 24 | return p1+p2; 25 | } 26 | -------------------------------------------------------------------------------- /DS/Segment Tree/SegTreeBeats.cpp: -------------------------------------------------------------------------------- 1 | // Tested : HDU - 5306 2 | 3 | #include 4 | using namespace std; 5 | const int maxn = 1000005; 6 | #define ll long long int 7 | 8 | int A[maxn]; 9 | struct data{ 10 | int fmx, smx, fmcnt; ll sum; 11 | }; 12 | 13 | data Merge(data A, data B){ 14 | data curr; 15 | 16 | curr.sum = A.sum + B.sum; 17 | curr.fmx = max(A.fmx, B.fmx); 18 | curr.smx = max(A.smx, B.smx); 19 | if(A.fmx != B.fmx) curr.smx = max(curr.smx, min(A.fmx, B.fmx)); 20 | 21 | curr.fmcnt = 0; 22 | if(curr.fmx == A.fmx) curr.fmcnt += A.fmcnt; 23 | if(curr.fmx == B.fmx) curr.fmcnt += B.fmcnt; 24 | return curr; 25 | } 26 | 27 | data tree[maxn*5]; 28 | #define Left (node * 2) 29 | #define Right ((node << 1) ^ 1) 30 | #define mid ((lo+hi) >> 1) 31 | 32 | void build(int node, int lo, int hi){ 33 | if (lo==hi) {tree[node] = {A[lo], -1, 1, A[lo]}; return;} 34 | build(Left,lo,mid); 35 | build(Right,mid+1,hi); 36 | tree[node] = Merge(tree[Left], tree[Right]); 37 | } 38 | 39 | void lazyPropagation(int node,int lo,int hi){ 40 | if(lo == hi) return; 41 | 42 | int val = tree[node].fmx; 43 | if(tree[Left].fmx > val){ 44 | tree[Left].sum -= (tree[Left].fmx - val) * 1LL * tree[Left].fmcnt; 45 | tree[Left].fmx = val; 46 | } 47 | 48 | if(tree[Right].fmx > val){ 49 | tree[Right].sum -= (tree[Right].fmx - val) * 1LL * tree[Right].fmcnt; 50 | tree[Right].fmx = val; 51 | } 52 | } 53 | 54 | void updateRange(int node, int lo, int hi, int i, int j, int val){ 55 | if(tree[node].fmx <= val) return; 56 | if(lo>=i && hi<=j && tree[node].smx < val){ 57 | tree[node].sum -= (tree[node].fmx - val) * 1LL * tree[node].fmcnt; 58 | tree[node].fmx = val; 59 | return; 60 | } 61 | if(lo == hi) return; 62 | 63 | lazyPropagation(node,lo,hi); 64 | if(i <= mid) updateRange(Left,lo,mid,i,j,val); 65 | if(j > mid) updateRange(Right,mid+1,hi,i,j,val); 66 | tree[node] = Merge(tree[Left], tree[Right]); 67 | } 68 | 69 | ll querySum(int node,int lo,int hi,int i,int j){ 70 | if(lo>=i && hi <= j) return tree[node].sum; 71 | 72 | ll ret = 0; 73 | lazyPropagation(node,lo,hi); 74 | if(i <= mid) ret += querySum(Left,lo,mid,i,j); 75 | if(j > mid) ret += querySum(Right,mid+1,hi,i,j); 76 | return ret; 77 | } 78 | 79 | int queryMax(int node,int lo,int hi,int i,int j){ 80 | if(lo>=i && hi <= j) return tree[node].fmx; 81 | 82 | int ret = -1; 83 | lazyPropagation(node,lo,hi); 84 | if(i <= mid) ret = max(ret, queryMax(Left,lo,mid,i,j)); 85 | if(j > mid) ret = max(ret, queryMax(Right,mid+1,hi,i,j)); 86 | return ret; 87 | } 88 | -------------------------------------------------------------------------------- /DS/Segment Tree/Segment Tree (2D).cpp: -------------------------------------------------------------------------------- 1 | // 2D Segment Tree 2 | // Memory Complexity : O(16nm) 3 | // Be careful writing lx, rx, ly, ry 4 | 5 | const int MAXN = 1030; 6 | int tree[4*MAXN][4*MAXN]; 7 | 8 | int n, m; 9 | void updateY(int ndx, int lx, int rx, int ndy, int ly, int ry, int y, int val) { 10 | if(ly == ry) { 11 | if(lx == rx) tree[ndx][ndy] = val; 12 | else tree[ndx][ndy] = tree[ndx*2][ndy] + tree[ndx*2+1][ndy]; 13 | return; 14 | } 15 | int mid = (ly + ry) >> 1; 16 | if(y <= mid) updateY(ndx, lx, rx, ndy*2, ly, mid, y, val); 17 | else updateY(ndx, lx, rx, ndy*2+1, mid+1, ry, y, val); 18 | tree[ndx][ndy] = tree[ndx][ndy*2] + tree[ndx][ndy*2+1]; 19 | } 20 | 21 | void updateX(int ndx, int lx, int rx, int x, int y, int val) { 22 | if(lx != rx) { 23 | int mid = (lx + rx) >> 1; 24 | if(x <= mid) updateX(ndx*2, lx, mid, x, y, val); 25 | else updateX(ndx*2+1, mid+1, rx, x,y, val); 26 | } 27 | updateY(ndx, lx, rx, 1, 1, m, y,val); 28 | } 29 | 30 | int queryY(int ndx, int ndy, int ly, int ry, int y1, int y2) { 31 | if(ry < y1 || ly > y2) return 0; 32 | if(y1 <= ly && ry <= y2) return tree[ndx][ndy]; 33 | 34 | int mid = (ly + ry) >> 1; 35 | return queryY(ndx, ndy*2, ly, mid, y1, y2) + queryY(ndx, ndy*2+1, mid+1, ry, y1, y2); 36 | } 37 | 38 | int queryX(int ndx, int lx, int rx, int x1, int y1, int x2, int y2) { 39 | if(rx < x1 || lx > x2) return 0; 40 | if(x1 <= lx && rx <= x2) return queryY(ndx, 1, 1, m, y1, y2); 41 | 42 | int mid = (lx + rx) >> 1; 43 | return queryX(ndx*2, lx, mid, x1,y1,x2,y2) + queryX(ndx*2+1, mid+1, rx, x1,y1,x2,y2); 44 | } 45 | -------------------------------------------------------------------------------- /DS/Segment Tree/Segment Tree (Iterative).cpp: -------------------------------------------------------------------------------- 1 | int n; 2 | int tree[MAX*2]; 3 | 4 | //point update, range query 5 | //initial elements at tree[n]....tree[2*n-1] 6 | void build(){ 7 | for(int i=n-1;i>=1;i--) 8 | tree[i]=max(tree[i<<1],tree[i<<1|1]); 9 | } 10 | 11 | void update(int p,int value){ 12 | for(tree[p+=n]=value; p>1; p>>=1) 13 | tree[p>>1]=max(tree[p],tree[p^1]); 14 | } 15 | 16 | //outputs max(l,r-1) 17 | int query(int l,int r){ 18 | int res=0; 19 | for(l+=n, r+=n; l>=1, r>>=1) { 20 | if(l&1) res=max(res,tree[l++]); 21 | if(r&1) res=max(res,tree[--r]); 22 | } 23 | return res; 24 | } 25 | -------------------------------------------------------------------------------- /DS/Segment Tree/Segment Tree (Persistent).cpp: -------------------------------------------------------------------------------- 1 | //Persistent Segment Tree 2 | struct node{ 3 | node *left,*right; int val; 4 | node(){val=0;left=NULL;right=NULL;} 5 | node(int a,node *b,node *c){val=a,left=b,right=c;} 6 | 7 | node *update(int lo,int hi,int i,int v){ 8 | node* ret = new node(val,left,right); 9 | 10 | if(lo==hi) {ret->val += v; return ret;} 11 | int mid=(lo+hi)/2; 12 | 13 | if(i<=mid){ 14 | if(!left) left = new node(); 15 | ret->left = left->update(lo,mid,i,v); 16 | } 17 | else{ 18 | if(!right) right = new node(); 19 | ret->right = right->update(mid+1,hi,i,v); 20 | } 21 | 22 | ret->val=0; 23 | if(ret->left) ret->val += ret->left->val; 24 | if(ret->right) ret->val += ret->right-> val; 25 | 26 | return ret; 27 | } 28 | 29 | int query(int lo,int hi,int i,int j) { 30 | if(hij) return 0; 31 | if(i<=lo && hi<=j) return val; 32 | int mid=(lo+hi)/2; 33 | 34 | int ret = 0; 35 | if(left) ret += left->query(lo,mid,i,j); 36 | if(right) ret += right->query(mid+1,hi,i,j); 37 | return ret; 38 | } 39 | }; 40 | 41 | inline int Val(node* x) {return x ? x->val : 0;} 42 | inline node* Left(node* x) {return x ? x->left : NULL;} 43 | inline node* Right(node* x) {return x ? x->right : NULL;} 44 | 45 | //Searching kth minimum element in sorted order 46 | int Search(node *a,node *b,node* c,node* d,int l,int r,int k) { 47 | if(l==r) return l; 48 | int Count=Val(Left(a))+Val(Left(b))-Val(Left(c))-Val(Left(d)); 49 | 50 | int mid=(l+r)/2; 51 | if(Count>=k) return Search(Left(a),Left(b),Left(c),Left(d),l,mid,k); 52 | else return Search(Right(a),Right(b),Right(c),Right(d),mid+1,r,k-Count); 53 | } 54 | 55 | void dfs(int u,int p,int d){ 56 | ...... 57 | root[u]=root[p]->update(1,Size,w[u],1); 58 | ...... 59 | } 60 | 61 | int main(){ 62 | ...... 63 | dfs(1,0,0); 64 | Size=Map.size(); //number of distinct elements after co-ordinate compression 65 | root[0]=new node(); 66 | ...... 67 | } 68 | -------------------------------------------------------------------------------- /DS/Segment Tree/Segment Tree (Recursive).cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAXN = 100005; 4 | 5 | int A[MAXN]; 6 | int tree[MAXN*5]; 7 | 8 | #define Left (node*2) 9 | #define Right (node*2+1) 10 | #define mid ((lo+hi)/2) 11 | 12 | void build(int node, int lo, int hi){ 13 | if (lo==hi) {tree[node] = A[lo]; return;} 14 | build(Left,lo,mid); 15 | build(Right,mid+1,hi); 16 | tree[node] = tree[Left] + tree[Right]; 17 | } 18 | 19 | int query(int node, int lo, int hi, int i, int j){ 20 | if (i>hi || j=i && hi<=j) return tree[node]; 22 | int p1 = query(Left,lo,mid,i,j); 23 | int p2 = query(Right,mid+1,hi,i,j); 24 | return p1 + p2; 25 | } 26 | 27 | void update(int node, int lo, int hi, int i, int val){ 28 | if (i>hi || ihi) return; 62 | else if(lo>j || hi=i && hi<=j) {lazy[node] += val; lazyPropagation(node,lo,hi); return;} 64 | updateRange(Left,lo,mid,i,j,val); 65 | updateRange(Right,mid+1,hi,i,j,val); 66 | tree[node] = tree[Left] + tree[Right]; 67 | } 68 | 69 | int queryRange(int node,int lo,int hi,int i,int j){ 70 | if(lo>hi) return 0; 71 | else if(lo>j || hi=i && hi <= j) return tree[node]; 74 | int p1 = queryRange(Left,lo,mid,i,j); 75 | int p2 = queryRange(Right,mid+1,hi,i,j); 76 | return p1 + p2; 77 | } 78 | -------------------------------------------------------------------------------- /DS/Segment Tree/Segment Tree (Sparse).cpp: -------------------------------------------------------------------------------- 1 | #define MAX 1000000005 2 | #define mid (lo+(hi-lo)/2) //Be careful about overflow 3 | 4 | struct item{ 5 | int value, lazy; 6 | item *Left, *Right ; 7 | item(){value=0; lazy=0; Left=Right=NULL;} 8 | }; 9 | item* root; 10 | 11 | int query(item* node, int lo, int hi, int i, int j){ 12 | if (!node || i>hi || j=i && hi<=j) return node->value; 14 | int p1=query(node->Left,lo,mid,i,j); 15 | int p2=query(node->Right,mid+1,hi,i,j); 16 | return p1+p2; 17 | } 18 | 19 | void update(item* node, int lo, int hi, int i, int val){ 20 | if (i>hi || ivalue=val; return;} 22 | if(lo!=hi && !node->Left) node->Left=new item(); 23 | if(lo!=hi && !node->Right) node->Right=new item(); 24 | 25 | update(node->Left,lo,mid,i,val); 26 | update(node->Right,mid+1,hi,i,val); 27 | node->value=node->Left->value + node->Right->value; 28 | } 29 | 30 | //lazy propagation 31 | void lazyPropagation(item* node,int lo,int hi){ 32 | if(node->lazy){ 33 | node->value+=(hi-lo+1)*node->lazy; 34 | if(lo != hi) {node->Left->lazy+=node->lazy; node->Right->lazy+=node->lazy;} 35 | node->lazy=0; 36 | } 37 | } 38 | 39 | void updateRange(item* node, int lo, int hi, int i, int j, ll val){ 40 | if(!node->Left) node->Left=new item(); 41 | if(!node->Right) node->Right=new item(); 42 | lazyPropagation(node,lo,hi); 43 | 44 | if(lo>hi) return; 45 | else if(lo>j || hi=i && hi<=j) {node->lazy+=val; lazyPropagation(node,lo,hi); return;} 47 | 48 | updateRange(node->Left,lo,mid,i,j,val); 49 | updateRange(node->Right,mid+1,hi,i,j,val); 50 | node->value=node->Left->value + node->Right->value; 51 | } 52 | 53 | ll queryRange(item* node,int lo,int hi,int i,int j){ 54 | if(lo>hi) return 0; 55 | else if(lo>j || hiLeft) node->Left=new item(); 58 | if(!node->Right) node->Right=new item(); 59 | lazyPropagation(node,lo,hi); 60 | 61 | if(lo>=i && hi <= j) return node->value; 62 | ll p1=queryRange(node->Left,lo,mid,i,j); 63 | ll p2=queryRange(node->Right,mid+1,hi,i,j); 64 | return p1+p2; 65 | } 66 | 67 | 68 | //Free each node of the tree after each test case 69 | void Free(item* node){ 70 | if(node->Left) Free(node->Left); 71 | if(node->Right) Free(node->Right); 72 | free(node); 73 | } 74 | 75 | int main() {root=new item();} 76 | -------------------------------------------------------------------------------- /DS/Segment Tree/Wavelet Tree.cpp: -------------------------------------------------------------------------------- 1 | //Tested : https://www.codechef.com/AUG19A/problems/CHGORAM 2 | 3 | #include 4 | using namespace std; 5 | 6 | struct WaveletTree{ 7 | int lo, hi; 8 | WaveletTree *l, *r; 9 | vector b; 10 | 11 | //from and to are array pointers 12 | //Build Wavelet Tree on A[from...to]; 13 | //x <= A[j] <= y, for each from <= j <= to 14 | //Warning : Changes the original array A 15 | WaveletTree(int *from, int *to, int x, int y){ 16 | lo = x, hi = y; 17 | if(lo == hi or from >= to) return; 18 | int mid = (lo+hi)/2; 19 | auto f = [mid](int x) {return x <= mid;}; 20 | 21 | b.reserve(to - from + 1); 22 | b.push_back(0); 23 | 24 | for(auto it = from; it != to; it++) 25 | b.push_back(b.back() + f(*it)); 26 | 27 | auto pivot = stable_partition(from, to, f); 28 | l = new WaveletTree(from, pivot, lo, mid); 29 | r = new WaveletTree(pivot, to, mid+1, hi); 30 | } 31 | 32 | //kth (1-indexed) smallest element in [l, r] 33 | int kth(int l, int r, int k){ 34 | if(l > r) return 0; 35 | if(lo == hi) return lo; 36 | int inLeft = b[r] - b[l-1]; 37 | int lb = b[l-1]; //amt of nos in first (l-1) nos that go in left 38 | int rb = b[r]; //amt of nos in first (r) nos that go in left 39 | if(k <= inLeft) return this->l->kth(lb+1, rb , k); 40 | return this->r->kth(l-lb, r-rb, k-inLeft); 41 | } 42 | 43 | //Count of numbers <= k in [l, r] 44 | int LTE(int l, int r, int k){ 45 | if(l > r or k < lo) return 0; 46 | if(hi <= k) return r - l + 1; 47 | int lb = b[l-1], rb = b[r]; 48 | return this->l->LTE(lb+1, rb, k) + this->r->LTE(l-lb, r-rb, k); 49 | } 50 | }; 51 | 52 | const int MAXN = 100005; 53 | const int MAXA = 1000005; 54 | int A[MAXN]; 55 | 56 | int main(){ 57 | int n; 58 | scanf("%d",&n); 59 | for(int i=1; i<=n; i++) scanf("%d",&A[i]); 60 | WaveletTree wt(A+1, A+n+1, 1, MAXA); 61 | } 62 | -------------------------------------------------------------------------------- /DS/Sliding RMQ.cpp: -------------------------------------------------------------------------------- 1 | //O(n) RMQ(Max) for all k-length subarrays of a n-length array using deque 2 | dequedq; 3 | int A[MAX]; 4 | int n,k; 5 | 6 | void solve(){ 7 | for(int i=1;i 2 | using namespace std; 3 | 4 | const int MAXN = 505; 5 | const int LOGN = 9; 6 | 7 | //O(n^2 (logn)^2 8 | //Supports Rectangular Query 9 | int A[MAXN][MAXN]; 10 | int M[MAXN][MAXN][LOGN][LOGN]; 11 | 12 | void Build2DSparse(int N){ 13 | for(int i = 1; i <= N; i++){ 14 | for(int j = 1; j <= N; j++){ 15 | M[i][j][0][0] = A[i][j]; 16 | } 17 | for(int q = 1; (1< 2 | using namespace std; 3 | 4 | const int MAXN = 1005; 5 | const int LOGN = 10; 6 | int A[MAXN][MAXN]; 7 | int M[MAXN][MAXN][LOGN]; 8 | 9 | //O(n^2 logn) 10 | //Supports Square Query 11 | void Build2DSparse(int n){ 12 | for(int k=0; (1< size : 0;} 20 | void upd_sz(pnode t) { if(t) t -> size = sz(t -> l) + 1 + sz(t -> r);} 21 | 22 | void push(pnode t) { 23 | if(!t) return; 24 | 25 | if(t->lazy){ 26 | t -> val += t -> lazy; 27 | t -> sum += t -> lazy * sz(t); 28 | if(t -> l) t -> l -> lazy += t -> lazy; 29 | if(t -> r) t -> r -> lazy += t -> lazy; 30 | t -> lazy = 0; 31 | } 32 | //Reverse 33 | if(t->rev){ 34 | swap(t->l,t->r); 35 | if(t -> l) t -> l -> rev ^= t -> rev; 36 | if(t -> r) t -> r -> rev ^= t -> rev; 37 | t -> rev = 0; 38 | } 39 | } 40 | 41 | void combine(pnode t) { 42 | // Note: This function should reset datas of t first (MUST!!) 43 | // Then update datas from l and r. 44 | if(!t) return; 45 | push(t -> l); 46 | push(t -> r); 47 | t -> sum = t -> val; // Reset 48 | if(t -> l) t -> sum += t -> l -> sum; 49 | if(t -> r) t -> sum += t -> r -> sum; 50 | } 51 | 52 | void split(pnode t, pnode &l, pnode &r, int pos, int add = 0) { 53 | if(!t) return void(l = r = NULL); 54 | push(t); 55 | int curr = sz(t -> l) + add; 56 | if(curr <= pos) 57 | split(t -> r, t -> r, r, pos, curr + 1), l = t; 58 | else split(t -> l, l, t -> l, pos, add), r = t; 59 | upd_sz(t); 60 | combine(t); 61 | } 62 | 63 | void merge(pnode &t, pnode l, pnode r) { 64 | push(l), push(r); 65 | if(!l || !r) 66 | t = l ? l : r; 67 | else if(l -> prior > r -> prior) 68 | merge(l -> r, l -> r, r), t = l; 69 | else merge(r -> l, l, r -> l), t = r; 70 | upd_sz(t); 71 | combine(t); 72 | } 73 | 74 | ll query(pnode t, int l, int r) { 75 | pnode L, mid, R; 76 | split(t, L, mid, l - 1); 77 | split(mid, t, R, r - l); 78 | ll ans = t -> sum; 79 | merge(mid, L, t); 80 | merge(t, mid, R); 81 | return ans; 82 | } 83 | 84 | void update(pnode t, int l, int r, ll v) { 85 | pnode L, mid, R; 86 | split(t, L, mid, l - 1); 87 | split(mid, t, R, r - l); 88 | t -> lazy += v; 89 | merge(mid, L, t); 90 | merge(t, mid, R); 91 | } 92 | 93 | void insert(pnode &t, int pos, int v) { 94 | pnode L, R, tmp, y = new node(v); 95 | split(t, L, R, pos - 1); 96 | merge(tmp, L, y); 97 | merge(t, tmp, R); 98 | } 99 | 100 | void Del(pnode &t, int pos) { 101 | pnode L, R, mid; 102 | split(t, L, mid, pos - 1); 103 | split(mid, t, R, 0); 104 | pnode tmp = t; 105 | merge(t, L, R); 106 | free(tmp); 107 | } 108 | 109 | void Reverse(pnode t, int l, int r) { 110 | pnode L, mid, R; 111 | split(t, L, mid, l - 1); 112 | split(mid, t, R, r - l); 113 | t -> rev ^= 1; 114 | merge(mid, L, t); 115 | merge(t, mid, R); 116 | } 117 | -------------------------------------------------------------------------------- /DS/Treap/Treap (Persistent).cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define MAX 1000005 5 | typedef long long ll; 6 | 7 | struct node{ 8 | int prior, size; 9 | ll val, sum; 10 | node *l, *r; 11 | node(int v = 0) { 12 | val = sum = v; 13 | prior = rand(); 14 | size = 1; 15 | l = r = NULL; 16 | } 17 | }; 18 | 19 | node* root[MAX]; 20 | typedef node* pnode; 21 | 22 | int sz(pnode t) {return t ? t -> size : 0;} 23 | void upd_sz(pnode t) {if(t) t -> size = sz(t -> l) + 1 + sz(t -> r);} 24 | 25 | void combine(pnode t) { 26 | // Note: This function should reset datas of t first (MUST!!) 27 | // Then update datas from l and r. 28 | if(!t) return; 29 | t -> sum = t -> val; // Reset 30 | if(t -> l) t -> sum += t -> l -> sum; 31 | if(t -> r) t -> sum += t -> r -> sum; 32 | } 33 | 34 | void split(pnode t, pnode &l, pnode &r, int pos, int add = 0) { 35 | if(!t) return void(l = r = NULL); 36 | node* cn = new node(); 37 | *cn = *t; 38 | 39 | int curr = sz(cn -> l) + add; 40 | if(curr <= pos) split(cn -> r, cn -> r, r, pos, curr + 1), l = cn; 41 | else split(cn -> l, l, cn -> l, pos, add), r = cn; 42 | 43 | upd_sz(cn); 44 | combine(cn); 45 | } 46 | 47 | void merge(pnode &t, pnode l, pnode r) { 48 | if(!l || !r) {t = l ? l : r; return;} 49 | node* cn = new node(); 50 | 51 | if(l -> prior > r -> prior) {*cn = *l; merge(cn -> r, cn -> r, r);} 52 | else {*cn = *r; merge(cn -> l, l, cn -> l);} 53 | t = cn; 54 | 55 | upd_sz(t); 56 | combine(t); 57 | } 58 | 59 | //Use pnode &t for non-persistent operation (will update original t) 60 | //Use pnode t for persistent operation (will not update the original one) 61 | //No need to merge back to retrieve the original node after split in persistent operation 62 | 63 | void insert(pnode &t, int pos, int v){ 64 | pnode L, R, tmp, y = new node(v); 65 | split(t, L, R, pos - 1); 66 | merge(tmp, L, y); 67 | merge(t, tmp, R); 68 | } 69 | 70 | void Replace(pnode &t,int x, int val){ 71 | pnode L, R, mid; 72 | split(t,L,mid,x); 73 | split(L,t,R,x-1); 74 | R->val = R->sum = val; 75 | merge(L,t,R); 76 | merge(t,L,mid); 77 | } 78 | 79 | ll Query(pnode t, int pos1, int pos2){ 80 | pnode L, R, mid, tmp; 81 | split(t, L, R, pos2); 82 | split(L, mid, tmp, pos1 - 1); 83 | return tmp->sum; 84 | } 85 | 86 | int main(){ 87 | int n; 88 | scanf("%d",&n); 89 | root[0]=new node(); 90 | 91 | int version=0; 92 | for(int i=1;i<=n;i++){//set A[version]=A[ID] and insert(pos,v) 93 | int tp; scanf("%d",&tp); 94 | if(tp==1){ 95 | int ID,pos,v; 96 | scanf("%d %d %d",&ID,&pos,&v); 97 | root[++version]=root[ID]; 98 | insert(root[version],pos,v); 99 | } 100 | else if(tp==2){//set A[ID][pos]=v; 101 | int ID,pos,v; 102 | scanf("%d %d %d",&ID,&pos,&v); 103 | Replace(root[ID],pos,v); 104 | } 105 | else if(tp==3){//print A[version] 106 | int ID; 107 | scanf("%d",&ID); 108 | for(int i=1;isize;i++) printf("%d ",Query(root[ID],i,i)); 109 | printf("\n"); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /DS/Trie/Trie (Basic).cpp: -------------------------------------------------------------------------------- 1 | //Space Complexity : O(Sum of |S_i|) 2 | 3 | const int LOG = 20; 4 | struct Trie{ 5 | struct Node{ 6 | Node* Child[2]; 7 | Node() {Child[0]=Child[1]=NULL;} 8 | }; 9 | Node* root; 10 | 11 | void Init() {root = new Node();} 12 | bool Check(int x,int b) {return (x>>b)&1;} 13 | 14 | void Insert(int n){ 15 | Node *Cur = root; 16 | for(int i = LOG-1; i>=0; i--){ 17 | bool ID = Check(n,i); 18 | if(!Cur->Child[ID]) Cur->Child[ID] = new Node(); 19 | Cur = Cur->Child[ID]; 20 | } 21 | } 22 | 23 | int MinQuery(int XOR){ 24 | int Ans = 0; 25 | Node *Cur = root; 26 | for(int i = LOG-1; i>=0; i--){ 27 | bool ID = Check(XOR,i); 28 | if(Cur->Child[ID]) Cur = Cur->Child[ID]; 29 | else Cur = Cur->Child[!ID], Ans += (1<>b)&1;} 13 | 14 | Node* Insert(int n){ 15 | Node *Old = root; 16 | Node *Cur = new Node(); 17 | Node* newRoot = Cur; 18 | 19 | for(int i = LOG-1; i>=0; i--){ 20 | bool ID = Check(n,i); 21 | if(Old && Old->Child[!ID]) Cur->Child[!ID] = Old->Child[!ID]; 22 | Cur->Child[ID] = new Node(); 23 | 24 | Cur = Cur->Child[ID]; 25 | if(Old) Old = Old->Child[ID]; 26 | } 27 | return newRoot; 28 | } 29 | 30 | int MinQuery(int XOR){ 31 | int Ans = 0; 32 | Node *Cur = root; 33 | for(int i = LOG-1; i>=0; i--){ 34 | bool ID = Check(XOR,i); 35 | 36 | if(Cur->Child[ID]) Cur = Cur->Child[ID]; 37 | else Cur = Cur->Child[!ID], Ans += (1< 3 | void debug_out(Head H, Tail... T) { 4 | cerr << " " << to_string(H); 5 | debug_out(T...); 6 | } 7 | #define debug(...) cerr << "Line : " << __LINE__ <<" [" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__) 8 | -------------------------------------------------------------------------------- /Game Theory/Green Hackenbush.cpp: -------------------------------------------------------------------------------- 1 | // Green Hackenbush 2 | // Description: 3 | // Consider a two player game on a graph with a specified vertex (root). 4 | // In each turn, a player eliminates one edge. 5 | // Then, if a subgraph that is disconnected from the root, it is removed. 6 | // If a player cannot select an edge (i.e., the graph is singleton), 7 | // he will lose. 8 | // 9 | // Compute the Grundy number of the given graph. 10 | // 11 | // Algorithm: 12 | // We use two principles: 13 | // 1. Colon Principle: Grundy number of a tree is the xor of 14 | // Grundy number of child subtrees. 15 | // (Proof: easy). 16 | // 17 | // 2. Fusion Principle: Consider a pair of adjacent vertices u, v 18 | // that has another path (i.e., they are in a cycle). Then, 19 | // we can contract u and v without changing Grundy number. 20 | // (Proof: difficult) 21 | // 22 | // We first decompose graph into two-edge connected components. 23 | // Then, by contracting each components by using Fusion Principle, 24 | // we obtain a tree (and many self loops) that has the same Grundy 25 | // number to the original graph. By using Colon Principle, we can 26 | // compute the Grundy number. 27 | // 28 | // Complexity: 29 | // O(m + n). 30 | // 31 | // Verified: 32 | // SPOJ 1477: Play with a Tree 33 | // IPSC 2003 G: Got Root? 34 | 35 | #define fst first 36 | #define snd second 37 | #define all(c) ((c).begin()), ((c).end()) 38 | struct hackenbush { 39 | int n; 40 | vector> adj; 41 | hackenbush(int n) : n(n), adj(n) { } 42 | void add_edge(int u, int v) { 43 | adj[u].push_back(v); 44 | if (u != v) adj[v].push_back(u); 45 | } 46 | // r is the only root connecting to the ground 47 | int grundy(int r) { 48 | vector num(n), low(n); 49 | int t = 0; 50 | function dfs = [&](int p, int u) { 51 | num[u] = low[u] = ++t; 52 | int ans = 0; 53 | for (int v : adj[u]) { 54 | if (v == p) { p += 2 * n; continue; } 55 | if (num[v] == 0) { 56 | int res = dfs(u, v); 57 | low[u] = min(low[u], low[v]); 58 | if (low[v] > num[u]) ans ^= (1 + res) ^ 1; // bridge 59 | else ans ^= res; // non bridge 60 | } else low[u] = min(low[u], num[v]); 61 | } 62 | if (p > n) p -= 2 * n; 63 | for (int v : adj[u]) 64 | if (v != p && num[u] <= num[v]) ans ^= 1; 65 | return ans; 66 | }; 67 | return dfs(-1, r); 68 | } 69 | }; 70 | 71 | int main() { 72 | int cases; scanf("%d", &cases); 73 | for (int icase = 0; icase < cases; ++icase) { 74 | int n; scanf("%d", &n); 75 | vector ground(n); 76 | int r; 77 | for (int i = 0; i < n; ++i) { 78 | scanf("%d", &ground[i]); 79 | if (ground[i] == 1) r = i; 80 | } 81 | int ans = 0; 82 | hackenbush g(n); 83 | for (int i = 0; i < n - 1; ++i) { 84 | int u, v; 85 | scanf("%d %d", &u, &v); 86 | --u; --v; 87 | if (ground[u]) u = r; 88 | if (ground[v]) v = r; 89 | if (u == v) ans ^= 1; 90 | else g.add_edge(u, v); 91 | } 92 | int res = ans ^ g.grundy(r); 93 | printf("%d\n", res != 0); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Game Theory/Red-Blue Hackenbush.cpp: -------------------------------------------------------------------------------- 1 | //Resources : http://www.geometer.org/mathcircles/hackenbush.pdf 2 | 3 | Lets say you are given a rooted tree and edges are coloured red and blue. 4 | Red player will cut red edges and blue player will cut blue edges. 5 | When a edge is cut, then the subtree under it is cut. Who will win? 6 | 7 | It can be solved by red-blue hacken bush. 8 | 9 | If the tree is a chain, then it's simple. 10 | Let cur = 1, and from root there are consecutive x blue/red edges. 11 | Then we add cur x times to our grundy val if the first edges are blue, 12 | otherwise minus cur x times if the first edges are red. And for every next edges 13 | we make cur = cur / 2 and add it to our grundy value depending on the edge colour. 14 | 15 | For a tree follow this pseudo-code: 16 | 17 | dfs(u): 18 | if(u == LEAF_NODE) return 0 19 | else: 20 | double grundy = 0 21 | 22 | for(all child v of u) 23 | double x = dfs(v) 24 | if(edge(u,v) is blue): 25 | y = smallest integer > 0 so that (x + y) > 1 26 | x = x + y 27 | y = 2 ^ (y - 1) 28 | grundy = grundy + (x / y) //Double Divison 29 | else: 30 | y = smallest integer > 0 so that (x - y) < -1 31 | x = x - y 32 | y = 2 ^ (y - 1) 33 | grundy = grundy + (x / y) //Double Divison 34 | return grundy 35 | 36 | If the grundy is positive, then blue wins 37 | if it's negetive red wins 38 | If it's 0, then the player who first moves lose. 39 | -------------------------------------------------------------------------------- /Geometry/Area of Union Of CIrcles.cpp: -------------------------------------------------------------------------------- 1 | // Problem ID : UVa 12056 2 | struct Range { 3 | double t; // -pi <= t <= pi 4 | int evt; 5 | Point p; 6 | Range() {} 7 | Range(double t, int evt, Point p) : t(t), evt(evt), p(p) {} 8 | 9 | bool operator <(const Range &s) const { 10 | return dcmp(t - s.t) < 0 || (dcmp(t - s.t) == 0 && evt > s.evt); 11 | } 12 | }; 13 | 14 | const int MAX = 1005; 15 | Circle C[MAX]; 16 | vectorR; 17 | 18 | bool cmp_r(const Circle &a, const Circle &b) {return a.r > b.r;} 19 | double AreaUnionCircle(Circle C[], int &n){ 20 | using namespace Vectorial; 21 | using namespace Circular; 22 | 23 | sort(C, C + n, cmp_r); 24 | int k = 0; 25 | for (int i = 0; i < n; i++){ 26 | if (dcmp(C[i].r) == 0) break; 27 | int j = 0; 28 | for (j = 0; j < k; j++) //interior or concentric 29 | if(getPos(C[i],C[j]) < 0 || !dcmp(getLength(C[i].o - C[j].o))) break; 30 | if (j == k) C[k++] = C[i]; 31 | } 32 | n = k; 33 | 34 | double ans = 0; 35 | for (int i = 0; i < n; ++ i){ 36 | int nc = 0; 37 | R.clear(); 38 | Point mpi = Point(- C[i].r, 0) + C[i].o; 39 | R.push_back(Range(-pi, 1, mpi)); 40 | R.push_back(Range( pi, -1, mpi)); 41 | 42 | for (int j = 0; j < n; ++ j){ 43 | if (j == i) continue; 44 | 45 | vectorsol; 46 | int ret = getCircleCircleIntersection(C[i],C[j],sol); 47 | if(ret<2) continue; 48 | 49 | Point a = sol[0]; Point b = sol[1]; 50 | double jR = getAngle(a - C[i].o), jL = getAngle(b - C[i].o); 51 | if (dcmp(jR - jL) > 0) ++ nc; 52 | R.push_back(Range(jR, 1, a)); 53 | R.push_back(Range(jL, -1, b)); 54 | } 55 | sort(R.begin(),R.end()); 56 | 57 | double pj = - pi; 58 | Point pp = mpi; 59 | for(Range rng : R){ 60 | nc += rng.evt; 61 | if((nc == 2 && rng.evt > 0) || nc == 0) 62 | ans += C[i].sector(rng.t - pj) + getCross(pp,rng.p) / 2; 63 | pj = rng.t; pp = rng.p; 64 | } 65 | } 66 | return ans; 67 | } 68 | -------------------------------------------------------------------------------- /Geometry/Integer Tricks.cpp: -------------------------------------------------------------------------------- 1 | // 1. Checks the relation between a/b and c/d, a, c >= 0, b, d > 0 2 | bool comp (ll a, ll b, ll c, ll d){ 3 | if(a / b != c / d) return a / b < c / d; 4 | a %= b, c %= d; 5 | if(c == 0) return 0; 6 | if(a == 0) return 1; 7 | return comp(d, c, b, a); 8 | } 9 | 10 | // 2. Sorting points based on polar angle 11 | bool sgn (Point p) {return p.y < 0 || (p.y == 0 && p.x < 0);} 12 | 13 | bool operator < (Point p, Point q) const{ 14 | if(sgn(p) != sgn(q)) return sgn(p) < sgn(q); 15 | return getCross(p, q) > 0; 16 | } 17 | 18 | // 3. Check whether Angle(a1, b1) < Angle(a2, b2) 19 | bool angleLess (Vector a1, Vector b1, Vector a2, Vector b2) { 20 | pt p1 ( getDot(a1, b1), abs(getCross(a1, b1)) ); 21 | pt p2 ( getDot(a2, b2), abs(getCross(a2, b2)) ); 22 | return getCross(p1, p2) > 0; 23 | } 24 | -------------------------------------------------------------------------------- /Geometry/IntegerGeo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define ll long long int 4 | inline ll dcmp(ll x) {return x;} 5 | 6 | struct Fraction{ 7 | ll m,n; 8 | Fraction(){} 9 | Fraction(ll x,ll y) {ll g=__gcd(x,y); m=x/g; n=y/g; if(n<0) {m=-m,n=-n;} } 10 | Fraction operator + (const Fraction& u) const {return Fraction(m*u.n+u.m*n,n*u.n); } 11 | Fraction operator - (const Fraction& u) const {return Fraction(m*u.n-u.m*n,n*u.n); } 12 | Fraction operator * (const Fraction& u) const {return Fraction(m*u.m,n*u.n); } 13 | Fraction operator / (const Fraction& u) const {return Fraction(m*u.n,n*u.m); } 14 | }; 15 | 16 | struct Point{ 17 | ll x, y; 18 | Point (ll x = 0, ll y = 0): x(x), y(y) {} 19 | 20 | bool operator == (const Point& u) const { return dcmp(x - u.x) == 0 && dcmp(y - u.y) == 0; } 21 | bool operator != (const Point& u) const { return !(*this == u); } 22 | bool operator < (const Point& u) const { return dcmp(x - u.x) < 0 || (dcmp(x-u.x)==0 && dcmp(y-u.y) < 0); } 23 | bool operator > (const Point& u) const { return u < *this; } 24 | bool operator <= (const Point& u) const { return *this < u || *this == u; } 25 | bool operator >= (const Point& u) const { return *this > u || *this == u; } 26 | Point operator + (const Point& u) { return Point(x + u.x, y + u.y); } 27 | Point operator - (const Point& u) { return Point(x - u.x, y - u.y); } 28 | Point operator * (const ll u) { return Point(x * u, y * u); } 29 | ll operator * (const Point& u) { return x*u.y - y*u.x; } 30 | }; 31 | typedef Point Vector; 32 | 33 | namespace Vectorial { 34 | ll getDot (Vector a, Vector b) { return a.x * b.x + a.y * b.y; } 35 | ll getCross (Vector a, Vector b) { return a.x * b.y - a.y * b.x; } 36 | ll getPLength (Vector a) { return getDot(a, a); } 37 | }; 38 | 39 | struct Line { 40 | ll a,b,c; 41 | Line(){} 42 | Line(ll x=0,ll y=0,ll z=0){ 43 | ll G=__gcd(x,y); //will equal gcd(x,y,z) 44 | a=x/G; b=y/G; c=z/G; 45 | if(a<0) {a=-a; b=-b; c=-c;} //a=0 case auto-handled 46 | } 47 | }; 48 | 49 | namespace Linear { 50 | using namespace Vectorial; 51 | 52 | bool getIntersection (Point p, Vector v, Point q, Vector w, Point& o) { 53 | if (dcmp(getCross(v, w)) == 0) return false; //parallel 54 | 55 | Vector u = p - q; 56 | ll cross1 = getCross(w, u); ll cross2 = getCross(v, w); 57 | ll g = __gcd(v.x,v.y); v.x/=g; v.y/=g; cross1 *= g; 58 | if(cross1 % cross2) return false; //intersection point non-integer 59 | 60 | ll k = cross1 / cross2; 61 | o = p + v * k; 62 | return true; 63 | } 64 | 65 | ll sign(ll x) {return x == 0 ? x : x/abs(x);} 66 | bool haveIntersection (Point a1, Point a2, Point b1, Point b2) { 67 | ll c1=getCross(a2-a1, b1-a1), c2=getCross(a2-a1, b2-a1), c3=getCross(b2-b1, a1-b1), c4=getCross(b2-b1,a2-b1); 68 | c1=sign(c1); c2=sign(c2); c3=sign(c3); c4=sign(c4); 69 | return dcmp(c1)*dcmp(c2) <= 0 && dcmp(c3)*dcmp(c4) <= 0; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Geometry/Radial Sweep.cpp: -------------------------------------------------------------------------------- 1 | #define ll long long int 2 | 3 | struct Point{ 4 | ll x; ll y; ll val; 5 | bool operator < (const Point& other) const { 6 | if(x * other.x > 0) return y*other.x < x*other.y; 7 | else return y*other.x > x*other.y; 8 | } 9 | }; 10 | Point p[MAX]; 11 | 12 | int main(){ 13 | int n; 14 | scanf("%d",&n); 15 | 16 | ll Plus=0, Minus=0; 17 | for(int i=1;i<=n;i++) cin>>p[i].x>>p[i].y>>p[i].val; 18 | 19 | //Precalculate w.r.t. Y-axis 20 | for(int i=1;i<=n;i++){ 21 | if(p[i].x>=0) Plus+=p[i].val; 22 | else Minus+=p[i].val; 23 | } 24 | sort(p+1,p+n+1); 25 | 26 | //Calculate w.r.t. all slopes 27 | for(int i=1;i<=n;i++){ 28 | if(p[i].x>=0) Plus-=p[i].val, Minus+=p[i].val; 29 | else Minus-=p[i].val, Plus+=p[i].val; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Geometry/RotationMatrix.cpp: -------------------------------------------------------------------------------- 1 | Translation Matrix : 2 | | 1 0 x | 3 | | 0 1 y | 4 | | 0 0 1 | 5 | 6 | Rotation Matrix : 7 | | cosθ -sinθ 1 | 8 | | sinθ cosθ 1 | 9 | | 0 0 1 | 10 | 11 | Rotate a Point Q by θ degrees counter-clockwise around the point P(x,y). 12 | | cosθ -sinθ x(1-cosθ) + ysinθ | 13 | | sinθ cosθ y(1-cosθ) - xsinθ | 14 | | 0 0 1 | 15 | -------------------------------------------------------------------------------- /Graph/Connectivity/ArticulationBridge.cpp: -------------------------------------------------------------------------------- 1 | #define MAX 100005 2 | #define f first 3 | #define s second 4 | int cnt; 5 | vector > graph(MAX); 6 | int d[MAX],md[MAX],vis[MAX]; 7 | map,int> bridges; 8 | int all_bridges(int now,int from) { 9 | d[now]=md[now]=cnt++; 10 | vis[now]=1; 11 | int i; 12 | for(i=0; id[now]) 20 | bridges[{min(now,graph[now][i]),max(now,graph[now][i])}]=1; 21 | } 22 | return md[now]; 23 | } 24 | -------------------------------------------------------------------------------- /Graph/Connectivity/ArticulationPoint.cpp: -------------------------------------------------------------------------------- 1 | #define MAX 100005 2 | #define f first 3 | #define s second 4 | int cnt, d[MAX],md[MAX],vis[MAX]; 5 | bool is_cutpoint[MAX]; 6 | vector > graph(MAX); 7 | int all_cutpoints(int now=0,int from=-1) { 8 | d[now]=md[now]=cnt++; 9 | vis[now]=1; 10 | int i,total_child=0,is_cut=0; 11 | for(i=0; i=d[now] ) is_cut=1; 20 | } 21 | if(from==-1 && total_child>=2)is_cutpoint[now]=true; 22 | else if(from!=-1 && is_cut) is_cutpoint[now]=true; 23 | else is_cutpoint[now]=false; 24 | return md[now]; 25 | } 26 | -------------------------------------------------------------------------------- /Graph/Connectivity/Block-CutVertexTree.cpp: -------------------------------------------------------------------------------- 1 | struct graph { 2 | int n; 3 | vector> adj; 4 | graph(int n) : n(n), adj(n) {} 5 | void add_edge(int u, int v) { 6 | adj[u].push_back(v); 7 | adj[v].push_back(u); 8 | } 9 | int add_node() { 10 | adj.push_back({}); 11 | return n++; 12 | } 13 | vector& operator[](int u) { 14 | return adj[u]; 15 | } 16 | }; 17 | 18 | int node_id[500005]; 19 | int comp_id[500005]; 20 | int art[500005]; 21 | // tree = block cut tree 22 | // return BCCs 23 | vector> biconnected_components(graph &adj,graph&tree ) { 24 | int n = adj.n; 25 | vector num(n), low(n), stk; 26 | vector> comps; 27 | function dfs = [&](int u, int p, int &t) { 28 | num[u] = low[u] = ++t; 29 | stk.push_back(u); 30 | for (int v : adj[u]) if (v != p) { 31 | if (!num[v]) { 32 | dfs(v, u, t); 33 | low[u] = min(low[u], low[v]); 34 | if (low[v] >= num[u]) { 35 | art[u] = (num[u] > 1 || num[v] > 2); 36 | comps.push_back({u}); 37 | while (comps.back().back() != v) 38 | comps.back().push_back(stk.back()),stk.pop_back(); 39 | } 40 | } else low[u] = min(low[u], num[v]); 41 | } 42 | }; 43 | for (int u = 0, t; u < n; ++u)if (!num[u]) dfs(u, -1, t = 0); 44 | for (int u = 0; u < n; ++u)if (art[u]) node_id[u] = tree.add_node(); 45 | int cmpi = 0; 46 | for (auto &comp : comps) { 47 | int node = tree.add_node(); 48 | comp_id[cmpi++]=node; 49 | for (int u : comp) 50 | if (!art[u]) node_id[u] = node; 51 | else tree.add_edge(node, node_id[u]); 52 | } 53 | return comps; 54 | } 55 | -------------------------------------------------------------------------------- /Graph/Connectivity/LinkCutTree(rooted).cpp: -------------------------------------------------------------------------------- 1 | struct Node{ 2 | ll sz, label, w ; 3 | Node *p, *pp, *l, *r; 4 | Node() { p = pp = l = r = 0; } 5 | }; 6 | void update(Node *x){ 7 | x->sz = x->w; 8 | if(x->l) x->sz += x->l->sz; 9 | if(x->r) x->sz += x->r->sz; 10 | } 11 | void rotr(Node *x){ 12 | Node *y, *z; 13 | y = x->p, z = y->p; 14 | if((y->l = x->r)) y->l->p = y; 15 | x->r = y, y->p = x; 16 | if((x->p = z)){ 17 | if(y == z->l) z->l = x; 18 | else z->r = x; 19 | } 20 | x->pp = y->pp; 21 | y->pp = 0; 22 | update(y); 23 | } 24 | 25 | void rotl(Node *x){ 26 | Node *y, *z; 27 | y = x->p, z = y->p; 28 | if((y->r = x->l)) y->r->p = y; 29 | x->l = y, y->p = x; 30 | if((x->p = z)){ 31 | if(y == z->l) z->l = x; 32 | else z->r = x; 33 | } 34 | x->pp = y->pp; 35 | y->pp = 0; 36 | update(y); 37 | } 38 | 39 | void splay(Node *x){ 40 | Node *y, *z; 41 | while(x->p){ 42 | y = x->p; 43 | if(y->p == 0){ 44 | if(x == y->l) rotr(x); 45 | else rotl(x); 46 | } 47 | else{ 48 | z = y->p; 49 | if(y == z->l){ 50 | if(x == y->l) rotr(y), rotr(x); 51 | else rotl(x), rotr(x); 52 | } 53 | else 54 | { 55 | if(x == y->r) rotl(y), rotl(x); 56 | else rotr(x), rotl(x); 57 | } 58 | } 59 | } 60 | update(x); 61 | } 62 | 63 | Node *access(Node *x){ 64 | splay(x); 65 | if(x->r){ 66 | x->r->pp = x; 67 | x->r->p = 0; 68 | x->r = 0; 69 | update(x); 70 | } 71 | 72 | Node *last = x; 73 | while(x->pp) { 74 | Node *y = x->pp; 75 | last = y; 76 | splay(y); 77 | if(y->r){ 78 | y->r->pp = y; 79 | y->r->p = 0; 80 | } 81 | y->r = x; 82 | x->p = y; 83 | x->pp = 0; 84 | update(y); 85 | splay(x); 86 | } 87 | return last; 88 | } 89 | 90 | Node *root(Node *x){ 91 | access(x); 92 | while(x->l) x = x->l; 93 | splay(x); 94 | return x; 95 | } 96 | 97 | void cut(Node *x){ 98 | access(x); 99 | x->l->p = 0; 100 | x->l = 0; 101 | update(x); 102 | } 103 | 104 | void link(Node *x, Node *y){ 105 | access(x); 106 | access(y); 107 | x->l = y; 108 | y->p = x; 109 | update(x); 110 | } 111 | 112 | Node *lca(Node *x, Node *y){ 113 | access(x); 114 | return access(y); 115 | } 116 | 117 | ll depth(Node *x){ 118 | access(x); 119 | return x->sz; 120 | } 121 | 122 | class LinkCut{ 123 | Node *x; 124 | 125 | public: 126 | void initLinkCut(ll n,ll *vat){ 127 | x = new Node[n+1]; 128 | for(ll i = 1; i <= n; i++){ 129 | x[i].label = i; 130 | x[i].w = vat[i]; 131 | update(&x[i]); 132 | } 133 | } 134 | virtual ~LinkCut(){ delete[] x;} 135 | //parent[u]=v. 136 | void link(ll u, ll v){ ::link(&x[u], &x[v]);} 137 | 138 | void cut(ll u){ ::cut(&x[u]);} 139 | 140 | ll root(ll u){ return ::root(&x[u])->label;} 141 | 142 | ll depth(ll u){ return ::depth(&x[u]);} 143 | 144 | ll lca(ll u, ll v){ return ::lca(&x[u], &x[v])->label;} 145 | }; 146 | -------------------------------------------------------------------------------- /Graph/Connectivity/LinkCutTree.cpp: -------------------------------------------------------------------------------- 1 | // can be used as online minimum spanning tree 2 | // dynamic add edge & cut edge 3 | // check the size of connected component 4 | // check whether two node is connected 5 | const int MAXN = 100005; 6 | const int MAXM = 300005; 7 | 8 | struct node { 9 | node *l, *r, *p, *m; int f, v, w, s, id; 10 | node(int v, int w, int id) : l(), r(), p(), 11 | m(this), f(), v(v), w(w), s(w), id(id) {} 12 | }; 13 | 14 | inline bool is_root(node *n){return n->p==NULL||n->p->l!=n&&n->p->r!=n;} 15 | inline bool left(node *n){return n == n -> p -> l;} 16 | inline int sum(node *n){return n ? n -> s : 0;} 17 | inline node* max(node *n){return n ? n -> m : NULL;} 18 | inline node* max(node *a, node *b) { 19 | if(a == NULL || b == NULL) return a ? a : b; 20 | return a -> v > b -> v ? a : b; 21 | } 22 | inline void push(node *n) { 23 | if(!n -> f) return;n -> f = 0;swap(n -> l, n -> r); 24 | if(n -> l) n -> l -> f ^= 1;if(n -> r) n -> r -> f ^= 1; 25 | } 26 | inline void pull(node *n) { 27 | n -> m = max(max(max(n -> l), max(n -> r)), n); 28 | n -> s = sum(n -> l) + sum(n -> r) + n -> w; 29 | } 30 | inline void connect(node *n, node *p, bool l) { 31 | (l ? p -> l : p -> r) = n; if(n) n -> p = p; 32 | } 33 | inline void rotate(node *n) { 34 | node *p = n -> p, *g = p -> p; bool l = left(n); 35 | connect(l ? n -> r : n -> l, p, l); 36 | if(!is_root(p)) connect(n, g, left(p)); else n -> p = g; 37 | connect(p, n, !l);pull(p), pull(n); 38 | } 39 | inline void splay(node *n) { 40 | while(!is_root(n)) { 41 | node *p = n -> p; 42 | if(!is_root(p)) push(p -> p); 43 | push(p), push(n); 44 | if(!is_root(p)) rotate(left(n) ^ left(p) ? n : p); 45 | rotate(n); 46 | } 47 | push(n); 48 | } 49 | inline void expose(node *n) { 50 | node *last = NULL; 51 | for(node *m = n; m; m = m -> p) { 52 | splay(m); 53 | m -> w -= sum(last); m -> w += sum(m -> r); 54 | m -> r = last; last = m; pull(m); 55 | } 56 | splay(n); 57 | } 58 | inline void evert(node *n){expose(n);n -> f ^= 1;} 59 | inline void link(node *m,node *n){evert(m);expose(n);m->p=n;n->w+=sum(m);} 60 | inline void cut(node *m,node *n){evert(m);expose(n);n->l=n->l->p=NULL;} 61 | inline node* path_max(node *m,node *n){evert(m);expose(n);return n->m;} 62 | inline int size(node *n){evert(n);return sum(n);} 63 | bool connected(node *m,node *n){expose(m);expose(n);return m->p!=NULL;} 64 | struct edge { 65 | int a, b, w, id; 66 | bool operator<(const edge e) const {return w != e.w ? w > e.w : id > e.id;} 67 | }; 68 | int n, m, o; 69 | node *v[MAXN],*ev[MAXM]; 70 | vector ed; 71 | set s; 72 | void delete_edge(edge e){cut(v[e.a],ev[e.id]);cut(v[e.b],ev[e.id]);} 73 | void add_edge(edge e) {link(v[e.a],ev[e.id]);link(v[e.b],ev[e.id]);} 74 | void new_edge(int a, int b, int w) { 75 | int id = ed.size(); 76 | edge e = {a, b, w, id}; 77 | ed.push_back(e); 78 | ev[id] = new node(w, 0, id); 79 | if(connected(v[a], v[b])) { 80 | node* m = path_max(v[a], v[b]); 81 | if(m -> v <= w) return; 82 | delete_edge(ed[m -> id]); 83 | s.erase(ed[m -> id]); 84 | } 85 | add_edge(e); 86 | s.insert(e); 87 | } 88 | void init(){for(int i=1;i<=n;i++){v[i]=new node(0,1,-i);}} 89 | 90 | -------------------------------------------------------------------------------- /Graph/Flow/Dinic.cpp: -------------------------------------------------------------------------------- 1 | const int MAXN = 5000+5 ; 2 | typedef long long T; 3 | const T INF = 1e15 ; 4 | const T eps = 0; 5 | struct edge { 6 | int a, b; 7 | T cap,flow; 8 | int yo, x, y; 9 | }; 10 | struct Dinic { 11 | int s,t,d[MAXN], ptr[MAXN] ; 12 | vectore; 13 | vectorg[MAXN]; 14 | void init() { 15 | e.clear(); 16 | memset(d,0,sizeof(d)); 17 | for(int i = 0; i < MAXN ; i++)g[i].clear(); 18 | } 19 | void addEdge(int a,int b,T cap, int x = -1, int y= -1) { 20 | edge e1 = { a, b, cap, 0, 1, x, y } ; 21 | edge e2 = { b, a, 0, 0, 0, x, y } ; 22 | g[a].push_back((int)e.size()); 23 | e.push_back(e1); 24 | g[b].push_back((int)e.size()); 25 | e.push_back(e2); 26 | } 27 | bool bfs() { 28 | queue < int > Q ; 29 | Q.push(s); 30 | memset(d,-1,sizeof(d)); 31 | d[s]=0 ; 32 | while (!Q.empty()) { 33 | int u=Q.front() ; 34 | Q.pop() ; 35 | for(int i=0; ieps) { 57 | e [id].flow+=pushed ; 58 | e [id^1].flow-=pushed ; 59 | return pushed ; 60 | } 61 | } 62 | return 0 ; 63 | } 64 | T dinic() { 65 | T flow = 0 ; 66 | while(true) { 67 | if(!bfs()) break ; 68 | memset(ptr, 0, sizeof(ptr)) ; 69 | while (true){ 70 | T pushed = dfs(s,INF ); 71 | if(pushed<=eps)break; 72 | flow += pushed ; 73 | } 74 | } 75 | return flow ; 76 | } 77 | }; 78 | -------------------------------------------------------------------------------- /Graph/Flow/GlobalMinCut.cpp: -------------------------------------------------------------------------------- 1 | //Global Mincut ( stoer Wagner N^3) 2 | typedef long long ll; 3 | const ll maxN = 305 ; 4 | const ll inf = 0x3f3f3f3f ; 5 | // Stoer-wagner algorithm, complexity: O(n^3) 6 | // compute the global minimum cut with self-loop ignored. 7 | ll n,m, g[maxN][maxN];//1-indexed,initialised with 0 8 | bool vis[maxN]; 9 | ll dis[maxN],v[maxN]; 10 | ll stoer_wagner() { 11 | ll i, j, now,ans=inf; 12 | for(i=0; i1) { 14 | for(now=0,i=1; iedgs; // original graph 6 | 7 | void clear(){edgs.clear();} 8 | void add_edge(int s,int e,int x) { 9 | edgs.push_back({s,e,x}); 10 | } 11 | #define maxn 1000 12 | bool vis[maxn]; 13 | void dfs(int x) { 14 | if(vis[x])return; 15 | vis[x]=1; 16 | for(auto&i:dinic.g[x]) { 17 | if(dinic.e[i].cap-dinic.e[i].flow>0) 18 | dfs(dinic.e[i].b); 19 | } 20 | } 21 | vector >solve(int n) { 22 | vector >ret(n); 23 | for(int i=1; i gph[MAXN]; 9 | void clear() { 10 | for(int i=0; i 0 && dist[k.pos] > dist[j] + k.cost) { 29 | dist[k.pos] = dist[j] + k.cost; 30 | par[k.pos] = j; 31 | pae[k.pos] = idx; 32 | if(i == n) { 33 | upd = j; 34 | while(!mark[upd]) { 35 | mark[upd] = 1; 36 | upd = par[upd]; 37 | } 38 | return upd; 39 | } 40 | } 41 | idx++; 42 | } 43 | } 44 | } 45 | 46 | return -1; 47 | } 48 | typedef pair pi ; 49 | T match(int n) { 50 | int rt = -1; 51 | T ans = 0; 52 | while(~(rt = negative_cycle(n))) { 53 | bool mark[MAXN] = {}; 54 | vector cyc; 55 | while(!mark[rt]) { 56 | cyc.push_back(pi(par[rt], pae[rt])); 57 | mark[rt] = 1; 58 | rt = par[rt]; 59 | } 60 | reverse(cyc.begin(), cyc.end()); 61 | int capv = 1e9; 62 | for(auto &i : cyc) { 63 | auto e = &gph[i.first][i.second]; 64 | capv = min(capv, e->cap); 65 | } 66 | for(auto &i : cyc) { 67 | auto e = &gph[i.first][i.second]; 68 | e->cap -= capv; 69 | gph[e->pos][e->rev].cap += capv; 70 | ans += e->cost * capv; 71 | } 72 | } 73 | return ans; 74 | } 75 | } circ; 76 | //call circ.match(n+1) 77 | -------------------------------------------------------------------------------- /Graph/Matching/Bipartite Matching (Hopcroft Karp).cpp: -------------------------------------------------------------------------------- 1 | #define mset0(x) memset(x,0,sizeof(x)) 2 | const int maxN = 50000 ; 3 | const int maxM = 50000 ; 4 | struct HopcroftKarp { 5 | int vis[maxN], level[maxN], ml[maxN], mr[maxM]; 6 | vector edge[maxN]; // constructing edges for left part only 7 | void init(int n) { 8 | for (int i = 1; i <= n; ++i) edge[i].clear(); 9 | } 10 | void add(int u, int v) { 11 | edge[u].push_back(v); 12 | } 13 | bool dfs(int u) { 14 | vis[u] = true; 15 | for (vector::iterator it = edge[u].begin(); it != edge[u].end(); ++it) { 16 | int v = mr[*it]; 17 | if (v == -1 || (!vis[v] && level[u] < level[v] && dfs(v))) { 18 | ml[u] = *it; 19 | mr[*it] = u; 20 | return true; 21 | } 22 | } 23 | return false; 24 | } 25 | int matching(int n) { // n for left 26 | mset0(vis); 27 | mset0(level); 28 | memset(ml, -1,sizeof(ml)); 29 | memset(mr, -1,sizeof(mr)); 30 | for (int match = 0;;) { 31 | queue que; 32 | for (int i = 1; i <= n; ++i) { 33 | if (ml[i] == -1) { 34 | level[i] = 0; 35 | que.push(i); 36 | } else level[i] = -1; 37 | } 38 | while (!que.empty()) { 39 | int u = que.front(); 40 | que.pop(); 41 | for (vector::iterator it = edge[u].begin(); it != edge[u].end(); ++it) { 42 | int v = mr[*it]; 43 | if (v != -1 && level[v] < 0) { 44 | level[v] = level[u] + 1; 45 | que.push(v); 46 | } 47 | } 48 | } 49 | for (int i = 1; i <= n; ++i) vis[i] = false; 50 | int d = 0; 51 | for (int i = 1; i <= n; ++i) if (ml[i] == -1 && dfs(i)) ++d; 52 | if (d == 0) return match; 53 | match += d; 54 | } 55 | } 56 | }; 57 | -------------------------------------------------------------------------------- /Graph/Matching/Bipartite Matching(Kuhn).cpp: -------------------------------------------------------------------------------- 1 | class KuhnBPM{ 2 | public: 3 | int n, k; 4 | vector < vector > g; 5 | vector pairs_of_right, pairs_of_left; 6 | vector used; 7 | bool kuhn (int v) { 8 | if (used[v]) return false; 9 | used[v] = true; 10 | for (int i = 0; i < g[v].size(); ++i) { 11 | int to = g[v][i]; 12 | if (pairs_of_right[to] == -1 || kuhn (pairs_of_right[to])) { 13 | pairs_of_right[to] = v; 14 | pairs_of_left[v] = to; 15 | return true; 16 | } 17 | } 18 | return false; 19 | } 20 | int find_max_matching(vector > &_g, int _n, int _k) { 21 | g = _g; 22 | n = _n; //n is number of vertices in left part of graph 23 | k = _k; //k is number of vertices in right part of graph 24 | pairs_of_right = vector (k, -1); 25 | pairs_of_left = vector (n, -1); 26 | //pairs_of_right[i] is a neighbor of vertex i from right part, on marked edge 27 | //pairs_of_left[i] is a neighbor of vertex i from left part, on marked edge 28 | used = vector (n, false); 29 | bool path_found; 30 | do { 31 | fill(used.begin(), used.end(), false); 32 | path_found = false; 33 | //remember to start only from free vertices which are not visited yet 34 | for (int i = 0; i < n; ++i) 35 | if (pairs_of_left[i] < 0 && !used[i]) path_found |= kuhn (i); 36 | } while (path_found); 37 | int res = 0 ; 38 | for(int i = 0; i < k; i++) if(pairs_of_right[i] != -1) res++ ; 39 | return res; 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /Graph/Matching/General Matching (Edmonds Blossom ).cpp: -------------------------------------------------------------------------------- 1 | //complexity EV^2,0-indexed 2 | const int maxn=250; 3 | struct Edge{int to,next;}edge[maxn*maxn]; 4 | int Adj[maxn],Size; 5 | void init(){memset(Adj,-1,sizeof(Adj)); Size=0;} 6 | void add_edge(int u,int v){ 7 | edge[Size].to=v; edge[Size].next=Adj[u]; Adj[u]=Size++; 8 | } 9 | int n,Match[maxn]; 10 | bool G[maxn][maxn]; 11 | int Start,Finish,NewBase,Father[maxn],Base[maxn]; 12 | bool InQueue[maxn],InPath[maxn],InBlossom[maxn]; 13 | int Count; 14 | queue q; 15 | int FindCommonAncestor(int u,int v){ 16 | memset(InPath,false,sizeof(InPath)); 17 | while(true){ 18 | u=Base[u];InPath[u]=true; 19 | if(u==Start) break; 20 | u=Father[Match[u]]; 21 | } 22 | while(true){ 23 | v=Base[v]; 24 | if(InPath[v]) break; 25 | v=Father[Match[v]]; 26 | } 27 | return v; 28 | } 29 | void ResetTrace(int u){ 30 | int v; 31 | while(Base[u]!=NewBase){ 32 | v=Match[u]; 33 | InBlossom[Base[u]]=InBlossom[Base[v]]=true; 34 | u=Father[v]; 35 | if(Base[u]!=NewBase) Father[u]=v; 36 | } 37 | } 38 | void BlosomContract(int u,int v){ 39 | NewBase=FindCommonAncestor(u,v); 40 | memset(InBlossom,false,sizeof(InBlossom)); 41 | ResetTrace(u);ResetTrace(v); 42 | if(Base[u]!=NewBase) Father[u]=v; 43 | if(Base[v]!=NewBase) Father[v]=u; 44 | for(int tu=1;tu<=n;tu++){ 45 | if(InBlossom[Base[tu]]){ 46 | Base[tu]=NewBase; 47 | if(!InQueue[tu]){ 48 | q.push(tu); 49 | InQueue[tu]=true; 50 | } 51 | } 52 | } 53 | } 54 | void FindAugmentingPath(){ 55 | memset(InQueue,false,sizeof(InQueue)); 56 | memset(Father,0,sizeof(Father)); 57 | for(int i=1;i<=n;i++)Base[i]=i; 58 | while(!q.empty()) q.pop(); 59 | q.push(Start); InQueue[Start]=true; 60 | Finish=0; 61 | while(!q.empty()){ 62 | int u=q.front(); //InQueue[u]=false; 63 | q.pop(); 64 | for(int i=Adj[u];~i;i=edge[i].next){ 65 | int v=edge[i].to; 66 | if((Base[u]!=Base[v])&&Match[u]!=v){ 67 | if(v==Start||(Match[v]>0&&Father[Match[v]]>0)) 68 | BlosomContract(u,v); 69 | else if(Father[v]==0){ 70 | Father[v]=u; 71 | if(Match[v]>0){ 72 | q.push(Match[v]); 73 | InQueue[Match[v]]=true; 74 | } 75 | else{ 76 | Finish=v; 77 | return ; 78 | } 79 | } 80 | } 81 | } 82 | } 83 | } 84 | void AugmentPath(){ 85 | int u,v,w;u=Finish; 86 | while(u>0){ 87 | v=Father[u]; w=Match[v]; 88 | Match[v]=u;Match[u]=v;u=w; 89 | } 90 | } 91 | void Edmonds(){ 92 | memset(Match,0,sizeof(Match)); 93 | for(int u=1;u<=n;u++){ 94 | if(Match[u]==0){ 95 | Start=u; 96 | FindAugmentingPath(); 97 | if(Finish>0) AugmentPath(); 98 | } 99 | } 100 | } 101 | void PrintMatch(){ 102 | Count=0; 103 | for(int i=1;i<=n;i++)if(Match[i])Count++; 104 | printf("%d\n",Count); 105 | for(int u=1;u<=n;u++)if(u q; 4 | int future_wife[maxn],future_husband[maxn], 5 | order[maxn][maxn],perfer[maxn][maxn],nextt[maxn]; 6 | //order[i][j]=indexOfMan i in j-th women'sListOfPreference 7 | //prefer[i]=listOfWomen inOrderOf decreasingPreference 8 | void enage(int man,int woman) { 9 | int m1=future_husband[woman]; 10 | if(m1==0) { 11 | future_husband[woman]=man; 12 | future_wife[man]=woman; 13 | } else { 14 | future_wife[m1]=0; 15 | future_husband[woman]=man; 16 | future_wife[man]=woman; 17 | q.push(m1); 18 | } 19 | } 20 | void stableMarriage() { 21 | while(!q.empty())q.pop(); 22 | int n,x;scanf("%d",&n); 23 | for(int i=1; i<=n; i++) { 24 | for(int j=1; j<=n; j++) 25 | scanf("%d",&perfer[i][j]); 26 | nextt[i]=1;q.push(i);future_wife[i]=0; 27 | } 28 | for(int i=1; i<=n; i++) { 29 | for(int j=1; j<=n; j++) 30 | scanf("%d",&x),order[i][x]=j; 31 | future_husband[i]=0; 32 | } 33 | while(!q.empty()) { 34 | int man=q.front();q.pop(); 35 | int woman=perfer[man][nextt[man]++]; 36 | if(future_husband[woman]==0)enage(man,woman); 37 | else if(order[woman][man]> 1) 5 | #define clr(ar) memset(ar, 0, sizeof(ar)) 6 | #define ran(a, b) ((((rand() << 15) ^ rand()) % ((b) - (a) + 1)) + (a)) 7 | namespace wm{ /// hash = 581023 8 | bool visited[MAX]; 9 | int U[MAX], V[MAX], P[MAX], way[MAX], minv[MAX], match[MAX], ar[MAX][MAX]; 10 | 11 | /// n = number of row and m = number of columns in 1 based, flag = MAXIMIZE or MINIMIZE 12 | /// match[i] contains the column to which row i is matched 13 | int hungarian(int n, int m, int mat[MAX][MAX], int flag){ 14 | clr(U), clr(V), clr(P), clr(ar), clr(way); 15 | 16 | for (int i = 1; i <= n; i++){ 17 | for (int j = 1; j <= m; j++){ 18 | ar[i][j] = mat[i][j]; 19 | if (flag == MAXIMIZE) ar[i][j] = -ar[i][j]; 20 | } 21 | } 22 | if (n > m) m = n; 23 | 24 | int i, j, a, b, c, d, r, w; 25 | for (i = 1; i <= n; i++){ 26 | P[0] = i, b = 0; 27 | for (j = 0; j <= m; j++) minv[j] = inf, visited[j] = false; 28 | 29 | do{ 30 | visited[b] = true; 31 | a = P[b], d = 0, w = inf; 32 | 33 | for (j = 1; j <= m; j++){ 34 | if (!visited[j]){ 35 | r = ar[a][j] - U[a] - V[j]; 36 | if (r < minv[j]) minv[j] = r, way[j] = b; 37 | if (minv[j] < w) w = minv[j], d = j; 38 | } 39 | } 40 | 41 | for (j = 0; j <= m; j++){ 42 | if (visited[j]) U[P[j]] += w, V[j] -= w; 43 | else minv[j] -= w; 44 | } 45 | b = d; 46 | } while (P[b] != 0); 47 | 48 | do{ 49 | d = way[b]; 50 | P[b] = P[d], b = d; 51 | } while (b != 0); 52 | } 53 | for (j = 1; j <= m; j++) match[P[j]] = j; 54 | 55 | return (flag == MINIMIZE) ? -V[0] : V[0]; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Graph/Matching/Weighted Bipartite Matching2(Hungarian).cpp: -------------------------------------------------------------------------------- 1 | typedef long long ll; 2 | #define MAX 105 3 | #define maxM 107 4 | #define maxN 107 5 | const ll inf = 1e12+7; 6 | template 7 | struct KuhnMunkras { // n for left, m for right 8 | int n, m, match[maxM]; 9 | T g[maxN][maxM], lx[maxN], ly[maxM], slack[maxM]; 10 | bool vx[maxN], vy[maxM]; 11 | void init(int n_, int m_) { 12 | n = n_, m = m_; 13 | for(int i=1;i<=n;i++) 14 | for(int j=1;j<=m;j++) 15 | g[i][j]=-inf; 16 | } 17 | void add(int u, int v, T w) { 18 | g[u][v] = w; 19 | } 20 | bool find(int x) { 21 | vx[x] = true; 22 | for (int y = 1; y <= m; ++y) { 23 | if (!vy[y]) { 24 | T delta = lx[x] + ly[y] - g[x][y]; 25 | if (delta== T(0)) { 26 | vy[y] = true; 27 | if (match[y] == 0 || find(match[y])) { 28 | match[y] = x; 29 | return true; 30 | } 31 | } else slack[y] = min(slack[y], delta); 32 | } 33 | } 34 | return false; 35 | } 36 | pair matching() { // maximum weight matching 37 | fill(lx + 1, lx + 1 + n, 0); 38 | memset(ly,0,sizeof(ly)); memset(match,0,sizeof(match)); 39 | for (int i = 1; i <= n; ++i) { 40 | for (int j = 1; j <= m; ++j) lx[i] = max(lx[i], g[i][j]); 41 | } 42 | for (int k = 1; k <= n; ++k) { 43 | fill(slack + 1, slack + 1 + m, numeric_limits::max()); 44 | while (true) { 45 | memset(vx,0,sizeof(vx)); memset(vy,0,sizeof(vy)); 46 | if (find(k)) break; 47 | else { 48 | T delta = numeric_limits::max(); 49 | for (int i = 1; i <= m; ++i) { 50 | if (!vy[i]) delta = min(delta, slack[i]); 51 | } 52 | for (int i = 1; i <= n; ++i) { 53 | if (vx[i]) lx[i] -= delta; 54 | } 55 | for (int i = 1; i <= m; ++i) { 56 | if (vy[i]) ly[i] += delta; 57 | if (!vy[i]) slack[i] -= delta; 58 | } 59 | } 60 | } 61 | } 62 | T resultCost = 0; 63 | T resultMatch = 0; 64 | for (int i = 1; i <= n; ++i) resultCost += lx[i]; 65 | for (int i = 1; i <= m; ++i) resultCost += ly[i]; 66 | for (int i = 1; i <= m; i++){ 67 | if(g[match[i]][i]>-inf) 68 | resultMatch++; 69 | else resultCost+=inf; 70 | } 71 | return {resultCost,resultMatch}; 72 | } 73 | }; 74 | -------------------------------------------------------------------------------- /Graph/Matching/Weighted General Matching.cpp: -------------------------------------------------------------------------------- 1 | //*for only perfect matching 2 | struct MinimumWeightedMatching { 3 | static const int MN = 105 ; 4 | int n, edge[MN][MN]; 5 | int match[MN],dis[MN],onstk[MN] ; 6 | vectorstk; 7 | void init(int _n) { 8 | n=_n; 9 | for(int i=0; idis[u]-edge[v][m]+edge[u][v]) { 24 | dis[m]=dis[u]-edge[v][m]+edge[u][v]; 25 | onstk[v]=1; 26 | stk.push_back(v); 27 | if(SPFA(m))return true; 28 | stk.pop_back(); 29 | onstk[v]=0; 30 | } 31 | } 32 | } 33 | onstk[u]=0; 34 | stk.pop_back(); 35 | return false; 36 | } 37 | int solve() { 38 | for(int i=0; i=2) { 50 | int u = stk.back(); 51 | stk.pop_back(); 52 | int v = stk.back(); 53 | stk.pop_back(); 54 | match[v]=u; 55 | match[u]=v; 56 | } 57 | } 58 | } 59 | if(!found)break; 60 | } 61 | int ret = 0; 62 | for(int i=0; i &edges, int root, int n) { 14 | int ans = 0; 15 | int cur_nodes = n; 16 | while (true) { 17 | vector lo(cur_nodes, inf), pi(cur_nodes, inf); 18 | for (int i = 0; i < edges.size(); ++i) { 19 | int u = edges[i].u, v = edges[i].v, w = edges[i].w; 20 | if (w < lo[v] and u != v) { 21 | lo[v] = w; 22 | pi[v] = u; 23 | } 24 | } 25 | lo[root] = 0; 26 | for (int i = 0; i < lo.size(); ++i) { 27 | if (i == root) continue; 28 | if (lo[i] == inf) return -1; 29 | } 30 | int cur_id = 0; 31 | vector id(cur_nodes, -1), mark(cur_nodes, -1); 32 | for (int i = 0; i < cur_nodes; ++i) { 33 | ans += lo[i]; 34 | int u = i; 35 | while (u != root and id[u] < 0 and mark[u] != i) { 36 | mark[u] = i; 37 | u = pi[u]; 38 | } 39 | if (u != root and id[u] < 0) { // Cycle 40 | for (int v = pi[u]; v != u; v = pi[v]) id[v] = cur_id; 41 | id[u] = cur_id++; 42 | } 43 | } 44 | if (cur_id == 0) break; 45 | for (int i = 0; i < cur_nodes; ++i) 46 | if (id[i] < 0) id[i] = cur_id++; 47 | for (int i = 0; i < edges.size(); ++i) { 48 | int u = edges[i].u, v = edges[i].v, w = edges[i].w; 49 | edges[i].u = id[u]; 50 | edges[i].v = id[v]; 51 | if (id[u] != id[v]) edges[i].w -= lo[v]; 52 | } 53 | cur_nodes = cur_id; 54 | root = id[root]; 55 | } 56 | return ans; 57 | } 58 | -------------------------------------------------------------------------------- /Graph/MinimumSpanningTree/DMSTwithSolution.cpp: -------------------------------------------------------------------------------- 1 | const int INF = 1029384756; 2 | #define MAXN 1000 3 | #define FOR(i,x) for(auto i :x ) 4 | struct edge_t { 5 | int u,v,w; 6 | set< pair > add, sub; 7 | edge_t() : u(-1), v(-1), w(0) {} 8 | edge_t(int _u, int _v, int _w) { 9 | u = _u; 10 | v = _v; 11 | w = _w; 12 | add.insert({u, v}); 13 | } 14 | edge_t& operator += (const edge_t& obj) { 15 | w += obj.w; 16 | for (auto it : obj.add) { 17 | if (!sub.count(it)) add.insert(it); 18 | else sub.erase(it); 19 | } 20 | for (auto it : obj.sub) { 21 | if (!add.count(it)) sub.insert(it); 22 | else add.erase(it); 23 | } 24 | return *this; 25 | } 26 | edge_t& operator -= (const edge_t& obj) { 27 | w -= obj.w; 28 | for (auto it : obj.sub) { 29 | if (!sub.count(it)) add.insert(it); 30 | else sub.erase(it); 31 | } 32 | for (auto it : obj.add) { 33 | if (!add.count(it)) sub.insert(it); 34 | else add.erase(it); 35 | } 36 | return *this; 37 | } 38 | } eg[MAXN*MAXN],prv[MAXN],EDGE_INF(-1,-1,INF); 39 | int N,M; 40 | int cid,incyc[MAXN],contracted[MAXN]; 41 | vector E[MAXN]; 42 | 43 | edge_t dmst(int rt) { 44 | edge_t cost; 45 | for (int i=0; i= N) break; // end 57 | for (int i=0; i=0 && incyc[prv[i].u] == cid) 85 | prv[i].u = v; 86 | } 87 | prv[v] = EDGE_INF; 88 | } 89 | return cost; 90 | } 91 | #define F first 92 | #define S second 93 | void solve() { 94 | edge_t cost = dmst(0); 95 | for (auto it : cost.add) { // find a solution 96 | E[it.F].push_back(it.S); 97 | prv[it.S] = edge_t(it.F,it.S,0); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Graph/MinimumSpanningTree/ManhattonMST.cpp: -------------------------------------------------------------------------------- 1 | struct point { 2 | int x, y, index; 3 | bool operator<(const point &p) const { return x == p.x ? y < p.y : x < p.x; } 4 | } p[maxN]; 5 | struct node { 6 | int value, p; 7 | } T[maxN]; 8 | 9 | int query(int x) { 10 | int r = maxint, p = -1; 11 | for (; x <= n; x += (x & -x)) if (T[x].value < r) r = T[x].value, p = T[x].p; 12 | return p; 13 | } 14 | 15 | void modify(int x, int w, int p) { 16 | for (; x > 0; x -= (x & -x)) if (T[x].value > w) T[x].value = w, T[x].p = p; 17 | } 18 | 19 | // impl add & kruskal 20 | int manhattan() { 21 | for (int i = 1; i <= n; ++i) p[i].index = i; 22 | for (int dir = 1; dir <= 4; ++dir) { 23 | if (dir == 2 || dir == 4) { 24 | for (int i = 1; i <= n; ++i) swap(p[i].x, p[i].y); 25 | } else if (dir == 3) { 26 | for (int i = 1; i <= n; ++i) p[i].x = -p[i].x; 27 | } 28 | sort(p + 1, p + 1 + n); 29 | vector v; static int a[maxN]; 30 | for (int i = 1; i <= n; ++i) a[i] = p[i].y - p[i].x, v.push_back(a[i]); 31 | sort(v.begin(), v.end()); 32 | v.erase(unique(v.begin(), v.end()), v.end()); 33 | for (int i = 1; i <= n; ++i) a[i] = lower_bound(v.begin(), v.end(), a[i]) - v.begin() + 1; 34 | for (int i = 1; i <= n; ++i) T[i].value = maxint, T[i].p = -1; 35 | for (int i = n; i >= 1; --i) { 36 | int pos = query(a[i]); 37 | if (pos != -1) add(p[i].index, p[pos].index, dist(p[i], p[pos])); 38 | modify(a[i], p[i].x + p[i].y, i); 39 | } 40 | } 41 | return kruskal(); 42 | } 43 | -------------------------------------------------------------------------------- /Graph/MinimumSpanningTree/PrimsBorukuvaMST.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | MST : Prim’s Algorithm 3 | initial distance of all nodes are INFINITE except the starting node , which distance is 0. 4 | and all nodes are marked as non-visited. 5 | Now until all nodes are visited, pick the non-visited node u 6 | which distance is lowest than all other non-visited nodes. 7 | After picking any nodes, update its all adjacent node v’s distance 8 | if dis[u]+edgeCost(u,v)> adj; 10 | Graph(int n) : n(n), adj(n) { } 11 | void addEdge(int u, int v) { 12 | adj[u].push_back(v); 13 | adj[v].push_back(u); 14 | } 15 | }; 16 | 17 | int chromaticNumber(Graph g) { 18 | const int N = 1 << g.n; 19 | vector nbh(g.n); 20 | for (int u = 0; u < g.n; ++u) 21 | for (int v: g.adj[u]) 22 | nbh[u] |= (1 << v); 23 | 24 | int ans = g.n; 25 | for (int d: {7}) { // ,11,21,33,87,93}) { 26 | long long mod = 1e9 + d; 27 | vector ind(N), aux(N, 1); 28 | ind[0] = 1; 29 | for (int S = 1; S < N; ++S) { 30 | int u = __builtin_ctz(S); 31 | ind[S] = ind[S^(1<> 1); // gray-code 37 | aux[S] = (aux[S] * ind[S]) % mod; 38 | chi += (i & 1) ? aux[S] : -aux[S]; 39 | } 40 | if (chi % mod) ans = k; 41 | } 42 | } 43 | return ans; 44 | } 45 | -------------------------------------------------------------------------------- /Graph/Miscellaneous/CycleEnumeration.cpp: -------------------------------------------------------------------------------- 1 | 2 | // For a directed graph, it enumerates all cycles 3 | // Hawick and James's implementation of Johnson algorithm. 4 | // Complexity O(n+m) average time for each cycles,O(n+m) space. 5 | #define fst first 6 | #define snd second 7 | #define all(c) ((c).begin()), ((c).end()) 8 | struct graph { 9 | int n; 10 | vector> adj; 11 | graph(int n) : n(n), adj(n) { } 12 | void add_edge(int u, int v) { 13 | adj[u].push_back(v); 14 | } 15 | void all_cycles() { 16 | vector S; 17 | for (int s = 0; s < n; ++s) { 18 | vector blocked(n); 19 | vector> B(n); 20 | function unblock = [&](int u) { 21 | blocked[u] = false; 22 | for (int v: B[u]) 23 | if (blocked[v]) unblock(v); 24 | B[u].clear(); 25 | }; 26 | function rec = [&](int u) { 27 | bool is_cycle = false; 28 | blocked[u] = true; 29 | S.push_back(u); 30 | for (int v: adj[u]) { 31 | if (v < s) continue; 32 | if (v == s) { 33 | is_cycle = true; // S forms a cycle 34 | cout << "found cycle" << endl; 35 | for (auto w: S) cout << " " << w; 36 | cout << endl; 37 | } else if (!blocked[v] && rec(v)) is_cycle = true; 38 | if (is_cycle) unblock(u); 39 | else { 40 | for (int v: adj[u]) { 41 | if (v < s) continue; 42 | if (!B[v].count(u)) B[v].insert(u); 43 | } 44 | } 45 | } 46 | S.pop_back(); 47 | return is_cycle; 48 | }; rec(s); 49 | } 50 | } 51 | }; 52 | //graph.all_cycles() 53 | -------------------------------------------------------------------------------- /Graph/Miscellaneous/EulerWalk.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Eulerian undirected/directed path/cycle algorithm.Returns a list of nodes 3 | in the Eulerian path/cycle with src at both start and end, or 4 | empty list if no cycle/path exists. To get edge indices back, also put it->second in s (and then ret). 5 | Time: O(E) where E is the number of edges. 6 | */ 7 | typedef pair pii; 8 | typedef vector vi; 9 | typedef vector vpi; 10 | #define sz(x) (int)x.size() 11 | struct V { 12 | vector outs; // (dest, edge index) 13 | int nins = 0; 14 | void clr(){nins=0;outs.clear();} 15 | }; 16 | #define ff first 17 | #define ss second 18 | vpi euler_walk(vector& nodes, int nedges, int src=0) { 19 | int c = 0; 20 | for(auto &n:nodes)c += abs(n.nins - sz(n.outs)); 21 | if (c > 2) return {}; 22 | vector::iterator> its; 23 | for(auto &n:nodes) 24 | its.push_back(n.outs.begin()); 25 | vector eu(nedges+7); 26 | vpi ret, s = {{src,0}}; 27 | while(!s.empty()) { 28 | auto x = s.back(); 29 | auto& it = its[x.ff], end = nodes[x.ff].outs.end(); 30 | while(it != end && eu[it->second]) ++it; 31 | if(it == end) { ret.push_back(x); s.pop_back(); } 32 | else { s.push_back(*it); eu[it->second] = true; } 33 | } 34 | if(sz(ret) != nedges+1) 35 | ret.clear(); // No Eulerian cycles/paths. 36 | // else, non-cycle if ret.front() != ret.back() 37 | reverse(ret.begin(),ret.end()); 38 | return ret; 39 | } 40 | vectornodes(maxn); 41 | -------------------------------------------------------------------------------- /Graph/Miscellaneous/MatrixTreeTheorem.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * To count the number of spanning trees in an undirected graph G 3 | create an N*N matrix mat, and for each edge (a,b) in G, do 4 | mat[a][a]++, mat[b][b]++, mat[a][b]--, mat[b][a]--. 5 | Remove the last row and column, and take the determinant. 6 | */ 7 | -------------------------------------------------------------------------------- /Graph/Miscellaneous/MaxClique.cpp: -------------------------------------------------------------------------------- 1 | class MaxClique { 2 | public: 3 | static const int MV = 210; 4 | int V; 5 | int el[MV][MV/30+1]; 6 | int dp[MV]; 7 | int ans; 8 | int s[MV][MV/30+1]; 9 | vector sol; 10 | void init(int v) { 11 | V = v; ans = 0; 12 | FZ(el); FZ(dp); 13 | } 14 | /* Zero Base */ 15 | void addEdge(int u, int v) { 16 | if(u > v) swap(u, v); 17 | if(u == v) return; 18 | el[u][v/32] |= (1<<(v%32)); 19 | } 20 | bool dfs(int v, int k) { 21 | int c = 0, d = 0; 22 | for(int i=0; i<(V+31)/32; i++) { 23 | s[k][i] = el[v][i]; 24 | if(k != 1) s[k][i] &= s[k-1][i]; 25 | c += __builtin_popcount(s[k][i]); 26 | } 27 | if(c == 0) { 28 | if(k > ans) { 29 | ans = k; 30 | sol.clear(); 31 | sol.push_back(v); 32 | return 1; 33 | } 34 | return 0; 35 | } 36 | for(int i=0; i<(V+31)/32; i++) { 37 | for(int a = s[k][i]; a ; d++) { 38 | if(k + (c-d) <= ans) return 0; 39 | int lb = a&(-a), lg = 0; 40 | a ^= lb; 41 | while(lb!=1) { 42 | lb = (unsigned int)(lb) >> 1; 43 | lg ++; 44 | } 45 | int u = i*32 + lg; 46 | if(k + dp[u] <= ans) return 0; 47 | if(dfs(u, k+1)) { 48 | sol.push_back(v); 49 | return 1; 50 | } 51 | } 52 | } 53 | return 0; 54 | } 55 | 56 | int solve() { 57 | for(int i=V-1; i>=0; i--) { 58 | dfs(i, 1); 59 | dp[i] = ans; 60 | } 61 | return ans; 62 | } 63 | }; 64 | -------------------------------------------------------------------------------- /Graph/Miscellaneous/MinimumMeanCycle.cpp: -------------------------------------------------------------------------------- 1 | #define maxN 10 2 | #define maxM 10 3 | int dp[maxN][maxN]; // minimum mean cycle(allow negative weight) 4 | double mmc(int n) { 5 | for (int i = 0; i < n; ++i) { 6 | memset(dp[i + 1], 0x7f, sizeof(dp[i + 1])); 7 | for (int j = 1; j <= ec; ++j) { 8 | int u = edge[j].u, v = edge[j].v, w = edge[j].w; 9 | if (dp[i][u] != maxint) 10 | dp[i + 1][v] = min(dp[i + 1][v],dp[i][u]+w); 11 | } 12 | } 13 | double res = maxdbl; 14 | for (int i = 1; i <= n; ++i) { 15 | if (dp[n][i] == maxint) continue; 16 | double value = -maxdbl; 17 | for (int j = 0; j < n; ++j) { 18 | value = max(value,double(dp[n][i]-dp[j][i])/(n-j)); 19 | } 20 | res = min(res, value); 21 | } 22 | return res; 23 | } 24 | -------------------------------------------------------------------------------- /Graph/Miscellaneous/TwoSat.cpp: -------------------------------------------------------------------------------- 1 | typedef long long ll; 2 | const int maxn = 2 * 100005; 3 | struct TwoSat { 4 | int n; 5 | vector G[maxn * 2]; 6 | // i = x', i+n = x , x = variable , i = index 7 | bool mark[maxn * 2];//store actual value 8 | int S[maxn * 2],c; 9 | bool dfs(int x) { 10 | if(mark[x + n]) return false; 11 | if(mark[x]) return true; 12 | mark[x] = true; 13 | S[c++] = x; 14 | for(int i = 0; i < G[x].size(); i++) { 15 | if(!dfs(G[x][i])) return false; 16 | } 17 | return true; 18 | } 19 | void init(int n) { 20 | this -> n = n; 21 | for(int i = 0; i < n * 2; i++) G[i].clear(); 22 | memset(mark,0,sizeof(mark)); 23 | } 24 | void add_clause(int x,int y) { 25 | G[x].push_back(y); 26 | //printf("%d ----- %d\n",x + 1,y + 1); 27 | } 28 | bool solve() { 29 | for(int i = 0; i < n; i ++) { 30 | if(!mark[i] && !mark[i + n]) { 31 | c = 0; 32 | if(!dfs(i)) { 33 | while(c > 0) mark[S[--c]] = false; 34 | if(!dfs(i + n)) return false; 35 | } 36 | } 37 | } 38 | return true; 39 | } 40 | }sat; 41 | -------------------------------------------------------------------------------- /Graph/Tree/Centroid Decomposition on Edge.cpp: -------------------------------------------------------------------------------- 1 | vector >adj[maxn]; 2 | vector >edge[maxn]; 3 | int __cnt ; 4 | #define vv first 5 | #define ww second 6 | inline void addEdge(int u, int v, int w){ 7 | edge[u].push_back({v,w}); 8 | edge[v].push_back({u,w}); 9 | } 10 | namespace Compress{ 11 | // make all node's degree at most 3 12 | void dfs(int u, int p=0){ 13 | int cu = u ; 14 | for(int i=0;i= r) return centroid(e.vv, u, r); 40 | return u; 41 | } 42 | void calc2(int u){ 43 | //cout << " yo yo " << u << endl; 44 | } 45 | void decompose(int u, int par) { 46 | calc(u, 0); 47 | total += sub[u]; 48 | if(sub[u]==1)return ; 49 | int c = centroid(u,0,(sub[u]+2)/3); 50 | int pp = p[c] ; 51 | vis[pp] = 1 ; decompose(c,0) ; vis[pp]= 0; 52 | vis[c]= 1; decompose(pp,0); vis[c] = 0 ; 53 | //calc2(pp); 54 | //calc2(c); 55 | } 56 | } 57 | //Compress::dfs(1); 58 | //CD::decompose(1,0); 59 | -------------------------------------------------------------------------------- /Graph/Tree/Centroid Decompostion.cpp: -------------------------------------------------------------------------------- 1 | // p[u] = parent of u in centroid tree 2 | // d[x][u] = distance from u to a parent of u at level x of centroid tree 3 | // if u is in subtree of centroid c, then d[lvl[c]][u] = dist(c, l) 4 | // Taken from Rezwan Arefin 5 | // If (x, y) edge exist, then x must be in adj[y] and y must be in adj[x] 6 | const int maxn = 1e5 + 10; 7 | vector adj[maxn]; 8 | int lvl[maxn], sub[maxn], p[maxn], vis[maxn], d[18][maxn], ans[maxn]; 9 | 10 | void calc(int u, int par) { sub[u] = 1; 11 | for(int v : adj[u]) if(v - par && !vis[v]) 12 | calc(v, u), sub[u] += sub[v]; 13 | } 14 | int centroid(int u, int par, int r) { 15 | for(int v : adj[u]) if(v - par && !vis[v]) 16 | if(sub[v] > r) return centroid(v, u, r); 17 | return u; 18 | } 19 | void dfs(int l, int u, int par) { 20 | if(par + 1) d[l][u] = d[l][par] + 1; 21 | for(int v : adj[u]) if(v - par && !vis[v]) 22 | dfs(l, v, u); 23 | } 24 | void decompose(int u, int par) { 25 | calc(u, -1); 26 | int c = centroid(u, -1, sub[u] >> 1); 27 | vis[c] = 1, p[c] = par, lvl[c] = 0; 28 | if(par + 1) lvl[c] = lvl[par] + 1; 29 | dfs(lvl[c], c, -1); 30 | for(int v : adj[c]) if(v - par && !vis[v]) 31 | decompose(v, c); 32 | } 33 | 34 | void update(int u) { 35 | for(int v = u; v + 1; v = p[v]) 36 | ans[v] = min(ans[v], d[lvl[v]][u]); 37 | } 38 | int query(int u) { 39 | int ret = 1e9; 40 | for(int v = u; v + 1; v = p[v]) 41 | ret = min(ret, ans[v] + d[lvl[v]][u]); 42 | return ret; 43 | } 44 | -------------------------------------------------------------------------------- /Graph/Tree/CompressTree.cpp: -------------------------------------------------------------------------------- 1 | typedef vector vi; 2 | typedef vector > vpi; 3 | vpi compressTree(const vector& subset) { 4 | vi rev(n+1); 5 | vi li = subset; 6 | auto cmp = [&](int a, int b) { 7 | return st[a] < st[b]; 8 | }; 9 | sort(li.begin(),li.end(), cmp); 10 | int m = li.size()-1; 11 | for(int i=0; i(0, li[0])}; 19 | for(int i=0; ick[1000006]; 3 | int id[1000006]; 4 | set >s[1000006]; 5 | int x, y, n, ans[1000006], offset[1000006]; 6 | vectoradj[1000006]; 7 | void go(int u,int p) { 8 | ck[id[u]][0]=1; 9 | s[id[u]].insert({-1,0}); 10 | for(int v : adj[u]) { 11 | if(v==p)continue; 12 | go(v,u); 13 | if(s[id[v]].size()>s[id[u]].size()) { 14 | for(auto p : s[id[u]]) { 15 | int ki = p.second-1+offset[id[u]]-offset[id[v]]; 16 | int koyta = ck[id[v]][ki]; 17 | if(koyta!=0)s[id[v]].erase(s[id[v]].find({-koyta,ki})); 18 | koyta -= p.first ; 19 | s[id[v]].insert({-koyta,ki}); 20 | ck[id[v]][ki] = koyta ; 21 | } 22 | offset[id[v]]++; 23 | swap(id[u],id[v]); 24 | } else { 25 | for(auto p : s[id[v]]) { 26 | int ki = p.second+1+offset[id[v]]-offset[id[u]]; 27 | int koyta = ck[id[u]][ki]; 28 | if(koyta!=0)s[id[u]].erase(s[id[u]].find({-koyta,ki})); 29 | koyta -= p.first ; 30 | s[id[u]].insert({-koyta,ki}); 31 | ck[id[u]][ki] = koyta ; 32 | } 33 | } 34 | } 35 | auto it = *(s[id[u]].begin()); 36 | ans[u] = it.second + offset[id[u]] ; 37 | } 38 | -------------------------------------------------------------------------------- /Graph/Tree/DominatorTree (for Any Directed Graph).cpp: -------------------------------------------------------------------------------- 1 | #define Max 1000000 2 | #define sz(u) u.size() 3 | #define pb push_back 4 | struct DominatorTree { 5 | vector g[Max], tree[Max],bucket[Max],rg[Max]; 6 | int sdom[Max],dom[Max],label[Max],arr[Max],rev[Max],T; 7 | int papa[Max]; //store u's dominator in papa[u] 8 | int n,m,par[Max],dsu[Max]; 9 | int Find(int u,int x=0) { 10 | if(u == dsu[u])return x ? -1 : u; 11 | int v = Find(dsu[u],x+1); 12 | if(v<0)return u; 13 | if(sdom[label[dsu[u]]]= 1; i--) { 32 | for(int j = 0; j 1)bucket[ sdom[i] ].pb(i); 35 | for(int j = 0; j < sz(bucket[i]); j++) { 36 | int w = bucket[i][j]; 37 | int v = Find(w); 38 | if( sdom[w] == sdom[v] )dom[w] = sdom[w]; 39 | else dom[w] = v; 40 | } 41 | if(i > 1)Union(par[i],i); 42 | } 43 | for(int i = 2; i <= T; i++) { 44 | if(dom[i] != sdom[i])dom[i] = dom[ dom[i] ]; 45 | tree[ rev[ dom[i] ] ].pb(rev[i]); 46 | papa[rev[i]]=rev[dom[i]]; 47 | //here rev[dom[i]] dominates rev[i] 48 | } 49 | } 50 | void Clear() { 51 | for(int i = 1; i <= n; i++) { 52 | arr[i] = sdom[i] = dom[i] = par[i] = dsu[i] = label[i] = rev[i] = 0; 53 | tree[i].clear(); 54 | g[i].clear(); 55 | rg[i].clear(); 56 | bucket[i].clear(); 57 | } 58 | T=0; 59 | } 60 | } dtree; 61 | //dree.g[u].pb(v)&then call dominator_tree_init() 62 | -------------------------------------------------------------------------------- /Graph/Tree/DominatorTree.cpp: -------------------------------------------------------------------------------- 1 | //construct DAG by dijkstra and then create dominator tree 2 | #define uu second 3 | typedef long long ll; 4 | const int maxN = 100007; 5 | const int inf=1e9; 6 | struct DominatorTree { 7 | int ans[maxN],par[maxN][25], level[maxN],dis[maxN]; 8 | vectoradj[maxN],cost[maxN],mama[maxN] ; 9 | vector >nodes ; 10 | void clr() { 11 | nodes.clear(); 12 | for(int i = 0 ; i < maxN ; i++)adj[i].clear(),cost[i].clear(),mama[i].clear(); 13 | memset(par,0,sizeof(par)); 14 | memset(level,0,sizeof(level)); 15 | memset(dis,0,sizeof(dis)); 16 | memset(ans,0,sizeof(ans)); 17 | } 18 | int lca(int u,int v) { 19 | if(level[u]< level[v])swap(u,v); 20 | int tmp=1; 21 | for(; (1<=0; --i) { 24 | if(level[u]-(1<=level[v])u=par[u][i]; 25 | } 26 | if(u==v)return u ; 27 | for(int i = tmp ; i >= 0 ; --i) if(par[u][i]!=par[v][i])u=par[u][i],v=par[v][i] ; 28 | return par[u][0]; 29 | } 30 | void dijkstra( int n, int src ) { 31 | priority_queue< pair < int, int > > pq ; 32 | pq.push( make_pair( 0, src ) ) ; 33 | for( int i = 0 ; i <= n ; i++ ) dis[i] = inf ; 34 | dis[src] = 0LL ; 35 | while( !pq.empty() ) { 36 | pairnode = pq.top() ; 37 | pq.pop(); 38 | for( int i = 0 ; i < adj[node.uu].size() ; i++ ) { 39 | int v = adj[node.uu][i] ; 40 | int w = cost[node.uu][i] ; 41 | if(dis[node.uu]+wr)return; 3 | if(L==R){ 4 | for(int i=l;i<=r;i++)ans[i]=L; 5 | return; 6 | } 7 | int mid=(l+r)/2; 8 | int ans=F(mid); 9 | calc(l,mid-1,ans,R); 10 | calc(mid+1,r,L,ans); 11 | } 12 | //call calc(1,n,0,n); 13 | -------------------------------------------------------------------------------- /Graph/Tree/HLD.cpp: -------------------------------------------------------------------------------- 1 | HeavyLightDecomposition 2 | 3 | LazySegmentTree Tree ; 4 | int sz[MAX]; 5 | int in[MAX]; 6 | int rin[MAX]; 7 | int out[MAX]; 8 | int head[MAX]; 9 | int par[MAX]; 10 | vectorg[MAX]; 11 | void dfs_sz(int u,int p) { 12 | sz[u] = 1; 13 | par[u] = p; 14 | for(auto &v: g[u]) { 15 | if(v==p)continue; 16 | dfs_sz(v,u); 17 | sz[u] += sz[v]; 18 | if(sz[v] > sz[g[u][0]]) 19 | swap(v,g[u][0]); 20 | } 21 | } 22 | int t; 23 | void dfs_hld(int u,int p) { 24 | in[u] = ++t; 25 | rin[in[u]] = u; 26 | for(auto v: g[u]) { 27 | if(v==p)continue; 28 | head[v] = (v == g[u][0] ? head[u] : v); 29 | dfs_hld(v,u); 30 | } 31 | out[u] = t; 32 | } 33 | bool isParent(int p,int u){ 34 | return in[p]<=in[u]&&out[u]<=out[p]; 35 | } 36 | int n ; 37 | int pathQuery(int u,int v){ 38 | int ret = -inf; 39 | while(true){ 40 | if(isParent(head[u],v))break; 41 | ret=max(ret,Tree.queryRange(1,1,n,in[head[u]],in[u])); 42 | u=par[head[u]]; 43 | } 44 | swap(u,v); 45 | while(true){ 46 | if(isParent(head[u],v))break; 47 | ret=max(ret,Tree.queryRange(1,1,n,in[head[u]],in[u])); 48 | u=par[head[u]]; 49 | } 50 | if(in[v]=0;i--) if(D[p]-D[q] >= (1<=0;i--) if(P[p][i]!=0 && P[p][i] != P[q][i]) {p = P[p][i]; q = P[q][i];} 25 | int LCA = Par[p]; 26 | return LCA; 27 | } 28 | 29 | //Note 1 : Reversing v while merging (u,v) might be necessary in some case. 30 | //Note 2 : We assign cost of an edge as the cost of the child node. 31 | //Note 3 : In case values/costs for each node given (instead of each edge), merge LCA too along with merging u and v. 32 | 33 | int kth_par(int u,int d){ 34 | int Log = log2(d)+1; 35 | for(int i=Log; i>=0; i--) if(d >= (1< > vpi; 3 | typedef vector graph; 4 | typedef long long ll ; 5 | int sz(graph& C) { 6 | return C.size(); 7 | } 8 | template 9 | struct RMQ { 10 | vector> jmp; 11 | RMQ(const vector& V) { 12 | int N = V.size(), on = 1, depth = 1; 13 | while (on < V.size() ) on *= 2, depth++; 14 | jmp.assign(depth, V); 15 | for(int i=0; i time; 26 | vector dist; 27 | RMQ > rmq; 28 | LCA(graph& C) : time(sz(C), -99), dist(sz(C)), rmq(dfs(C)) {} 29 | vpi dfs(graph& C) { 30 | vector> q(1); 31 | vector > ret; 32 | int T = 0, v, p, d; 33 | ll di; 34 | while (!q.empty()) { 35 | tie(v, p, d, di) = q.back(); 36 | q.pop_back(); 37 | if (d) ret.emplace_back(d, p); 38 | time[v] = T++; 39 | dist[v] = di; 40 | for(auto &e: C[v]) if (e.first != p) 41 | q.emplace_back(e.first, v, d+1, di + e.second); 42 | } 43 | return ret; 44 | } 45 | int query(int a, int b) { 46 | if (a == b) return a; 47 | a = time[a], b = time[b]; 48 | return rmq.query(min(a, b), max(a, b)).second; 49 | } 50 | long long distance(int a, int b) { 51 | int lca = query(a, b); 52 | return dist[a] + dist[b] - 2 * dist[lca]; 53 | } 54 | }; 55 | -------------------------------------------------------------------------------- /Graph/Tree/MO on Tree.cpp: -------------------------------------------------------------------------------- 1 | typedef pair< pair , pair > que; 2 | vector< que >query; 3 | 4 | int S = sqrt(100005); 5 | #define L first.first 6 | #define R first.second 7 | #define lca second.first 8 | #define id second.second 9 | 10 | bool cmp(const que &P,const que &Q){ 11 | if(P.L/S!=Q.L/S)return P.L/SQ.R; 13 | return P.Rst[v])swap(u,v);//st=dfs start time 27 | int lca = LCA(u,v); 28 | if(lca!=u)query.push_back({{en[u],st[v]},{st[lca],i}}); 29 | else query.push_back({{st[u],st[v]},{-1,i}}); 30 | } 31 | 32 | void solve(){ 33 | sort(query.begin(),query.end(),cmp); 34 | l=1; 35 | r=0; 36 | 37 | for (auto q : query){ 38 | while(l>q.L) up(--l); 39 | while(rq.R) up(r--); 42 | } 43 | 44 | if(q.lca!=-1) up(lca); 45 | calc(ans); 46 | if(q.lca!=-1) up(lca); 47 | } 48 | -------------------------------------------------------------------------------- /Graph/Tree/Path Path Intersection.cpp: -------------------------------------------------------------------------------- 1 | vectorcmp; 2 | int calc(int a,int b,int c,int d) { 3 | int ac = lca(a,c); 4 | if(level[ac] solve(int a,int b,int c,int d) { 16 | cmp.clear(); 17 | int ab= lca(a,b); 18 | int cd= lca(c,d); 19 | int ans = 0; 20 | ans += calc(a,ab,c,cd); 21 | ans += calc(a,ab,d,cd); 22 | ans += calc(b,ab,c,cd); 23 | ans += calc(b,ab,d,cd); 24 | int f = 0; 25 | f += calc(ab,ab,c,cd); 26 | f += calc(ab,ab,d,cd); 27 | f += calc(a,ab,cd,cd); 28 | f += calc(b,ab,cd,cd); 29 | ans -= f ; 30 | if(ab==cd) 31 | ans++; 32 | sort(cmp.begin(),cmp.end()); 33 | cmp.erase(unique(cmp.begin(),cmp.end()),cmp.end()); 34 | pairret={-1,-1}; 35 | assert(cmp.size()<=3); 36 | int mxdis=0; 37 | for(int i=0;imxdis){ 44 | ret={u,v}; 45 | mxdis=dis; 46 | } 47 | } 48 | } 49 | return ret ; 50 | } 51 | -------------------------------------------------------------------------------- /Graph/shortestPath/0-1BFS.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | if edge weight is 1, insert at the end 3 | otherwise insert at the beginning 4 | */ 5 | -------------------------------------------------------------------------------- /Graph/shortestPath/BellmanFord.cpp: -------------------------------------------------------------------------------- 1 | typedef double ll; 2 | const int maxn = 105; 3 | const int maxm = 10005; 4 | const ll inf = 1e9; 5 | ll d[maxn],w[maxm]; 6 | int u[maxm],v[maxm],n,m; 7 | bool BellmanFord(){//1-indexed 8 | for(int i=1;i<=n;i++)d[i]=inf; 9 | d[1]=0; 10 | for(int i=1; i<=n; i++) 11 | for(int j=0; jfound(n+1); 6 | dis[start] = 0; 7 | while (start != -1) { 8 | found[start] = true; 9 | int best = -1; 10 | for (int k = 1; k <= n; k++) 11 | if (!found[k]) { 12 | if (dis[k] > dis[start] + cost[start][k]) { 13 | dis[k] = dis[start] + cost[start][k]; 14 | par[k] = start; 15 | } 16 | if (best==-1 || dis[k]adj[N],cost[N]; 5 | #define uu second 6 | #define ww first 7 | void dijkstra(int src ) { //VlogV+E 8 | priority_queue< pair < int, int > > pq ; 9 | pq.push( make_pair( 0, src ) ) ; 10 | for( int i = 0; i <= n ; i++ ) dis[i] = inf ; 11 | dis[src] = 0 ; 12 | while( !pq.empty() ) { 13 | pairnode = pq.top() ; 14 | int u = node.uu; 15 | pq.pop(); 16 | if(dis[u]<-node.ww)continue; 17 | for( int i =0; i E, vector & dis){ 14 | dis[src] = 0; 15 | for (int i = 0; i <= n; i++){ 16 | int flag = 0; 17 | for (auto e: E){ 18 | if ((dis[e.u] + e.w) < dis[e.v]){ 19 | flag = 1; 20 | dis[e.v] = dis[e.u] + e.w; 21 | } 22 | } 23 | if (flag == 0) return true; 24 | } 25 | return false; 26 | } 27 | vector dijkstra(int n, int src, vector E, vector potential){ 28 | set > S; 29 | vector dis(n + 1, INF); 30 | vector temp(n + 1, INF); 31 | vector > adj[n + 1]; 32 | dis[src] = temp[src] = 0; 33 | S.insert(make_pair(temp[src], src)); 34 | for (auto e: E){ 35 | adj[e.u].push_back(make_pair(e.v, e.w)); 36 | } 37 | int __sigh = 0; 38 | while (!S.empty()){ 39 | pair cur = *(S.begin()); 40 | S.erase(cur); 41 | int u = cur.second; 42 | for (int i = 0; i < adj[u].size(); i++){ 43 | int v = adj[u][i].first; 44 | ll w = adj[u][i].second; 45 | if ((temp[u] + w) < temp[v]){ 46 | S.erase(make_pair(temp[v], v)); 47 | temp[v] = temp[u] + w; 48 | dis[v] = dis[u] + w; 49 | S.insert(make_pair(temp[v], v)); 50 | } 51 | } 52 | } 53 | return dis; 54 | } 55 | void johnson(int n, ll ar[MAX][MAX], vector E){ 56 | vector potential(n + 1, INF); 57 | for (int i = 1; i <= n; i++) E.push_back(Edge(0, i, 0)); 58 | 59 | assert(bellman_ford(n, 0, E, potential)); 60 | for (int i = 1; i <= n; i++) E.pop_back(); 61 | 62 | for (int i = 1; i <= n; i++){ 63 | vector dis = dijkstra(n, i, E, potential); 64 | for (int j = 1; j <= n; j++){ 65 | ar[i][j] = dis[j]; 66 | } 67 | } 68 | } 69 | ll ar[MAX][MAX];// output all pair shortest distance 70 | vector E; // input graph 71 | -------------------------------------------------------------------------------- /Math/Combinatorial Summation Formulas.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnikSarker/ACM-Library/aeb469c565e5f84e5ccf08ab1304e45dda4d6297/Math/Combinatorial Summation Formulas.pdf -------------------------------------------------------------------------------- /Math/Combinatorics/Partition Function.cpp: -------------------------------------------------------------------------------- 1 | // Calculates Partition Function(x) for all x <= n 2 | // p(n) = number of distinct ways of representing n 3 | // as sum of natural numbers (with order irrelevant). 4 | // Complexity : O(n sqrt(n)) 5 | 6 | #define MAX 60005 7 | #define MOD 1000000007 8 | int p[MAX]; 9 | inline int Add(int a,int b){return (a+b)%MOD;} 10 | 11 | int PartitionFunction(){ 12 | p[0] = 1; 13 | for(int i = 1; i < MAX; i++){ 14 | int j = 1, r = 1; 15 | while(i - (3*j*j - j) / 2 >= 0){ 16 | p[i] = Add(p[i], p[i - (3*j*j - j) / 2] * r); 17 | 18 | if(i - (3*j*j + j) / 2 >= 0) 19 | p[i] = Add(p[i], p[i - (3*j*j + j) / 2] * r); 20 | 21 | j += 1; 22 | r *= -1; 23 | } 24 | if(p[i]<0) p[i]+=MOD; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Math/Combinatorics/Stirling Number (via NTT).cpp: -------------------------------------------------------------------------------- 1 | NTT ntt(mod); 2 | vectorv[MAX]; 3 | 4 | //Stirling1 (n,k) = co-eff of x^k in x*(x+1)*(x+2)*....(x+n-1) 5 | int Stirling1(int n, int r) { 6 | int nn = 1; 7 | while(nn < n) nn <<= 1; 8 | 9 | for(int i = 0; i < n; ++i) {v[i].push_back(i); v[i].push_back(1);} 10 | for(int i = n; i < nn; ++i) v[i].push_back(1); 11 | 12 | for(int j = nn; j > 1; j >>= 1) { 13 | int hn = j >> 1; 14 | for(int i = 0; i < hn; ++i) ntt.multiply(v[i], v[i + hn], v[i]); 15 | } 16 | return v[0][r]; 17 | } 18 | 19 | NTT ntt(mod); 20 | vectora,b,res; 21 | 22 | //Stirling2 (n,k) = co-eff of x^k in product of polynomials A & B 23 | //where A(i) = (-1)^i / i! and B(i) = i^n / i! 24 | int Stirling2(int n, int r) { 25 | a.resize(n+1); b.resize(n+1); 26 | for(int i = 0; i <= n; i++){ 27 | a[i] = invfct[i]; 28 | if(i % 2 == 1) a[i] = mod - a[i]; 29 | } 30 | 31 | for(int i = 0; i <= n; i++){ 32 | b[i] = bigMod(i, n, mod); 33 | b[i] = (b[i] * invfct[i]) % mod; 34 | } 35 | 36 | NTT ntt(mod); 37 | ntt.multiply(a,b,res); 38 | return res[r]; 39 | } 40 | -------------------------------------------------------------------------------- /Math/Linear Equation - Matrix/Gaussian Elimination.cpp: -------------------------------------------------------------------------------- 1 | //Gaussian Elimination 2 | //format : (a[0]*x[0]+a[1]*x[1] ... a[m-1]*x[m-1]) % k = a[m], where 0 <= ai < k 3 | //number of solution : k^(number of free variable) = k^(n-rank) 4 | 5 | int gcdExtended(int a, int b, int& x, int& y){ 6 | if(a==0) {x=0;y=1; return b;} 7 | int x1,y1; 8 | int gcd = gcdExtended(b%a,a,x1,y1); 9 | x=y1-(b/a)*x1; 10 | y=x1; 11 | return gcd; 12 | } 13 | 14 | int modinverse(int x,int y) {int a,b; gcdExtended(x,y,a,b); return a;} 15 | 16 | //n equations (n rows), m variables (m+1 columns) 17 | void Gauss(int n,int m,int k){ 18 | int r,c; 19 | for(r=0,c=0;rabs(A[r][c])) swap(A[i],A[r]); 21 | if(!A[r][c]) continue; 22 | int s = modinverse(A[r][c],k); 23 | for(int i=r+1;i=0;i--){ 34 | x[i]=A[i][m]; 35 | for(int j=i+1;j 2 | using namespace std; 3 | #define MAX 100005 4 | #define ll long long int 5 | 6 | // Gaussian Elimination Online 7 | struct maxxor{ 8 | vector basis; 9 | void init() {basis.clear();} 10 | 11 | void add(ll x){ 12 | // Keep the basis sorted in increasing order 13 | for(ll b : basis) x = min(x, x ^ b); 14 | for(ll &b : basis) b = min(b, x ^ b); 15 | 16 | if(x){ 17 | basis.push_back(x); 18 | for(ll i = basis.size() - 1; i> 0 ; i--){ 19 | if(basis[i] < basis[i - 1]) swap(basis[i], basis[i - 1]); 20 | else break; 21 | } 22 | } 23 | } 24 | 25 | //returns max subset xor 26 | ll getMax(){ 27 | ll ans=0; 28 | for(ll b : basis) ans ^= b; 29 | return ans; 30 | } 31 | 32 | //returns max xor over (k ^ some subset) 33 | ll getMax(ll k){ 34 | ll ans = k; 35 | for(ll b : basis) ans = max(ans, ans ^ b); 36 | return ans; 37 | } 38 | 39 | //returns k-th (0-indexed) smallest distinct subset xor 40 | ll getKth(ll k){ 41 | ll ans = 0; 42 | for(ll i = 0; i < basis.size(); i++) 43 | if((k >> i) & 1) ans ^= basis[i]; 44 | return ans; 45 | } 46 | }ds; 47 | 48 | // Gaussian Elimination Offline 49 | ll a[MAX], n; 50 | ll maxxor(){ 51 | int r = 0; ll ret = 0; 52 | for(int c = 63; c >= 0; c--){ 53 | int idx = -1; 54 | for(int i = r; i < n && idx < 0; i++) 55 | if(a[i] >> c & 1) idx = i; 56 | if(idx == -1) continue; 57 | swap(a[r], a[idx]); 58 | for(int i = 0; i < n; i++) if(i != r) 59 | if(a[i] >> c & 1) a[i] ^= a[r]; 60 | r++; 61 | } 62 | for(int i = 0; i < n; i++) ret = max(ret, ret ^ a[i]); 63 | return ret; 64 | } 65 | -------------------------------------------------------------------------------- /Math/Linear Equation - Matrix/SImplex.cpp: -------------------------------------------------------------------------------- 1 | /* Note: Simplex algorithm on augmented matrix a of dimension (m+1)x(n+1) 2 | * returns 1 if feasible, 0 if not feasible, -1 if unbounded 3 | * returns solution in b[] in original var order, max(f) in ret 4 | * form: maximize sum_j(a_mj*x_j)-a_mn s.t. sum_j(a_ij*x_j)<=a_in 5 | * To convert into standard form: 6 | * 1. if exists equality constraint, then replace by both >= and <= 7 | * 2. if variable x doesn't have nonnegativity constraint, then replace by 8 | * difference of 2 variables like x1-x2, where x1>=0, x2>=0 9 | * 3. for a>=b constraints, convert to -a<=-b 10 | * note: watch out for -0.0 in the solution, algorithm may cycle 11 | * EPS = 1e-7 may give wrong answer, 1e-10 is better */ 12 | 13 | #include 14 | using namespace std; 15 | #define maxM 7 16 | #define maxN 100007 17 | #define INF 1000000007 18 | #define EPS (1e-12) 19 | #define PI acos(-1) 20 | 21 | struct Simplex { 22 | void pivot( int m,int n,double A[maxM][maxN+7],int *B,int *N,int r,int c ) { 23 | int i,j; 24 | swap( N[c],B[r] ); 25 | A[r][c] = 1/A[r][c]; 26 | for( j=0; j<=n; j++ ) if( j!=c ) A[r][j] *= A[r][c]; 27 | for( i=0; i<=m; i++ ) { 28 | if( i!=r ) { 29 | for( j=0; j<=n; j++ ) if( j!=c ) A[i][j] -= A[i][c]*A[r][j]; 30 | A[i][c] = -A[i][c]*A[r][c]; 31 | } 32 | } 33 | } 34 | 35 | int feasible( int m,int n,double A[maxM][maxN+7],int *B,int *N ) { 36 | int r,c,i; 37 | double p,v; 38 | while( 1 ) { 39 | for( p=INF,i=0; i -EPS ) return 1; 41 | for( p=0,i=0; i -EPS ) return 0; 43 | p = A[r][n]/A[r][c]; 44 | for( i=r+1; i EPS ) { 46 | v = A[i][n]/A[i][c]; 47 | if( v

p ) p = A[m][c=i]; 65 | if( p EPS ) { 73 | v = A[i][n]/A[i][c]; 74 | if( v

2 | using namespace std; 3 | #define LD long double 4 | 5 | // Equation of the form: (x_prev * l) + (x_cur * p) + (x_next * r) = rhs 6 | struct equation{ 7 | LD l, p, r, rhs; 8 | 9 | equation(){} 10 | equation(LD l, LD p, LD r, LD rhs = 0.0): 11 | l(l), p(p), r(r), rhs(rhs){} 12 | }; 13 | 14 | // Thomas algorithm to solve tri-digonal system of equations in O(n) 15 | vector thomas_algorithm(int n, vector ar){ 16 | ar[0].r = ar[0].r / ar[0].p; 17 | ar[0].rhs = ar[0].rhs / ar[0].p; 18 | 19 | for (int i = 1; i < n; i++){ 20 | LD v = 1.0 / (ar[i].p - ar[i].l * ar[i - 1].r); 21 | ar[i].r = ar[i].r * v; 22 | ar[i].rhs = (ar[i].rhs - ar[i].l * ar[i - 1].rhs) * v; 23 | } 24 | for (int i = n - 2; i >= 0; i--) ar[i].rhs = ar[i].rhs - ar[i].r * ar[i + 1].rhs; 25 | 26 | vector res; 27 | for (int i = 0; i < n; i++) res.push_back(ar[i].rhs); 28 | return res; 29 | } 30 | -------------------------------------------------------------------------------- /Math/Number Theory/Baby Step Giant Step (Any modulo).cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int egcd(int a, int b, int& x, int& y){ 5 | if (!b) {y = 0, x = 1; return a;} 6 | int g = egcd(b, a % b, y, x); 7 | y -= ((a / b) * x); 8 | return g; 9 | } 10 | 11 | int discrete_log(int g, int h, int p){ 12 | // returns smallest x such that (g^x) % p = h, -1 if none exists 13 | // function returns x, the discrete log of h with respect to g modulo p 14 | 15 | if (h >= p) return -1; 16 | if ((g % p) == 0){ 17 | if (h == 1) return 0; // return -1 if strictly positive integer solution is required 18 | else return -1; 19 | } 20 | 21 | int i, c, x, y, z, r, m, counter = 0; 22 | long long v = 1, d = 1, mul = 1, temp = 1 % p; 23 | 24 | for (int i = 0; i < 100; i++){ 25 | if (temp == h) return i; 26 | temp = (temp * g) % p; 27 | } 28 | 29 | while ((v = __gcd(g, p)) > 1){ 30 | if (h % v) return -1; 31 | h /= v, p /= v; 32 | d = (d * (g / v)) % p; 33 | counter++; 34 | } 35 | 36 | m = ceil(sqrt(p)); // try sqrtl() 37 | unordered_map mp; 38 | 39 | for (i = 0; i < m; i++){ 40 | if(!mp[mul]) mp[mul] = i + 1; 41 | mul = (mul * g) % p; 42 | } 43 | 44 | for (i = 0; i < m; i++){ 45 | z = egcd(d, p, x, y); 46 | c = p / z; 47 | r = ((((long long)x * h) / z) % p + p) % p; 48 | if (mp[r]) return ((i * m) + mp[r] + counter - 1); 49 | d = (d * mul) % p; 50 | } 51 | return -1; 52 | } 53 | 54 | int main(){ 55 | int g, h, p, res; 56 | scanf("%d %d %d", &g, &p, &h); 57 | 58 | res = discrete_log(g, h % p, p); 59 | if (res == -1) puts("No Solution"); 60 | else printf("%d\n", res); 61 | } 62 | -------------------------------------------------------------------------------- /Math/Number Theory/Baby Step Giant Step (Only Prime Modulo).cpp: -------------------------------------------------------------------------------- 1 | //Tested : LightOJ 1325 - Distributing Chocolates 2 | 3 | #include 4 | using namespace std; 5 | #define ll long long int 6 | 7 | //Shanks Baby-Step Giant-Step (Faster) 8 | //a^x = b (mod m) 9 | ll egcd(ll a,ll b,ll &x,ll &y){ 10 | if(b == 0) {x = 1; y = 0; return a;} 11 | ll g = egcd(b,a%b,y,x); 12 | y -= a / b * x; 13 | return g; 14 | } 15 | 16 | ll InvMod(ll a,ll m){ 17 | ll x,y; 18 | if(egcd(a,m,x,y) == 1) return (x + m) % m; 19 | return -1; 20 | } 21 | 22 | unordered_map H; 23 | ll baby_step_giant_step(ll a,ll b,ll m){ 24 | H.clear(); 25 | int k = (int) sqrt(m)+1; 26 | 27 | //Baby step 28 | ll aa = 1; 29 | for(int j=0;j= 0 3 | * finds the closest rational approximation p/q with p, q <= N. 4 | * It will obey |p/q - x| <= 1 / qN. 5 | * For consecutive convergents, p_{k+1} * q_k - q_{k+1} * p_k = (-1)^k 6 | * (p_k / q_k alternates between > x and < x) 7 | * If x is rational, y eventually becomes \infty; 8 | * if x is the root of a degree 2 polynomial the a's eventually become cyclic. 9 | * Time: O(log N) 10 | */ 11 | 12 | #include 13 | using namespace std; 14 | 15 | #define d double // for N ~ 1e7; long double for N ~ 1e9 16 | #define ll long long int 17 | 18 | pair approximate(d x, ll N) { 19 | ll LP = 0, LQ = 1; 20 | ll P = 1, Q = 0; 21 | ll inf = LLONG_MAX; 22 | d y = x; 23 | 24 | while(true){ 25 | ll lim = min(P ? (N-LP) / P : inf, Q ? (N-LQ) / Q : inf); 26 | ll a = (ll) floor(y); 27 | ll b = min(a, lim); 28 | ll NP = b*P + LP, NQ = b*Q + LQ; 29 | 30 | if(a > b){ 31 | // If b > a/2, we have a semi-convergent that gives us a 32 | // better approximation; if b = a/2, we *may* have one. 33 | // Return {P, Q} here for a more canonical approximation. 34 | return (abs(x - (d)NP / (d)NQ) < abs(x - (d)P / (d)Q)) ? 35 | make_pair(NP, NQ) : make_pair(P, Q); 36 | } 37 | 38 | if(abs(y = 1/(y - (d) a)) > 3*N) return {NP, NQ}; 39 | LP = P; P = NP; 40 | LQ = Q; Q = NQ; 41 | } 42 | } 43 | 44 | int main(){ 45 | auto ret = approximate(0.53846153846, 14); 46 | cout< 4 | using namespace std; 5 | #define ll long long int 6 | 7 | // Diophantine equation : a * x + b * y = gcd(a, b) 8 | // egcd computes one solution (x, y) for gcd(a,b) = g 9 | // Note: computed value g can be negative. 10 | // Given one solution (x0, y0), other solutions have form : 11 | // xk = x0 + k * b / g and yk = y0 - k * a / g 12 | 13 | ll egcd(ll a,ll b,ll &x,ll &y){ 14 | if(a == 0) {x = 0; y = 1; return b;} 15 | ll x1,y1; 16 | ll gcd = egcd(b%a, a, x1, y1); 17 | x = y1 - (b / a) * x1; y = x1; 18 | return gcd; 19 | } 20 | 21 | inline ll Floor(ll p, ll q) {return p>0 ? p/q : p/q - !!(p%q);} 22 | inline ll Ceil(ll p, ll q) {return p<0 ? p/q : p/q + !!(p%q);} 23 | 24 | // Number of solutions of Diophantine Eqn : Ax + By = C 25 | // A,B,C,x,y integers and X1 <= x <= X2 and Y1 <= y <= Y2 26 | inline ll solve(ll A,ll B,ll C,ll X1,ll X2,ll Y1,ll Y2){ 27 | if(A<0) {A = -A; B = -B; C = -C;} 28 | ll G = __gcd(A,B); 29 | if(G && C%G) return 0; 30 | 31 | if(A == 0 && B == 0) return (C == 0) ? (X2 - X1 + 1) * (Y2 - Y1 + 1) : 0; 32 | if(A == 0) return (Y1 <= C/B && C/B <= Y2) ? (X2 - X1 + 1) : 0; 33 | if(B == 0) return (X1 <= C/A && C/A <= X2) ? (Y2 - Y1 + 1) : 0; 34 | 35 | ll x,y; 36 | egcd(A,B,x,y); 37 | x = x * (C/G); y = y * (C/G); 38 | 39 | ll newX1 = C - B * Y1, newX2 = C - B * Y2; 40 | if(newX1> newX2) swap(newX1, newX2); 41 | newX2 = Floor(newX2, A); newX1 = Ceil(newX1, A); 42 | 43 | if(X1 > newX2) return 0; 44 | if(X2 < newX1) return 0; 45 | X1 = max(X1, newX1); X2 = min(X2, newX2); 46 | 47 | ll div = abs(B/G); 48 | if(x < X1) return (X2 - x) / div - (X1 - 1 - x) / div; 49 | if(x > X2) return (x - X1) / div - (x - X2 - 1) / div; 50 | return 1 + (x - X1) / div + (X2 - x) / div; 51 | } 52 | -------------------------------------------------------------------------------- /Math/Number Theory/Fast Fibonacci.cpp: -------------------------------------------------------------------------------- 1 | // F(n-1) * F(n+1) - F(n) * F(n) = (-1)^n 2 | // F(n+k) = F(k) * F(n+1) + F(k-1) * F(n) 3 | // gcd(F(m), F(n)) = F(gcd(m,n)) 4 | 5 | #define ll long long int 6 | 7 | pair fib(ll n) { 8 | if(n == 0) return {0, 1}; 9 | ll x, y; 10 | if(n & 1) { 11 | tie(y, x) = fib(n - 1); 12 | return {x, (y + x) % MOD}; 13 | } 14 | else{ 15 | tie(x, y) = fib(n >> 1); 16 | return {(x * y + x * (y - x + MOD)) % MOD, (x * x + y * y) % MOD}; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Math/Number Theory/Faulhaber's Formua.cpp: -------------------------------------------------------------------------------- 1 | //Faulhaber's Formua 2 | //faulhaber(n,k) = 1^k + 2^k + 3^k + ... + n^k modulo ANY number 3 | //Complexity : O(k^2) 4 | 5 | #include 6 | using namespace std; 7 | #define MAX 1005 8 | #define ll long long int 9 | const ll MOD = (1LL<<32); 10 | 11 | ll S[MAX][MAX]; 12 | 13 | void Stirling2(){ 14 | S[0][0] = 1; 15 | for(int i = 1; i < MAX; i++){ 16 | S[i][0] = 0; 17 | for(int j = 1; j <= i; j++){ 18 | S[i][j] = ((S[i - 1][j] * j) % MOD + S[i - 1][j - 1]) % MOD; 19 | } 20 | } 21 | } 22 | 23 | ll faulhaber(ll n, int k){ 24 | if (!k) return n % MOD; 25 | 26 | ll res = 0; 27 | for(int j = 0; j <= k; j++){ 28 | ll Div = j + 1; 29 | ll Mul = 1; 30 | ll r = n % Div + 1; 31 | if(r == Div) r = 0; 32 | 33 | for(int x = 0; x <= j; x++){ 34 | if(x == r) Mul *= (n - x + 1) / Div; 35 | else Mul *= (n - x + 1); 36 | Mul %= MOD; 37 | } 38 | 39 | res += (S[k][j] * Mul) % MOD; 40 | if(res >= MOD) res -= MOD; 41 | if(res < 0) res+= MOD; 42 | } 43 | return res; 44 | } 45 | -------------------------------------------------------------------------------- /Math/Number Theory/Fraction Binary Search.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Given f and N, finds the smallest fraction p/q in [0, 1] 3 | * such that f(p/q) is true, and p, q <= N. 4 | * May throw an exception from f if it finds an exact solution, 5 | * in which case N can be removed. 6 | * Time: O(log(N)) 7 | */ 8 | 9 | #include 10 | using namespace std; 11 | #define ll long long int 12 | 13 | struct Frac{ ll p, q;}; 14 | template Frac fracBS(F f, ll N){ 15 | bool dir = 1, A = 1, B = 1; 16 | Frac lo{0, 1}, hi{1, 1}; // Set hi to 1/0 to search (0, N] 17 | assert(!f(lo)); 18 | assert(f(hi)); 19 | 20 | while (A || B){ 21 | ll adv = 0, step = 1; // move hi if dir, else lo 22 | for (int si = 0; step; (step *= 2) >>= si) { 23 | adv += step; 24 | Frac mid{lo.p * adv + hi.p, lo.q * adv + hi.q}; 25 | if (abs(mid.p) > N || mid.q > N || dir == !f(mid)) { 26 | adv -= step; si = 2; 27 | } 28 | } 29 | hi.p += lo.p * adv; 30 | hi.q += lo.q * adv; 31 | dir = !dir; 32 | swap(lo, hi); 33 | A = B; B = !!adv; 34 | } 35 | return dir ? hi : lo; 36 | } 37 | 38 | int main(){ 39 | Frac ret = fracBS([](Frac f) {return 3*f.p >= f.q;}, 10); // {1,3} 40 | cout< 4 | using namespace std; 5 | #define ll long long int 6 | #define pll pair 7 | 8 | ll egcd(ll a, ll b, ll& x, ll& y){ 9 | if(!b) {y = 0, x = 1; return a;} 10 | ll g = egcd(b, a % b, y, x); 11 | y -= ((a / b) * x); 12 | return g; 13 | } 14 | 15 | pll GeneralCRT(pll a, pll b){ 16 | if(a.second < b.second) swap(a, b); 17 | ll x, y; egcd(a.second, b.second, x, y); 18 | ll g = a.second * x + b.second * y; 19 | ll l = a.second / g * b.second; 20 | if((b.first - a.first) % g) return {-1, -1}; // No Solution 21 | 22 | ll c = (b.first - a.first) % b.second; 23 | c = (c * x) % b.second; 24 | c = c / g * a.second; 25 | c += a.first; 26 | if(c < 0) c += l; 27 | return {c, l}; 28 | } 29 | -------------------------------------------------------------------------------- /Math/Number Theory/Geometric Sum.cpp: -------------------------------------------------------------------------------- 1 | //Computes the sum of a^1 + a^2 .... + a^n 2 | 3 | ll GeoSum(ll a, ll n){ 4 | ll sz = 0; 5 | ll ret = 0; 6 | ll mul = 1; 7 | int MSB = 63 - __builtin_clzll(n); 8 | 9 | while(MSB >= 0){ 10 | ret = ret * (1 + mul); mul = (mul * mul) % MOD; sz <<= 1; 11 | if( (n >> MSB) & 1) {mul = (mul * a) % MOD; ret += mul; sz++;} 12 | ret %= MOD; MSB--; 13 | } 14 | return ret; 15 | } 16 | -------------------------------------------------------------------------------- /Math/Number Theory/Integration (Romberg).cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define LD long double 4 | LD eps = 1e-8; 5 | 6 | LD f(LD x) {return sin(x);} 7 | 8 | LD romberg(LD a, LD b){ 9 | vectort; 10 | LD h = b-a; 11 | LD last, curr; 12 | int k = 1; 13 | int i = 1; 14 | t.push_back(h*(f(a)+f(b))/2); 15 | 16 | while(true){ 17 | last = t.back(); curr=0; 18 | LD x = a+h/2; 19 | for(int j=0;j 2 | using namespace std; 3 | typedef long double LD; 4 | const LD eps = 1e-6; 5 | 6 | LD f(LD x) {return sin(x);} 7 | 8 | inline LD simpson(LD fl, LD fr, LD fmid, LD l, LD r){ 9 | return (fl + fr + 4.0 * fmid) * (r-l) / 6.0; 10 | } 11 | 12 | LD Solve(LD slr, LD fl, LD fr, LD fmid, LD l, LD r){ 13 | LD mid = (l + r) / 2; 14 | LD fml = f((l + mid) / 2); 15 | LD fmr = f((mid + r) / 2); 16 | LD slm = simpson(fl,fmid,fml,l,mid); 17 | LD smr = simpson(fmid,fr,fmr,mid,r); 18 | if( fabs(slr-slm-smr) < eps) return slm + smr; 19 | return Solve(slm,fl,fmid,fml,l,mid) + Solve(smr,fmid,fr,fmr,mid,r); 20 | } 21 | 22 | LD integrate(LD l,LD r){ 23 | LD mid = (l+r) / 2; 24 | LD fl = f(l); 25 | LD fr = f(r); 26 | LD fmid = f(mid); 27 | LD slr = simpson(fl,fr,fmid,l,r); 28 | return Solve(slr,fl,fr,fmid,l,r); 29 | } 30 | -------------------------------------------------------------------------------- /Math/Number Theory/Interpolation (Lagrange - Optimized).cpp: -------------------------------------------------------------------------------- 1 | //Lagrange Polynomial 2 | //lagrange(n,k) = 1^k + 2^k + 3^k + ... + n^k modulo Prime 3 | //Complexity : O(k log (MOD)) 4 | 5 | #include 6 | using namespace std; 7 | #define MAX 1000010 // Upper Limit of k 8 | #define MOD 1000000007 9 | #define ll long long int 10 | 11 | namespace lgr{ 12 | short factor[MAX]; 13 | int P[MAX],S[MAX],ar[MAX],inv[MAX]; 14 | 15 | inline int Add(int a,int b) {return a + b >= MOD ? a + b - MOD : a + b;} 16 | inline int Sub(int a,int b) {return a - b < 0 ? a - b + MOD : a - b;} 17 | 18 | inline int bigMod(ll a,ll b){ 19 | ll res = 1; 20 | while(b){ 21 | if(b&1) res = (res * a) % MOD; 22 | a = (a * a) % MOD; b >>= 1; 23 | } 24 | return res; 25 | } 26 | 27 | int lagrange(ll n,int k){ 28 | if(!k) return ( n % MOD ); 29 | 30 | if(!inv[0]){ 31 | int x = 1; 32 | for(int i = 2; i < MAX; i++) x = (ll)x * i % MOD; 33 | inv[MAX-1] = bigMod(x,MOD-2); 34 | for(int i = MAX-2; i>=0; i--) inv[i] = (ll)inv[i+1] * (i+1) %MOD; 35 | for(int i = 0;i < MAX; i++) factor[i] = 0; 36 | for(int i = 4;i < MAX; i+=2) factor[i] = 2; 37 | for(int i = 3; i * i < MAX; i+=2){ 38 | if(!factor[i]) 39 | for(int j = i*i; j= 0; i--) S[i] = (n-i-1) % MOD * S[i+1] % MOD; 55 | 56 | int res = 0; 57 | for (int i = 0; i <= k; i++){ 58 | int x = (ll) ar[i] * P[i] % MOD * S[i] % MOD * inv[k - i] % MOD * inv[i] % MOD; 59 | if((k-i) & 1) res = Sub(res,x); 60 | else res = Add(res, x); 61 | } 62 | return res; 63 | } 64 | } 65 | 66 | int main(){ 67 | ll n; int k; 68 | scanf("%lld %d",&n,&k); 69 | printf("%d\n",lgr::lagrange(n, k)); 70 | } 71 | -------------------------------------------------------------------------------- /Math/Number Theory/Interpolation (Lagrange).cpp: -------------------------------------------------------------------------------- 1 | #define ll long long int 2 | #define MAXN 1000005 3 | #define MOD 1000000007 4 | 5 | ll bigMod(ll n, ll r) { 6 | if (r==0) return 1LL; 7 | ll ret = bigMod (n, r/2); 8 | ret = (ret * ret)% MOD; 9 | if (r %2 ) ret = (ret * n) % MOD; 10 | return ret; 11 | } 12 | 13 | ll Point[MAXN]; 14 | ll Fact[MAXN]; 15 | 16 | // Calculate first k + 1 points (0 to k) on the polynomial 17 | // where k = degree of the polynomial 18 | // Then find f(x) for any x using interpolation in O(n log(MOD)) 19 | 20 | ll interpolate(int n,ll x) { 21 | if(x <= n) return Point[x]; 22 | 23 | ll num = 1; 24 | for(int i=0; i<=n; i++) num=(num * (x-i)) % MOD; 25 | 26 | ll ret = 0; 27 | for(int i=0; i<=n; i++) { 28 | ll nn = (num * bigMod(x-i, MOD-2)) % MOD; 29 | ll dd = (Fact[n-i] * Fact[i]) % MOD; 30 | 31 | if((n-i) & 1) dd = MOD -dd; 32 | nn = (Point[i] * nn) % MOD; 33 | ret = (ret + nn * bigMod(dd, MOD-2))%MOD; 34 | } 35 | return ret; 36 | } 37 | -------------------------------------------------------------------------------- /Math/Number Theory/Interpolation (Newton).cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define ll long long int 4 | const int maxn = 5005; 5 | const int mod = 100019; 6 | 7 | inline ll add(ll x, ll y) {x += y; return x >= mod ? x - mod : x;} 8 | inline ll sub(ll x, ll y) {x -= y; return x < 0 ? x + mod : x;} 9 | inline ll mul(ll x, ll y) {return (x * y) % mod;} 10 | inline ll bigMod(ll x, ll y){ 11 | ll res = 1; 12 | while(y){ 13 | if(y & 1) res = mul(res, x); 14 | y >>= 1; x = mul(x, x); 15 | } 16 | return res; 17 | } 18 | inline ll inv(ll n) {return bigMod(n, mod-2);} 19 | inline ll Div(ll a, ll b) {return mul(a, inv(b));} 20 | 21 | struct Newton{ 22 | ll dp[maxn][maxn]; 23 | vector coX, coY; 24 | Newton() {coX.clear(); coY.clear();} 25 | 26 | void Insert(ll x, ll y){ 27 | coX.push_back(x); 28 | coY.push_back(y); 29 | int v = coX.size() - 1; 30 | 31 | dp[v][v] = y; 32 | for(int u=v-1; u>=0; u--){ 33 | dp[u][v] = sub(dp[u+1][v], dp[u][v-1]); 34 | dp[u][v] = Div(dp[u][v], sub(coX[v], coX[u])); 35 | } 36 | } 37 | 38 | ll Query(ll x){ 39 | ll pre = 1; 40 | ll ans = 0; 41 | for(int i=0; i= p(j)) 5 | Then we have : dp(n,1) = n and dp(n,j+1) = dp(n,j) - dp(n/p(j),j) 6 | Let p(k) be the smallest prime > sqrt(n), π(n) = dp(n,k) + k - 1 7 | Complexity : O(n ^ (2/3)) */ 8 | 9 | #include 10 | using namespace std; 11 | #define ll long long int 12 | 13 | const int LIM = 250; 14 | const int MAXP = 10000005; 15 | 16 | vector P; 17 | int prec[MAXP]; 18 | bool prime[MAXP]; 19 | 20 | void build(){ 21 | prime[2] = true; 22 | for(int i = 3; i < MAXP; i += 2) prime[i] = true; 23 | 24 | for(int i = 3; i*i < MAXP; i += 2){ 25 | if(!prime[i]) continue; 26 | for(int j = i*i; j < MAXP; j += i+i) prime[j] = false; 27 | } 28 | 29 | for(int i=2; i N) return N-1 - prec[N] + prec[P[K]]; 38 | 39 | bool ok = N < LIM * LIM && K < LIM; 40 | if (ok && dp[N][K]) return dp[N][K]; 41 | 42 | ll ret = N/P[K] - rec(N/P[K], K-1) + rec(N, K-1); 43 | 44 | if(ok) dp[N][K] = ret; 45 | return ret; 46 | } 47 | 48 | ll count_primes(ll N) { 49 | if(N < MAXP) return prec[N]; 50 | int K = prec[(int)sqrt(N) + 1]; 51 | return N-1 - rec(N, K) + prec[P[K]]; 52 | } 53 | -------------------------------------------------------------------------------- /Math/Number Theory/Maximum Divisors in Range.cpp: -------------------------------------------------------------------------------- 1 | //Finds x such that x <= n and has maximum number of divisors 2 | 3 | #include 4 | using namespace std; 5 | #define ULL unsigned long long int 6 | 7 | ULL n, res, idx; 8 | int p, primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71}; 9 | 10 | ULL mul(ULL a, ULL b){ 11 | ULL res = 0; 12 | while (b){ 13 | if (b & 1LL) res = (res + a); 14 | if (res > n) return 0; 15 | a = (a << 1LL); 16 | b >>= 1LL; 17 | } 18 | return res; 19 | } 20 | 21 | void backtrack(int i, int lim, ULL val, ULL r){ 22 | if ((r > res) || (r == res && val < idx)) res = r, idx = val; 23 | if (i == p) return; 24 | 25 | ULL x = val; 26 | for (int d = 1; d <= lim; d++){ 27 | x = mul(x, primes[i]); 28 | if (x == 0) return; 29 | backtrack(i + 1, d, x, r * (d + 1)); 30 | } 31 | } 32 | 33 | int main(){ 34 | /* Tested for <= 10^18 */ 35 | p = sizeof(primes) / sizeof(int); 36 | res = 0; 37 | scanf("%llu", &n); 38 | backtrack(0, 100, 1, 1); 39 | printf("%llu = %llu\n", idx, res); 40 | } 41 | -------------------------------------------------------------------------------- /Math/Number Theory/Pollard's Rho.cpp: -------------------------------------------------------------------------------- 1 | //Complexity : O(sqrt(Smallest Prime Factor of n)) = O(n^(1/4)) 2 | #include 3 | using namespace std; 4 | #define ll long long int 5 | #define pii pair 6 | 7 | ll Mul(ll a,ll b,ll Mod){ 8 | ll Ans=0; 9 | while(b){ 10 | if(b&1) {Ans+=a; if(Ans>=Mod) Ans-=Mod;} 11 | a+=a; if(a>=Mod) a-=Mod; 12 | b>>=1; 13 | } 14 | return Ans; 15 | } 16 | 17 | ll bigMod(ll n,ll r,ll Mod){ 18 | if(r==0) return 1LL; 19 | ll ret=bigMod(n,r/2,Mod); 20 | ret=Mul(ret,ret,Mod); 21 | if(r%2==1) ret=Mul(ret,n,Mod); 22 | return ret; 23 | } 24 | 25 | //Miller-Rabin 26 | bool witness(ll wit,ll n){ 27 | if(wit>=n) return false; 28 | 29 | int s=0; ll t=n-1; 30 | while(t%2==0) s++,t/=2; 31 | 32 | wit=bigMod(wit,t,n); 33 | if(wit==1 || wit==n-1) return false; 34 | 35 | for(int i=1;i &x) { 79 | if(n==1) return; 80 | else if(miller(n)) x.push_back(n); 81 | else{ 82 | ll d=get_factor(n); 83 | factorize(d,x); 84 | factorize(n/d,x); 85 | } 86 | } 87 | 88 | vectorfactorize(ll n) {vectorx; factorize(n, x); return x;} 89 | 90 | vectorFactors; 91 | vectorDivisors; 92 | void findDiv(int pos,ll val){ 93 | if(pos<0) {Divisors.push_back(val); return;} 94 | ll Now=1; 95 | for(int i=0;i<=Factors[pos].second;i++){ 96 | findDiv(pos-1,val*Now); 97 | Now=Now*Factors[pos].first; 98 | } 99 | } 100 | 101 | void findAllDiv(ll n){ 102 | vectornow=factorize(n); 103 | sort(now.begin(),now.end()); 104 | 105 | Factors.clear(); 106 | Divisors.clear(); 107 | int Count=1; 108 | for(int i=1;i factor; 16 | int php = phi(p); 17 | 18 | int tmp = php; 19 | for(int i = 2; i * i <= tmp; i++){ 20 | if(tmp % i == 0){ 21 | factor.push_back(i); 22 | while (tmp % i == 0) tmp /= i; 23 | } 24 | } 25 | if(tmp != 1) factor.push_back(tmp); 26 | 27 | for(int root=1; ; root++){ 28 | bool flag = true; 29 | for(int i = 0; i < factor.size(); ++i){ 30 | if(bigMod(root, php / factor[i], p) == 1){ 31 | flag = false; 32 | break; 33 | } 34 | } 35 | if (flag) return root; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Math/Number Theory/Range Congruence.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define ll long long int 4 | 5 | // finds minimum x such that L <= (A * x) % P <= R 6 | // constraint : 0 < A < P and 0 <= L <= R < P 7 | // returns -1 if no solution exists 8 | 9 | ll cdiv(ll x, ll y) {return (x+y-1)/y;} 10 | ll get(ll A, ll P, ll L, ll R) { 11 | if(A == 0) return L == 0 ? 0 : -1; 12 | ll c = cdiv(L, A); 13 | if(A*c <= R) return c; 14 | ll B = P % A; 15 | 16 | // P = k * A + B, L <= A * (x - K * y) - B * y <= R 17 | // => -R <= (B * y) % A <= -L 18 | auto y = get(B, A, A - R % A, A - L % A); 19 | return y == -1 ? y : cdiv(L + B * y, A) + P / A * y; 20 | } 21 | -------------------------------------------------------------------------------- /Math/Number Theory/Sieve (Linear).cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int MAX = 10000005; 4 | 5 | int phi[MAX], dvc[MAX], sig[MAX], mob[MAX]; 6 | int least[MAX], lstCnt[MAX], lstSum[MAX]; 7 | vector primes; 8 | 9 | void RunLinearSieve(int n) { 10 | n = max(n, 1); 11 | for(int i = 0; i <= n; i++) least[i] = lstCnt[i] = lstSum[i] = 0; 12 | 13 | primes.clear(); 14 | phi[1] = dvc[1] = sig[1] = mob[1] = 1; 15 | 16 | for(int i = 2; i <= n; i++){ 17 | if(least[i] == 0){ 18 | least[i] = i; lstCnt[i] = 1; lstSum[i] = 1 + i; 19 | phi[i] = i - 1; dvc[i] = 2; sig[i] = 1 + i; mob[i] = -1; 20 | primes.push_back(i); 21 | } 22 | for(int x : primes){ 23 | if(x > least[i] || i * x > n) break; 24 | least[i * x] = x; 25 | 26 | if(least[i] == x){ 27 | lstCnt[i * x] = lstCnt[i] + 1; 28 | lstSum[i * x] = 1 + x * lstSum[i]; 29 | 30 | phi[i * x] = phi[i] * x; 31 | dvc[i * x] = dvc[i] / (lstCnt[i] + 1) * (lstCnt[i * x] + 1); 32 | sig[i * x] = sig[i] / lstSum[i] * lstSum[i * x]; 33 | mob[i * x] = 0; 34 | } 35 | else{ 36 | lstCnt[i * x] = 1; 37 | lstSum[i * x] = 1 + x; 38 | 39 | phi[i * x] = phi[i] * (x - 1); 40 | dvc[i * x] = dvc[i] * 2; 41 | sig[i * x] = sig[i] * (1 + x); 42 | mob[i * x] = -mob[i]; 43 | } 44 | } 45 | } 46 | } 47 | 48 | int main(){ 49 | int n = 100; 50 | RunLinearSieve(n); 51 | for(int i=1;i<=n;i++) cout<= 0 && ((j>>t)&1) ) {j ^= 1 << t;--t;} 33 | if( t >= 0 ) { j ^= 1 << t; --t;} 34 | rev[i] = j; 35 | } 36 | } 37 | void fft(base *a, ll k) { 38 | build_rev(k); 39 | ll n = 1 << k; 40 | for(ll i=0; i i ) swap(a[i], a[rev[i]]); 41 | for(ll l = 2, llo = 1; l <= n; l += l, llo += llo) { 42 | if( w[llo].re == 0 && w[llo].im == 0 ) { 43 | ld angle = M_PI / llo; 44 | base ww( cosl(angle), sinl(angle) ); 45 | if( llo > 1 ) for(ll j = 0; j < llo; ++j) { 46 | if( j & 1 ) w[llo + j] = w[(llo+j)/2] * ww; 47 | else w[llo + j] = w[(llo+j)/2]; 48 | } 49 | else w[llo] = base(1, 0); 50 | } 51 | for(ll i = 0; i < n; i += l) { 52 | for(ll j=0; j& a, vector& b,vector& res) { 61 | ll k = 1; 62 | while( (1< 0 ) f1[(n - i)] = f1[i].conj(); 74 | } 75 | for(ll i=0; i VI; 5 | typedef complex CN; 6 | 7 | const double PI = acos(-1); 8 | const double eps = 1e-6; 9 | 10 | void FFT(vector&a,bool invert){ 11 | int n=a.size(); 12 | for(int i=1,j=0;i>1; 14 | for(;j>=bit;bit>>=1) j-=bit ; 15 | j+=bit ; 16 | if(i & a, vector & b, vector & res) { 42 | ll sq=sqrt(MOD); 43 | int n = 1; 44 | while (n < max (a.size(), b.size())) n <<= 1; 45 | n <<= 1; 46 | 47 | vector a1(n),a2(n),b1(n),b2(n); 48 | 49 | a.resize(n); 50 | b.resize(n); 51 | for(int i=0;ic1(n),c2(n),c3(n); 59 | 60 | for(int i=0;i 9 | using namespace std; 10 | #define ll long long int 11 | 12 | // to check if all value of A is zero 13 | bool AllZero( vector &A ){ 14 | for(int i=0;i &A,vector &B,vector &Ret ){ 22 | ll i,j,n = A.size(); 23 | Ret.resize(2*n); 24 | 25 | // check if any polynomial is zero 26 | if( AllZero( A ) || AllZero( B ) ) return; 27 | 28 | /* normal multiplication for n lower value 29 | limit should be power of 2 ( 16,32,64 ) 30 | any value can be used but 32 seems to be better */ 31 | if(n<=32){ 32 | for(i=0;i A1( A.begin()+n/2,A.end()); 38 | vector A0( A.begin(),A.begin()+n/2 ); 39 | vector B1( B.begin()+n/2,B.end()); 40 | vector B0( B.begin(),B.begin()+n/2 ); 41 | 42 | vector A1_B1,A0_B0; 43 | KaratSuva( A1,B1,A1_B1 ); 44 | KaratSuva( A0,B0,A0_B0 ); 45 | 46 | for(i=0;i A_B; 49 | KaratSuva( A1,B1,A_B ); 50 | for(i=0;i A, B; 64 | A.resize(n+1); B.resize(n+1); 65 | 66 | for(int i=0;i<=n;i++) scanf("%lld",&A[i]); 67 | for(int i=0;i<=n;i++) scanf("%lld",&B[i]); 68 | n++; 69 | while(n&(n-1)) A.push_back(0), B.push_back(0), n++; 70 | 71 | vector Ret; 72 | KaratSuva(A,B,Ret); 73 | while(Ret.back() == 0) Ret.pop_back(); 74 | } 75 | -------------------------------------------------------------------------------- /Math/Polynomial/NTT Applications.cpp: -------------------------------------------------------------------------------- 1 | /********************************* 2 | * polyinv(a, b, n) calculates b: b(z)a(z) = 1 (mod z^n) 3 | * polysqrt(a, b, n) calculates b: b(z)^2 = a(z) (mod z^n) 4 | * make sure ta[], tb[] has 2n spaces to be used. 5 | * in polysqrt(), if a[0] != 1 then discrete sqrt function is needed 6 | */ 7 | 8 | int ta[N], tb[N], tc[N]; 9 | void prepare(int n) { init(n >> 1); } 10 | void ntt(int *a, int n, ll f){ 11 | for(int i=0; i> 1); 19 | for(int i = 0; i < n; ++i) 20 | ta[i] = a[i], tb[i] = b[i]; 21 | for(int i = n; i < (n << 1); ++i) 22 | ta[i] = tb[i] = 0; 23 | n <<= 1; prepare(n); 24 | ntt(ta, n, 0), ntt(tb, n, 0); 25 | for(int i = 0; i < n; ++i) 26 | b[i] = (ll) tb[i] * (2 + mod - (ll) ta[i] * tb[i] % mod) % mod; 27 | ntt(b, n, 1); 28 | fill(b + (n >> 1), b + n, 0); 29 | } 30 | 31 | int inv2 = Pow(2, mod - 2); 32 | void polysqrt(int *a, int *b, int n) { 33 | if(n == 1) return void(b[0] = 1); // b[0] = x: x^2 \equiv a[0] 34 | polysqrt(a, b, n >> 1); 35 | polyinv(b, tb, n); 36 | for(int i = 0; i < n; ++i) 37 | ta[i] = a[i]; 38 | for(int i = n; i < (n << 1); ++i) 39 | ta[i] = tb[i] = 0; 40 | n <<= 1; prepare(n); 41 | ntt(ta, n, 0); ntt(tb, n, 0); 42 | for(int i = 0; i < n; ++i) 43 | ta[i] = (ll) ta[i] * tb[i] % mod; 44 | ntt(ta, n, 1); 45 | for(int i = 0; i < n; ++i) 46 | b[i] = (ll) inv2 * (ta[i] + b[i]) % mod; 47 | fill(b + (n >> 1), b + n, 0); 48 | } 49 | -------------------------------------------------------------------------------- /Math/Polynomial/NTT.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define ll long long int 4 | const ll mod = 786433; 5 | //For 10^9 + 7 : {7340033, 415236097, 463470593} 6 | 7 | inline ll add(ll x, ll y) {x += y; return x >= mod ? x - mod : x;} 8 | inline ll sub(ll x, ll y) {x -= y; return x < 0 ? x + mod : x;} 9 | inline ll mul(ll x, ll y) {return (x * y) % mod;} 10 | inline ll Pow(ll x, ll y){ 11 | ll res = 1; 12 | while(y){ 13 | if(y & 1) res = (res * x) % mod; 14 | y >>= 1, x = (x * x) % mod; 15 | } 16 | return res; 17 | } 18 | 19 | struct NTT{ 20 | vector A,B; 21 | vector root, rev; 22 | ll P,M,G; 23 | 24 | NTT(ll mod) {P = mod; G = 10;} 25 | void init(int n){ 26 | M = 1; int z = 0; 27 | while(M < n) M <<= 1, z++; 28 | M <<= 1; z++; 29 | 30 | A.resize(M); B.resize(M); 31 | root.resize(M); rev.resize(M); 32 | for(int i = 1; i < M; i++) rev[i] = rev[i >> 1] >> 1 | (i & 1) << (z - 1); 33 | 34 | int x = Pow(G, (P-1) / M); 35 | root[0] = 1; 36 | for(int i = 1; i < M; i++) root[i] = mul(root[i-1], x); 37 | } 38 | 39 | void ntransform(vector &a,ll f){ 40 | if(f) reverse(a.begin() + 1, a.end()); 41 | for (ll i = 0; i < M; i++) if(i < rev[i]) swap(a[i],a[rev[i]]); 42 | for (ll i = 1; i < M; i <<= 1){ 43 | for (ll j = 0, t = M / (i << 1); j < M; j += i << 1){ 44 | for (ll k = 0, l = 0; k < i; k++, l += t){ 45 | ll x = a[j + k]; 46 | ll y = mul(a[j + k + i], root[l]); 47 | a[j + k] = add(x, y); 48 | a[j + k + i] = sub(x, y); 49 | } 50 | } 51 | } 52 | 53 | if(f){ 54 | ll inv = Pow(M, P-2); 55 | for(ll i = 0; i < M; i++) a[i] = mul(a[i], inv); 56 | } 57 | } 58 | 59 | void multiply( vector &X, vector &Y, vector &res){ 60 | init(max(X.size(), Y.size())); 61 | for (ll i = 0; i < M; i++) A[i] = B[i] = 0; 62 | for (ll i = 0; i < X.size(); i++) A[i] = X[i]; 63 | for (ll i = 0; i < Y.size(); i++) B[i] = Y[i]; 64 | ntransform(A, 0); ntransform(B, 0); 65 | res.clear(); res.resize(M); 66 | for (ll i = 0; i < M; i++) res[i] = mul(A[i], B[i]); 67 | ntransform(res, 1); 68 | } 69 | } ntt(mod); 70 | -------------------------------------------------------------------------------- /Math/Polynomial/Online FFT Trick.cpp: -------------------------------------------------------------------------------- 1 | //Online FFT Calculation 2 | //a[i] = Sum of a[j]*b[i-j-1] for j in range [0,i-1] 3 | //Problem Link : https://www.codechef.com/problems/MANCBST 4 | 5 | const ll MAX = 1e5 + 9; 6 | ll a[2*MAX+10], b[2*MAX+10]; 7 | vector vec1,vec2,res; 8 | 9 | int main(){ 10 | b[0]=b[1]=1; 11 | for(int i=2;i< MAX;i++) b[i]=bigMod(i,i-1); 12 | 13 | a[0]=1; 14 | for(int i = 0; i < MAX; i++){ 15 | //+1 because of the format of the recurrence 16 | a[i + 0 + 1] += (a[i] * b[0]) % mod; 17 | a[i + 1 + 1] += (a[i] * b[1]) % mod; 18 | if(a[i + 0 + 1] >= mod) a[i + 0 +1]-=mod; 19 | if(a[i + 1 + 1] >= mod) a[i + 1 +1]-=mod; 20 | 21 | ll cc = 1; 22 | ll tmp = i; 23 | while(tmp && (tmp & 1) == 0){ 24 | tmp = tmp / 2; cc = cc * 2; 25 | vec1.clear(); vec2.clear(); 26 | 27 | for(int j=i-cc;j=mod) a[Beg+j]-=mod; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Math/Polynomial/Polynomial Root Check.cpp: -------------------------------------------------------------------------------- 1 | //Check whether x=k is a root of polynomial f(x) 2 | //Check whether f(k) = 0 efficiently 3 | 4 | #define ll long long int 5 | bool divisible_by_k(vectorarr,int k){ 6 | int n = arr.size(); 7 | if(arr[0] % k != 0) return false; 8 | for(int i=1;i 3 | using namespace std; 4 | const int MX = 300; 5 | int n, m; 6 | bool enabled[MX]; 7 | struct graph_t { 8 | int u[MX], v[MX]; 9 | void read(); 10 | vector getNonBridges(); 11 | } G1, G2; 12 | void graph_t::read() { 13 | for (int i = 0; i < m; i++) { 14 | ignore = scanf("%d %d", u + i, v + i); 15 | u[i]--; 16 | v[i]--; 17 | } 18 | } 19 | vector graph_t::getNonBridges() { 20 | static vector> G[MX]; 21 | for (int i = 0; i < n; i++) G[i].clear(); 22 | for (int i = 0; i < m; i++) { 23 | if (enabled[i] == false) continue; 24 | G[u[i]].emplace_back(v[i], i); 25 | G[v[i]].emplace_back(u[i], i); 26 | } 27 | static bool vis[MX]; 28 | static int up[MX], dep[MX]; 29 | fill(vis, vis + n, false); 30 | vector result; 31 | function dfs = [&](int v, int p, int d) { 32 | vis[v] = true; 33 | dep[v] = d; 34 | up[v] = d; 35 | for (auto& e : G[v]) { 36 | if (e.second == p) continue; 37 | 38 | if (vis[e.first] == false) { 39 | dfs(e.first, e.second, d + 1); 40 | if (up[e.first] <= d) result.push_back(e.second); 41 | } 42 | else { 43 | if (dep[e.first] < d) result.push_back(e.second); 44 | } 45 | 46 | up[v] = min(up[v], up[e.first]); 47 | } 48 | }; 49 | dfs(0, -1, 0); 50 | return result; 51 | } 52 | namespace ExchangeGraph { 53 | vector G[MX]; 54 | void clear() { for (int i = 0; i < m; i++) G[i].clear(); } 55 | void addEdge(int u, int v) { G[u].push_back(v); } 56 | bool findAugmentalPath(vector from, vector to) { 57 | vector par(m, -1), dist(m), queue; 58 | for (int v : from) { 59 | queue.push_back(v); par[v] = -2; dist[v] = 0; 60 | } 61 | for (size_t i = 0; i < queue.size(); i++) { 62 | int v = queue[i]; 63 | for (int u : G[v]) { 64 | if (par[u] == -1) { 65 | queue.push_back(u); par[u] = v; dist[u] = dist[v] + 1; 66 | } 67 | } 68 | } 69 | int target = -1; 70 | for (int v : to) { 71 | if (par[v] == -1) continue; 72 | if (target == -1 || dist[v] < dist[target]) target = v; 73 | } 74 | if (target != -1) { 75 | while (target != -2) { 76 | enabled[target] = not enabled[target]; target = par[target]; 77 | } 78 | return true; 79 | } 80 | return false; 81 | } 82 | } 83 | int main() { 84 | int T; 85 | ignore = scanf("%d", &T); 86 | while (T--) { 87 | ignore = scanf("%d %d", &n, &m); 88 | G1.read(); 89 | G2.read(); 90 | fill(enabled, enabled + m, true); 91 | int ans = m; 92 | while (true) { 93 | ExchangeGraph::clear(); 94 | auto Y1 = G1.getNonBridges(); 95 | auto Y2 = G2.getNonBridges(); 96 | if (ExchangeGraph::findAugmentalPath(Y1, Y2)) { ans--; continue; } 97 | for (int e = 0; e < m; e++) { 98 | if (enabled[e]) continue; 99 | enabled[e] = true; 100 | auto edgesTo = G1.getNonBridges(); 101 | auto edgesFrom = G2.getNonBridges(); 102 | enabled[e] = false; 103 | for (int v : edgesTo) ExchangeGraph::addEdge(e, v); 104 | for (int v : edgesFrom) ExchangeGraph::addEdge(v, e); 105 | } 106 | if (ExchangeGraph::findAugmentalPath(Y1, Y2)) { ans--; } 107 | else { break; } 108 | } 109 | printf("%d\n", ans); 110 | } 111 | return 0; 112 | } 113 | -------------------------------------------------------------------------------- /Notes/Bernoulli.cpp: -------------------------------------------------------------------------------- 1 | // Bernoulli Number : We have - 2 | // B(k) = sum over m in [0,k] (-1)^m * m! / (m+1) * Str2(k,m) 3 | -------------------------------------------------------------------------------- /Notes/Catalan.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Total number of paths from point P(x1, y1) 3 | to point Q(x2, y2) where x2 >= x1 and y2 >= y1 : 4 | Let x = x2 - x1 and y = y2 - y1. Then ans = C(x+y, x). 5 | 6 | * Total number of paths from point P(x1, y1) to point Q(x2, y2) 7 | where x2 >= x1 and y2 >= y1 without crossing the line X = Y + c : 8 | Let x = x2 - x1 and y = y2 - y1. Then ans = C(x+y, x) - C(x+y, x+c-1). 9 | Special Case : x = n, y = n, c = 0, then ans = C(2n, n) - C(2n, n-1) [Catalan] 10 | 11 | * Catalan triangle : Total number of permutation having n X and k Y 12 | so that Count(X)-Count(Y)>=0 in any prefix (Non-negative Partial Sum) : 13 | ans = C(n+k,k) - C(n+k, k-1) 14 | 15 | * Catalan trapezoid : Total number of permutation having n X and k Y 16 | so that Count(Y) - Count(X) < m in any prefix, then : 17 | when 0 <= k < m, ans = C(n+k,k) 18 | when m <= k <= n+m-1, ans = C(n+k,k) - C(n+k,k-m) 19 | when k > n+m-1, ans = 0 20 | */ 21 | -------------------------------------------------------------------------------- /Notes/Euler's Therorem: -------------------------------------------------------------------------------- 1 | * if x and m coprime, x ^ phi(m) = 1 (mod m) 2 | * if x and m coprime, x ^ n = x ^ (n mod phi(m)) (mod m) 3 | * if n >= log2(m), x ^ n = x ^ (phi(m) + n mod phi(m)) (mod m) 4 | * phi( phi(m) ) <= m / 2 5 | -------------------------------------------------------------------------------- /Notes/Eulerian.cpp: -------------------------------------------------------------------------------- 1 | * Eulerian number of the first kind : 2 | 3 | * A1(n,k) is the number of permutations of 1 to n in which 4 | exactly k elements are greater than their previous element. 5 | Then : A1(n,k) = (n-k) * A1(n-1,k-1) + (k+1) * A1(n-1,k). 6 | 7 | * Eulerian number of the second kind : 8 | 9 | * Number of permutations of the multiset {1,1,2,2,..,n,n} 10 | such that for each k, all the numbers appearing between the 11 | two occurrences of k are greater than k = (2n - 1) ! 12 | 13 | * A2(n,k) is the number of such permutations with k ascents. 14 | Then : A2(n,k) = (2n-k-1) * A2(n-1, k-1) + (k+1) * A2(n-1,k) 15 | -------------------------------------------------------------------------------- /Notes/Linear Algebra.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnikSarker/ACM-Library/aeb469c565e5f84e5ccf08ab1304e45dda4d6297/Notes/Linear Algebra.pdf -------------------------------------------------------------------------------- /Notes/Notebook (KTH).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnikSarker/ACM-Library/aeb469c565e5f84e5ccf08ab1304e45dda4d6297/Notes/Notebook (KTH).pdf -------------------------------------------------------------------------------- /Notes/Notebook (NTU).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnikSarker/ACM-Library/aeb469c565e5f84e5ccf08ab1304e45dda4d6297/Notes/Notebook (NTU).pdf -------------------------------------------------------------------------------- /Notes/Stirling.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Number of permutations of n elements with k disjoint cycles 3 | = Str1(n,k) = (n-1) * Str1(n-1,k) + Str1(n-1,k-1) 4 | 5 | * n! = Sum(Str1(n,k)) (for all 0 <= k <= n). 6 | 7 | * Ways to partition n labelled objects into k unlabelled 8 | subsets = Str2(n,k) = k * Str2(n-1,k) + Str2(n-1,k-1) 9 | 10 | * Parity of Str2(n,k) : ( (n-k) & Floor((k-1)/2) ) == 0) 11 | 12 | * Ways to partition n labelled objects into k unlabelled 13 | subsets, with each subset containing at least r elements : 14 | SR(n,k) = k * SR(n-1,k) + C(n-1,r-1) * SR(n-r,k-1) 15 | 16 | * Number of ways to partition n labelled objects 1,2,3, ... n 17 | into k non-empty subsets so that for any integers i and j in a 18 | given subset |i-j| >= d : Str2(n-d+1, k-d+1), n >= k >= d 19 | */ 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #### This team library is not only a collection of C++ codes, but also a diary of our 2 | #### many sleepless nights, a silent witness of our excitements and stuggles, a loyal 3 | #### companion in our difficult fights and a homage to all those who helped us learn. 4 | 5 | 6 | # Contributors: 7 | * Hasin Rayhan Dewan Dhruboo 8 | * Saad Muhammed Junayed 9 | * Anik Sarker 10 | 11 | ### 1st Runners-up : ACM ICPC Dhaka Regional Onsite 2019 (BUET Gifted Hypocrites) 12 | ### Champion : ACM ICPC Dhaka Regional Online Preliminary 2018 (BUET Upside_Down) 13 | -------------------------------------------------------------------------------- /String/Aho Corasick.cpp: -------------------------------------------------------------------------------- 1 | // Aho-Corasick 2 | // Complexity : |Text| + Sum of all |Pattern| + O(number of Occurrences) 3 | // if occurrence positions needed, Worst Case Complexity : (SumLen) Root (SumLen) 4 | #include 5 | using namespace std; 6 | const int MAXT = 1000005; // Length of Text 7 | const int MAXP = 1000005; // Sun of all |Pattern| 8 | const int MAXQ = 1000005; // Number of Patterns 9 | 10 | int n; 11 | map Next[MAXP]; 12 | int Root; // AC automaton Root 13 | int Nnode; // Total node count 14 | int Link[MAXP]; // failure links 15 | int Len[MAXP]; // Len[i] = length of i-th pattern 16 | vector End[MAXP]; // End[i] = indices of patterns those end in node i 17 | // vector Occ[MAX]; // Occ[i] = occurrences of i-th pattern 18 | vector edgeLink[MAXP]; 19 | vector perNodeText[MAXP]; 20 | 21 | int in[MAXQ], out[MAXQ]; 22 | int euler[MAXT]; 23 | int Time; 24 | 25 | void Clear(int node){ 26 | Next[node].clear(); 27 | End[node].clear(); 28 | edgeLink[node].clear(); 29 | perNodeText[node].clear(); 30 | } 31 | 32 | void init(){ 33 | Time = 0; 34 | Root = Nnode = 0; 35 | Clear(Root); 36 | } 37 | 38 | void insertword(string p,int ind){ 39 | int len = p.size(); 40 | int now = Root; 41 | for(int i=0; i q; 53 | Link[0] = -1; 54 | q.push(0); 55 | while(!q.empty()){ 56 | int u = q.front(); 57 | q.pop(); 58 | for(auto edge : Next[u]){ 59 | char ch = edge.first; 60 | int v = edge.second; 61 | int j = Link[u]; 62 | 63 | while(j != -1 && !Next[j][ch]) j = Link[j]; 64 | if(j != -1) Link[v] = Next[j][ch]; 65 | else Link[v] = 0; 66 | 67 | q.push(v); 68 | edgeLink[Link[v]].push_back(v); 69 | // for(int x : End[Link[v]]) End[v].push_back(x); 70 | } 71 | } 72 | } 73 | 74 | void traverse(string s){ 75 | int len = s.size(); 76 | int now = Root; 77 | for(int i = 0; i < len; i++) { 78 | while(now != -1 && !Next[now][s[i]]) now = Link[now]; 79 | if(now!=-1) now = Next[now][s[i]]; 80 | else now = 0; 81 | perNodeText[now].push_back(i+1); // using 1 based indexing for text indices 82 | // for(int x=0;x 5 | using namespace std; 6 | typedef long long ll; 7 | const int MAX = 100009; 8 | ll mods[2] = {1000000007, 1000000009}; 9 | //Some back-up primes: 1072857881, 1066517951, 1040160883 10 | ll bases[2] = {137, 281}; 11 | ll pwbase[3][MAX]; 12 | 13 | void Preprocess(){ 14 | pwbase[0][0] = pwbase[1][0] = 1; 15 | for(ll i = 0; i < 2; i++){ 16 | for(ll j = 1; j < MAX; j++){ 17 | pwbase[i][j] = (pwbase[i][j - 1] * bases[i]) % mods[i]; 18 | } 19 | } 20 | } 21 | 22 | struct Hashing{ 23 | ll hsh[2][MAX]; 24 | string str; 25 | 26 | Hashing(){} 27 | Hashing(string _str) {str = _str; memset(hsh, 0, sizeof(hsh)); build();} 28 | 29 | void Build(){ 30 | for(ll i = str.size() - 1; i >= 0; i--){ 31 | for(int j = 0; j < 2; j++){ 32 | hsh[j][i] = (hsh[j][i + 1] * bases[j] + str[i]) % mods[j]; 33 | hsh[j][i] = (hsh[j][i] + mods[j]) % mods[j]; 34 | } 35 | } 36 | } 37 | 38 | pair GetHash(ll i, ll j){ 39 | assert(i <= j); 40 | ll tmp1 = (hsh[0][i] - (hsh[0][j + 1] * pwbase[0][j - i + 1]) % mods[0]) % mods[0]; 41 | ll tmp2 = (hsh[1][i] - (hsh[1][j + 1] * pwbase[1][j - i + 1]) % mods[1]) % mods[1]; 42 | if(tmp1 < 0) tmp1 += mods[0]; 43 | if(tmp2 < 0) tmp2 += mods[1]; 44 | return make_pair(tmp1, tmp2); 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /String/Hashing (2D).cpp: -------------------------------------------------------------------------------- 1 | #define MAX 2005 2 | #define ll long long int 3 | 4 | int Base[2] = {773,709}; 5 | int Mod[2] = {281559881,398805713}; 6 | int InvBase[2][2]; 7 | 8 | int Pow[MAX][2][2],Inv[MAX][2][2]; 9 | int PowCell[MAX][MAX][2],InvCell[MAX][MAX][2]; 10 | 11 | int A[MAX][MAX],B[MAX][MAX]; 12 | int cA[MAX][MAX][2],cB[MAX][MAX][2]; 13 | 14 | inline int cMod(int x,int mod){ 15 | while(x >= mod) x-=mod; 16 | while(x < 0) x+=mod; 17 | return x; 18 | } 19 | 20 | int bigMod(int n,int r,int mod){ 21 | if(r==0) return 1; 22 | ll ret = bigMod(n, r/2, mod); 23 | ret = (ret*ret) % mod; 24 | if(r&1) ret = (ret*n)% mod; 25 | return ret; 26 | } 27 | int invMod(int n,int mod) {return bigMod(n,mod-2,mod);} 28 | 29 | void Preprocess(){ 30 | for(int b=0;b<2;b++) for(int m=0;m<2;m++) 31 | Pow[0][b][m] = Inv[0][b][m] = 1; 32 | for(int b=0;b<2;b++) for(int m=0;m<2;m++) for(int i=1;i Query(int cM[MAX][MAX][2],int x1,int y1,int x2,int y2){ 58 | ll Sum[2]; 59 | for(int m=0;m<2;m++){ 60 | Sum[m] = cB[x2][y2][m]-cB[x2][y1-1][m]-cB[x1-1][y2][m]+cB[x1-1][y1-1][m]; 61 | Sum[m] = cMod(Sum[m],Mod[m]); 62 | Sum[m] = (InvCell[x1-1][y1-1][m]*1LL*Sum[m]) % Mod[m]; 63 | } 64 | return {Sum[0],Sum[1]}; 65 | } 66 | -------------------------------------------------------------------------------- /String/KMP Fail + Z-Algo.cpp: -------------------------------------------------------------------------------- 1 | //0-indexed string s[0...n-1] 2 | //fail[i] = maximum x such that s[0....x-1] matches with s[i-x+1...i] 3 | int fail[MAX]; 4 | void build_failure(string s){ 5 | int n=s.size(); 6 | for(int i=1;i0 && s[i]!=s[j]) j=fail[j-1]; 9 | if(s[i]==s[j]) j++; 10 | fail[i]=j; 11 | } 12 | } 13 | 14 | int KMPSearch(string txt, string pat){ 15 | int Count = 0; 16 | int i = 0; 17 | int j = 0; 18 | while(i < txt.size()){ 19 | if(txt[i] == pat[j]) i++, j++; 20 | 21 | if(j == pat.size()) Count++, j = fail[j - 1]; 22 | else if(i < txt.size() && txt[i] != pat[j]){ 23 | if(j != 0) j = fail[j - 1]; 24 | else i++; 25 | } 26 | } 27 | return Count; 28 | } 29 | 30 | //0-indexed string s[0...n-1] 31 | //z[i] = maximum x such that s[0....x-1] matches with s[i..i+x-1] 32 | int z[MAX]; 33 | void zAlgo(string s){ 34 | int L=0,R=0; 35 | int n=s.size(); 36 | for(int i=1;iR) {L=R=i; while(R 2 | using namespace std; 3 | #define MAX 1000005 4 | 5 | int wa[MAX],wb[MAX],wv[MAX],Ws[MAX]; 6 | int cmp(int *r,int a,int b,int l) {return r[a]==r[b] && r[a+l]==r[b+l];} 7 | 8 | //(1-indexed) sa[i] = starting position (0...n-1) of ith lexicographically smallest suffix in s 9 | //(0-indexed) Rank[i] = lexicographical rank of s[i....n-1] ((i+1)th suffix by position) 10 | //LCP[i] = longest common prefix of sa[i] & sa[i-1] 11 | int sa[MAX],Rank[MAX],LCP[MAX]; 12 | 13 | //Suffix Array (O(nlogn)) 14 | //m = maximum possible ASCII value of a string character (alphabet size) 15 | //also, m = maximum number of distinct character in string (when compressed) 16 | void buildSA(string s,int* sa,int n,int m){ 17 | int i,j,p,*x=wa,*y=wb,*t; 18 | for(i=0; i=0; i--) sa[--Ws[x[i]]]=i; 22 | for(j=1,p=1; p=j) y[p++]=sa[i]-j; 25 | for(i=0; i=0; i--) sa[--Ws[wv[i]]]=y[i]; 30 | for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i