├── README.md ├── main.pdf ├── scripts └── convert.py └── src ├── Computational Geometry ├── 2D_Geometry_Base - Full.cpp ├── 2D_Geometry_Base.cpp ├── 3D Convex Cut.cpp ├── 3D Convex Hull.cpp ├── 3D_Geometry_Base.cpp ├── Circle.cpp ├── CircleKCover.cpp ├── ClosestPair.cpp ├── Convex Hull && Convex Diameter.cpp ├── DistOnBall.cpp ├── DistOnCuboid.cpp ├── Farmland.cpp ├── Fermat Point Of A Quadrilateral.cpp ├── Half Plane Intersection.cpp ├── Max Area Empty Convex Hull.cpp ├── MinBall.cpp ├── Point.cpp ├── Polygon Circle Intersection.cpp ├── Polygon.cpp ├── Voronoi.cpp └── isPL.cpp ├── Data Structure ├── Dynamic Convex Hull (Insertion Only).cpp ├── Functional Treap.cpp ├── KDTree.cpp ├── KDTree_2.cpp ├── Leftist Heap.cpp ├── Link Cut Tree.cpp ├── Treap.cpp ├── TreeDecomposition - Full.cpp ├── TreeDecomposition.cpp └── Usage Of Rope.cpp ├── Graph Theory ├── Blossom Algorithm.cpp ├── Dynamic MST(Offline).cpp ├── EulerianWalk.cpp ├── Highest Level Preflow-Push.cpp ├── HopcroftKarp.cpp ├── K-shortest Path (Repeat is allowed).cpp ├── K-shortest Path (Repeat is not allowed).cpp ├── KM.cpp ├── MCS.cpp ├── MaxClique.cpp ├── MaxCliqueCounting.cpp ├── Maxflow.cpp ├── Minimum Optimum branchings.cpp ├── StableMatching.cpp ├── Stoer-Wagner.cpp └── TwoSat SCC.cpp ├── Math ├── ExGcd.cpp ├── FFT.cpp ├── FFT_Integer.cpp ├── GaussElimination.cpp ├── HighterResidue.cpp ├── Linear Congruence.cpp ├── Linear Recursive Equation.cpp ├── MillerRabin.cpp ├── ModLog.cpp ├── Nth Residue.cpp ├── Pell.cpp ├── PollardRho.cpp ├── PrimitiveRoot.cpp ├── QuadraticResidue.cpp ├── Romberg.cpp ├── Root Of Polynomial.cpp ├── SimplexCpp.cpp └── SimplexJava.java ├── Others ├── C Split.cpp ├── DotsBelowLine.cpp ├── Expression Evaluation.cpp ├── Java Polynomial.java ├── Josephus.cpp ├── K Disjoint LIS.cpp ├── LCSFast.cpp ├── Long Long Multi and Mod.cpp ├── Manhattan MST.cpp ├── MinimalColoring.cpp ├── Multiple Cover - Full.cpp ├── Multiple Cover.cpp ├── Zeller.cpp ├── next nCk.cpp └── nextPermutation.java ├── String Related ├── Aho Corasick Automaton.cpp ├── KMP.cpp ├── Manacher.cpp ├── Minimial Representation Of A Cyclic String.cpp ├── Palindrome Automaton.cpp ├── Suffix Array Backup.cpp ├── Suffix Array.cpp └── Suffix Automaton.cpp └── Templates ├── cpp_template.cpp ├── java_template - Full.java ├── java_template.java ├── pai.sh └── vimrc.cpp /README.md: -------------------------------------------------------------------------------- 1 | Standard Code Library for *Call It Magic* 2 | ========= 3 | 4 | We are the *Call It Magic*. We competed for The ACM-ICPC International Collegiate Programming Contest. 5 | 6 | Codes in the template are often narrowed in a single line to fulfill the page nunmber limitation, please ignore the coding style :) 7 | 8 | How to Compile 9 | ========== 10 | 11 | ``` {bash} 12 | $ python scripts/convert.py # convert C++ / Java code to LaTeX lstlisting 13 | $ cd src 14 | $ xelatex main.tex 15 | $ xelatex main.tex 16 | $ mv main.pdf .. 17 | $ rm *.aux *.log *.out *.toc 18 | $ cd .. 19 | ``` 20 | 21 | License 22 | ========== 23 | 24 | Do What The Fuck You Want To Public License ([WTFPL](http://www.wtfpl.net/)) 25 | 26 | Contributors 27 | ========== 28 | 29 | Junru Shao, Tiancheng Xie, Bicheng Gao 30 | 31 | -------------------------------------------------------------------------------- /main.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junrushao/ACM-ICPC-Standard-Code-Library/8c471c4417bc2bbab6d56cbd5d4dd45fdd413aa1/main.pdf -------------------------------------------------------------------------------- /scripts/convert.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | @Author JunruShao(yz_sjr@163.com) 4 | """ 5 | 6 | import os 7 | 8 | def checkExist(f): 9 | f = os.path.splitext(f)[0] 10 | return os.path.exists(f + ".cpp") or os.path.exists(f + ".java") or os.path.exists(f + ".py") or os.path.exists(f + ".sh") 11 | 12 | def processFile(f): 13 | if os.path.isfile(f) and not f.startswith("."): 14 | if f.endswith((".cpp", ".java", ".sh", ".py")): 15 | print("File " + f) 16 | toWrite = "\\begin{lstlisting}" 17 | toWrite += "\n" 18 | with open(f, "r") as infile: 19 | for line in infile.readlines(): 20 | line = line.replace(" ", " ") 21 | toWrite += line 22 | toWrite += "\n" 23 | toWrite += "\\end{lstlisting}" 24 | with open(os.path.splitext(f)[0] + ".tex", "w") as outfile: 25 | outfile.write(toWrite) 26 | 27 | if f.endswith((".tex")) and not checkExist(f): 28 | print("File " + f) 29 | toWrite = "" 30 | with open(f, "r") as infile: 31 | for line in infile.readlines(): 32 | line = line.replace(" ", " ") 33 | line = line.replace("。", ". ") 34 | line = line.replace(",", ", ") 35 | line = line.replace("(", "( ") 36 | line = line.replace(")", ") ") 37 | line = line.replace("!", "! ") 38 | line = line.replace("?", "? ") 39 | toWrite += line 40 | with open(f, "w") as outfile: 41 | outfile.write(toWrite) 42 | 43 | def walkFolder(depth): 44 | for f in os.listdir(os.getcwd()): 45 | if os.path.isdir(f): 46 | if not f.startswith("."): 47 | print("Enter " + f) 48 | os.chdir(f) 49 | walkFolder(depth + 1) 50 | os.chdir("..") 51 | print("Exit") 52 | else: 53 | # if not (depth == 0 and (f == "convert.py" or f == "main.tex")): 54 | if not (depth == 0 and (f == "convert.py" or f == "convert2.7.py")): 55 | processFile(f) 56 | 57 | def main(): 58 | walkFolder(0) 59 | 60 | if __name__ == "__main__": 61 | main() 62 | -------------------------------------------------------------------------------- /src/Computational Geometry/2D_Geometry_Base - Full.cpp: -------------------------------------------------------------------------------- 1 | const double PI = 3.14159265358979323846264338327950288; 2 | int sign(const double &a, const double &eps = EPS) { return a < -eps ? -1 : int(a > eps); } 3 | double sqr(const double &x) { return x * x; } 4 | double Sqrt(const double &x) { return x < 0 ? 0 : sqrt(x); } 5 | double arcSin(const double &a) { 6 | if (a <= -1.0) return -PI / 2; 7 | if (a >= 1.0) return PI / 2; 8 | return asin(a); 9 | } 10 | double arcCos(const double &a) { 11 | if (a <= -1.0) return PI; 12 | if (a >= 1.0) return 0; 13 | return acos(a); 14 | } 15 | 16 | struct point { 17 | double x, y; 18 | point() : x(0.0), y(0.0) {} 19 | point(const double &x, const double &y) : x(x), y(y) {} 20 | point operator +(const point &rhs) const { return point(x + rhs.x, y + rhs.y); } 21 | point operator -(const point &rhs) const { return point(x - rhs.x, y - rhs.y); } 22 | point operator *(const double &k) const { return point(x * k, y * k); } 23 | point operator /(const double &k) const { return point(x / k, y / k); } 24 | double len() const { return hypot(x, y); } 25 | double norm() const { return x * x + y * y; } 26 | point unit() const { double k = len(); return point(x / k, y / k); } 27 | point rot(const double &a) const { // `counter-clockwise` 28 | return point(x * cos(a) - y * sin(a), x * sin(a) + y * cos(a)); 29 | } 30 | point rot90() const { return point(-y, x); } // `counter-clockwise` 31 | point project(const point &p1, const point &p2) const { 32 | const point &q = *this; return p1 + (p2 - p1) * (dot(p2 - p1, q - p1) / (p2 - p1).norm()); 33 | } 34 | friend double dot(const point &a, const point &b) { return a.x * b.x + a.y * b.y; } 35 | friend double det(const point &a, const point &b) { return a.x * b.y - a.y * b.x; } 36 | bool onSeg(const point &a, const point &b) const { // `a, b inclusive` 37 | const point &c = *this; return sign(dot(a - c, b - c)) <= 0 && sign(det(b - a, c - a)) == 0; 38 | } 39 | double distLP(const point &p1, const point &p2) const { // `dist from *this to line p1->p2` 40 | const point &q = *this; return fabs(det(p2 - p1, q - p1)) / (p2 - p1).len(); 41 | } 42 | double distSP(const point &p1, const point &p2) const { // `dist from *this to segment [p1, p2]` 43 | const point &q = *this; 44 | if (dot(p2 - p1, q - p1) < EPS) return (q - p1).len(); 45 | if (dot(p1 - p2, q - p2) < EPS) return (q - p2).len(); 46 | return distLP(p1, p2); 47 | } 48 | bool inAngle(const point &p1, const point &p2) const { // `det(p1, p2) $\ge$ 0` 49 | const point &q = *this; return det(p1, q) > -EPS && det(p2, q) < EPS; 50 | } 51 | }; 52 | bool lineIntersect(const point &a, const point &b, const point &c, const point &d, point &e) { 53 | double s1 = det(c - a, d - a), s2 = det(d - b, c - b); 54 | if (!sign(s1 + s2)) return false; 55 | e = (b - a) * (s1 / (s1 + s2)) + a; 56 | return true; 57 | } 58 | bool segIntersect(const point &a, const point &b, const point &c, const point &d, point &e) { 59 | double s1 = det(c - a, d - a), s2 = det(d - b, c - b); 60 | if (!sign(s1 + s2)) return false; 61 | e = (b - a) * (s1 / (s1 + s2)) + a; 62 | return e.onSeg(a, b) && e.onSeg(c, d); 63 | } 64 | int iCnt; 65 | int segIntersectCheck(const point &a, const point &b, const point &c, const point &d, point &o) { 66 | static double s1, s2, s3, s4; 67 | int d1 = sign(s1 = det(b - a, c - a)), d2 = sign(s2 = det(b - a, d - a)); 68 | int d3 = sign(s3 = det(d - c, a - c)), d4 = sign(s4 = det(d - c, b - c)); 69 | if ((d1 ^ d2) == -2 && (d3 ^ d4) == -2) { 70 | o = (c * s2 - d * s1) / (s2 - s1); return true; 71 | } iCnt = 0; 72 | if (d1 == 0 && c.onSeg(a, b)) o = c, ++iCnt; 73 | if (d2 == 0 && d.onSeg(a, b)) o = d, ++iCnt; 74 | if (d3 == 0 && a.onSeg(c, d)) o = a, ++iCnt; 75 | if (d4 == 0 && b.onSeg(c, d)) o = b, ++iCnt; 76 | return iCnt ? 2 : 0; // `不相交返回0, 严格相交返回1, 非严格相交返回2` 77 | } 78 | struct circle { 79 | point o; double r, rSqure; 80 | circle() : o(), r(0.0), rSqure(0.0) {} 81 | circle(const point &o, const double &r) : o(o), r(r), rSqure(r * r) {} 82 | bool inside(const point &a) { return (a - o).len() < r + EPS; } // `非严格` 83 | bool contain(const circle &b) const { return sign(b.r + (o - b.o).len() - r) <= 0; } // `非严格` 84 | bool disjunct(const circle &b) const { return sign(b.r + r - (o - b.o).len()) <= 0; } // `非严格` 85 | int isCL(const point &p1, const point &p2, point &a, point &b) const { 86 | double x = dot(p1 - o, p2 - p1); 87 | double y = (p2 - p1).norm(); 88 | double d = x * x - y * ((p1 - o).norm() - rSqure); 89 | if (d < -EPS) return 0; 90 | if (d < 0) d = 0; 91 | point q1 = p1 - (p2 - p1) * (x / y); 92 | point q2 = (p2 - p1) * (sqrt(d) / y); 93 | a = q1 - q2; b = q1 + q2; 94 | return q2.len() < EPS ? 1 : 2; 95 | } 96 | int tanCP(const point &p, point &a, point &b) const { // `返回切点, 注意可能与 $p$ 重合` 97 | double x = (p - o).norm(); 98 | double d = x - rSqure; 99 | if (d < -EPS) return 0; 100 | if (d < 0) d = 0; 101 | point q1 = (p - o) * (rSqure / x); 102 | point q2 = ((p - o) * (-r * sqrt(d) / x)).rot90(); 103 | a = o + (q1 - q2); b = o + (q1 + q2); 104 | return q2.len() < EPS ? 1 : 2; 105 | } 106 | }; 107 | 108 | bool checkCrossCS(const circle &cir, const point &p1, const point &p2) { // `非严格` 109 | const point &c = cir.o; 110 | const double &r = cir.r; 111 | return c.distSP(p1, p2) < r + EPS && (r < (c - p1).len() + EPS || r < (c - p2).len() + EPS); 112 | } 113 | 114 | bool checkCrossCC(const circle &cir1, const circle &cir2) { // `非严格` 115 | const double &r1 = cir1.r, &r2 = cir2.r; 116 | double d = (cir1.o - cir2.o).len(); 117 | return d < r1 + r2 + EPS && fabs(r1 - r2) < d + EPS; 118 | } 119 | 120 | int isCC(const circle &cir1, const circle &cir2, point &a, point &b) { 121 | const point &c1 = cir1.o, &c2 = cir2.o; 122 | double x = (c1 - c2).norm(); 123 | double y = ((cir1.rSqure - cir2.rSqure) / x + 1) / 2; 124 | double d = cir1.rSqure / x - y * y; 125 | if (d < -EPS) return 0; 126 | if (d < 0) d = 0; 127 | point q1 = c1 + (c2 - c1) * y; 128 | point q2 = ((c2 - c1) * sqrt(d)).rot90(); 129 | a = q1 - q2; b = q1 + q2; 130 | return q2.len() < EPS ? 1 : 2; 131 | } 132 | 133 | vector > tanCC(const circle &cir1, const circle &cir2) { 134 | // `注意: 如果只有三条切线, 即 $s1 = 1, s2 = 1$, 返回的切线可能重复, 切点没有问题` 135 | vector > list; 136 | if (cir1.contain(cir2) || cir2.contain(cir1)) return list; 137 | const point &c1 = cir1.o, &c2 = cir2.o; 138 | double r1 = cir1.r, r2 = cir2.r; 139 | point p, a1, b1, a2, b2; int s1, s2; 140 | if (sign(r1 - r2) == 0) { 141 | p = c2 - c1; 142 | p = (p * (r1 / p.len())).rot90(); 143 | list.push_back(make_pair(c1 + p, c2 + p)); 144 | list.push_back(make_pair(c1 - p, c2 - p)); 145 | } else { 146 | p = (c2 * r1 - c1 * r2) / (r1 - r2); 147 | s1 = cir1.tanCP(p, a1, b1); 148 | s2 = cir2.tanCP(p, a2, b2); 149 | if (s1 >= 1 && s2 >= 1) { 150 | list.push_back(make_pair(a1, a2)); 151 | list.push_back(make_pair(b1, b2)); 152 | } 153 | } p = (c1 * r2 + c2 * r1) / (r1 + r2); 154 | s1 = cir1.tanCP(p, a1, b1); 155 | s2 = cir2.tanCP(p, a2, b2); 156 | if (s1 >= 1 && s2 >= 1) { 157 | list.push_back(make_pair(a1, a2)); 158 | list.push_back(make_pair(b1, b2)); 159 | } return list; 160 | } 161 | 162 | bool distConvexPIn(const point &p1, const point &p2, const point &p3, const point &p4, const point &q) { 163 | point o12 = (p1 - p2).rot90(), o23 = (p2 - p3).rot90(), o34 = (p3 - p4).rot90(); 164 | return (q - p1).inAngle(o12, o23) || (q - p3).inAngle(o23, o34) 165 | || ((q - p2).inAngle(o23, p3 - p2) && (q - p3).inAngle(p2 - p3, o23)); 166 | } 167 | 168 | double distConvexP(int n, point ps[], const point &q) { 169 | int left = 0, right = n; 170 | while (right - left > 1) { 171 | int mid = (left + right) / 2; 172 | if (distConvexPIn(ps[(left + n - 1) % n], ps[left], ps[mid], ps[(mid + 1) % n], q)) 173 | right = mid; 174 | else left = mid; 175 | } return q.distSP(ps[left], ps[right % n]); 176 | } 177 | 178 | double areaCT(const circle &cir, point pa, point pb) { 179 | pa = pa - cir.o; pb = pb - cir.o; 180 | double R = cir.r; 181 | if (pa.len() < pb.len()) swap(pa, pb); 182 | if (pb.len() < EPS) return 0; 183 | point pc = pb - pa; 184 | double a = pa.len(), b = pb.len(), c = pc.len(); 185 | double cosB = dot(pb, pc) / b / c, B = acos(cosB); 186 | double cosC = dot(pa, pb) / a / b, C = acos(cosC); 187 | double S, h, theta; 188 | if (b > R) { 189 | S = C * 0.5 * R * R; 190 | h = b * a * sin(C) / c; 191 | if (h < R && B < PI * 0.5) S -= acos(h / R) * R * R - h * sqrt(R * R - h * h); 192 | } else if (a > R) { 193 | theta = PI - B - asin(sin(B) / R * b); 194 | S = 0.5 * b * R * sin(theta) + (C - theta) * 0.5 * R * R; 195 | } else S = 0.5 * sin(C) * b * a; 196 | return S; 197 | } 198 | circle minCircle(const point &a, const point &b) { 199 | return circle((a + b) * 0.5, (b - a).len() * 0.5); 200 | } 201 | circle minCircle(const point &a, const point &b, const point &c) { // `钝角三角形没有被考虑` 202 | double A = 2 * a.x - 2 * b.x, B = 2 * a.y - 2 * b.y; 203 | double D = 2 * a.x - 2 * c.x, E = 2 * a.y - 2 * c.y; 204 | double C = a.x * a.x + a.y * a.y - b.x * b.x - b.y * b.y; 205 | double F = a.x * a.x + a.y * a.y - c.x * c.x - c.y * c.y; 206 | point p((C * E - B * F) / (A * E - B * D), (A * F - C * D) / (A * E - B * D)); 207 | return circle(p, (p - a).len()); 208 | } 209 | circle minCircle(point P[], int N) { // `1-based` 210 | if (N == 1) return circle(P[1], 0.0); 211 | random_shuffle(P + 1, P + N + 1); 212 | circle O = minCircle(P[1], P[2]); 213 | Rep(i, 1, N) if(!O.inside(P[i])) { O = minCircle(P[1], P[i]); 214 | Foru(j, 1, i) if(!O.inside(P[j])) { O = minCircle(P[i], P[j]); 215 | Foru(k, 1, j) if(!O.inside(P[k])) O = minCircle(P[i], P[j], P[k]); 216 | } 217 | } return O; 218 | } 219 | -------------------------------------------------------------------------------- /src/Computational Geometry/2D_Geometry_Base.cpp: -------------------------------------------------------------------------------- 1 | const double PI = 3.14159265358979323846264338327950288; 2 | double arcSin(const double &a) { 3 | return a <= -1.0 ? -PI / 2 : (a >= 1.0 ? PI / 2 : asin(a)); 4 | } 5 | double arcCos(const double &a) { 6 | return a <= -1.0 ? PI : (a >= 1.0 ? 0 : acos(a)); 7 | } 8 | struct point { 9 | double x, y; // `something omitted` 10 | point rot(const double &a) const { // `counter-clockwise` 11 | return point(x * cos(a) - y * sin(a), x * sin(a) + y * cos(a)); 12 | } 13 | point rot90() const { // `counter-clockwise` 14 | return point(-y, x); 15 | } 16 | point project(const point &p1, const point &p2) const { 17 | const point &q = *this; 18 | return p1 + (p2 - p1) * (dot(p2 - p1, q - p1) / (p2 - p1).norm()); 19 | } 20 | bool onSeg(const point &a, const point &b) const { // `a, b inclusive` 21 | const point &c = *this; 22 | return sign(dot(a - c, b - c)) <= 0 && sign(det(b - a, c - a)) == 0; 23 | } 24 | double distLP(const point &p1, const point &p2) const { // `dist from *this to line p1->p2` 25 | const point &q = *this; 26 | return fabs(det(p2 - p1, q - p1)) / (p2 - p1).len(); 27 | } 28 | double distSP(const point &p1, const point &p2) const { // `dist from *this to segment [p1, p2]` 29 | const point &q = *this; 30 | if (dot(p2 - p1, q - p1) < EPS) return (q - p1).len(); 31 | if (dot(p1 - p2, q - p2) < EPS) return (q - p2).len(); 32 | return distLP(p1, p2); 33 | } 34 | bool inAngle(const point &p1, const point &p2) const { // `det(p1, p2) $\ge$ 0` 35 | const point &q = *this; return det(p1, q) > -EPS && det(p2, q) < EPS; 36 | } 37 | }; 38 | bool lineIntersect(const point &a, const point &b, const point &c, const point &d, point &e) { 39 | double s1 = det(c - a, d - a); 40 | double s2 = det(d - b, c - b); 41 | if (!sign(s1 + s2)) return false; 42 | e = (b - a) * (s1 / (s1 + s2)) + a; 43 | return true; 44 | } 45 | int segIntersectCheck(const point &a, const point &b, const point &c, const point &d, point &o) { 46 | static double s1, s2, s3, s4; 47 | static int iCnt; 48 | int d1 = sign(s1 = det(b - a, c - a)); 49 | int d2 = sign(s2 = det(b - a, d - a)); 50 | int d3 = sign(s3 = det(d - c, a - c)); 51 | int d4 = sign(s4 = det(d - c, b - c)); 52 | if ((d1 ^ d2) == -2 && (d3 ^ d4) == -2) { 53 | o = (c * s2 - d * s1) / (s2 - s1); 54 | return true; 55 | } 56 | iCnt = 0; 57 | if (d1 == 0 && c.onSeg(a, b)) o = c, ++iCnt; 58 | if (d2 == 0 && d.onSeg(a, b)) o = d, ++iCnt; 59 | if (d3 == 0 && a.onSeg(c, d)) o = a, ++iCnt; 60 | if (d4 == 0 && b.onSeg(c, d)) o = b, ++iCnt; 61 | return iCnt ? 2 : 0; // `不相交返回0, 严格相交返回1, 非严格相交返回2` 62 | } 63 | struct circle { 64 | point o; 65 | double r, rSqure; 66 | bool inside(const point &a) { // `非严格` 67 | return (a - o).len() < r + EPS; 68 | } 69 | bool contain(const circle &b) const { // `非严格` 70 | return sign(b.r + (o - b.o).len() - r) <= 0; 71 | } 72 | bool disjunct(const circle &b) const { // `非严格` 73 | return sign(b.r + r - (o - b.o).len()) <= 0; 74 | } 75 | int isCL(const point &p1, const point &p2, point &a, point &b) const { 76 | double x = dot(p1 - o, p2 - p1), y = (p2 - p1).norm(); 77 | double d = x * x - y * ((p1 - o).norm() - rSqure); 78 | if (d < -EPS) return 0; 79 | if (d < 0) d = 0; 80 | point q1 = p1 - (p2 - p1) * (x / y); 81 | point q2 = (p2 - p1) * (sqrt(d) / y); 82 | a = q1 - q2; b = q1 + q2; 83 | return q2.len() < EPS ? 1 : 2; 84 | } 85 | int tanCP(const point &p, point &a, point &b) const { // `返回切点, 注意可能与 $p$ 重合` 86 | double x = (p - o).norm(), d = x - rSqure; 87 | if (d < -EPS) return 0; 88 | if (d < 0) d = 0; 89 | point q1 = (p - o) * (rSqure / x); 90 | point q2 = ((p - o) * (-r * sqrt(d) / x)).rot90(); 91 | a = o + (q1 - q2); b = o + (q1 + q2); 92 | return q2.len() < EPS ? 1 : 2; 93 | } 94 | }; 95 | bool checkCrossCS(const circle &cir, const point &p1, const point &p2) { // `非严格` 96 | const point &c = cir.o; 97 | const double &r = cir.r; 98 | return c.distSP(p1, p2) < r + EPS 99 | && (r < (c - p1).len() + EPS || r < (c - p2).len() + EPS); 100 | } 101 | bool checkCrossCC(const circle &cir1, const circle &cir2) { // `非严格` 102 | const double &r1 = cir1.r, &r2 = cir2.r, d = (cir1.o - cir2.o).len(); 103 | return d < r1 + r2 + EPS && fabs(r1 - r2) < d + EPS; 104 | } 105 | int isCC(const circle &cir1, const circle &cir2, point &a, point &b) { 106 | const point &c1 = cir1.o, &c2 = cir2.o; 107 | double x = (c1 - c2).norm(), y = ((cir1.rSqure - cir2.rSqure) / x + 1) / 2; 108 | double d = cir1.rSqure / x - y * y; 109 | if (d < -EPS) return 0; 110 | if (d < 0) d = 0; 111 | point q1 = c1 + (c2 - c1) * y; 112 | point q2 = ((c2 - c1) * sqrt(d)).rot90(); 113 | a = q1 - q2; b = q1 + q2; 114 | return q2.len() < EPS ? 1 : 2; 115 | } 116 | vector > tanCC(const circle &cir1, const circle &cir2) { 117 | // `注意: 如果只有三条切线, 即 $s1 = 1, s2 = 1$, 返回的切线可能重复, 切点没有问题` 118 | vector > list; 119 | if (cir1.contain(cir2) || cir2.contain(cir1)) return list; 120 | const point &c1 = cir1.o, &c2 = cir2.o; 121 | double r1 = cir1.r, r2 = cir2.r; 122 | point p, a1, b1, a2, b2; 123 | int s1, s2; 124 | if (sign(r1 - r2) == 0) { 125 | p = c2 - c1; 126 | p = (p * (r1 / p.len())).rot90(); 127 | list.push_back(make_pair(c1 + p, c2 + p)); 128 | list.push_back(make_pair(c1 - p, c2 - p)); 129 | } else { 130 | p = (c2 * r1 - c1 * r2) / (r1 - r2); 131 | s1 = cir1.tanCP(p, a1, b1); 132 | s2 = cir2.tanCP(p, a2, b2); 133 | if (s1 >= 1 && s2 >= 1) { 134 | list.push_back(make_pair(a1, a2)); 135 | list.push_back(make_pair(b1, b2)); 136 | } 137 | } 138 | p = (c1 * r2 + c2 * r1) / (r1 + r2); 139 | s1 = cir1.tanCP(p, a1, b1); 140 | s2 = cir2.tanCP(p, a2, b2); 141 | if (s1 >= 1 && s2 >= 1) { 142 | list.push_back(make_pair(a1, a2)); 143 | list.push_back(make_pair(b1, b2)); 144 | } 145 | return list; 146 | } 147 | bool distConvexPIn(const point &p1, const point &p2, const point &p3, const point &p4, const point &q) { 148 | point o12 = (p1 - p2).rot90(), o23 = (p2 - p3).rot90(), o34 = (p3 - p4).rot90(); 149 | return (q - p1).inAngle(o12, o23) || (q - p3).inAngle(o23, o34) 150 | || ((q - p2).inAngle(o23, p3 - p2) && (q - p3).inAngle(p2 - p3, o23)); 151 | } 152 | double distConvexP(int n, point ps[], const point &q) { // `外部点到多边形的距离` 153 | int left = 0, right = n; 154 | while (right - left > 1) { 155 | int mid = (left + right) / 2; 156 | if (distConvexPIn(ps[(left + n - 1) % n], ps[left], ps[mid], ps[(mid + 1) % n], q)) 157 | right = mid; 158 | else left = mid; 159 | } 160 | return q.distSP(ps[left], ps[right % n]); 161 | } 162 | double areaCT(const circle &cir, point pa, point pb) { 163 | pa = pa - cir.o; pb = pb - cir.o; 164 | double R = cir.r; 165 | if (pa.len() < pb.len()) swap(pa, pb); 166 | if (pb.len() < EPS) return 0; 167 | point pc = pb - pa; 168 | double a = pa.len(), b = pb.len(), c = pc.len(), S, h, theta; 169 | double cosB = dot(pb, pc) / b / c, B = acos(cosB); 170 | double cosC = dot(pa, pb) / a / b, C = acos(cosC); 171 | if (b > R) { 172 | S = C * 0.5 * R * R; 173 | h = b * a * sin(C) / c; 174 | if (h < R && B < PI * 0.5) 175 | S -= acos(h / R) * R * R - h * sqrt(R * R - h * h); 176 | } else if (a > R) { 177 | theta = PI - B - asin(sin(B) / R * b); 178 | S = 0.5 * b * R * sin(theta) + (C - theta) * 0.5 * R * R; 179 | } else S = 0.5 * sin(C) * b * a; 180 | return S; 181 | } 182 | circle minCircle(const point &a, const point &b) { 183 | return circle((a + b) * 0.5, (b - a).len() * 0.5); 184 | } 185 | circle minCircle(const point &a, const point &b, const point &c) { // `钝角三角形没有被考虑` 186 | double a2( (b - c).norm() ), b2( (a - c).norm() ), c2( (a - b).norm() ); 187 | if (b2 + c2 <= a2 + EPS) return minCircle(b, c); 188 | if (a2 + c2 <= b2 + EPS) return minCircle(a, c); 189 | if (a2 + b2 <= c2 + EPS) return minCircle(a, b); 190 | double A = 2.0 * (a.x - b.x), B = 2.0 * (a.y - b.y); 191 | double D = 2.0 * (a.x - c.x), E = 2.0 * (a.y - c.y); 192 | double C = a.norm() - b.norm(), F = a.norm() - c.norm(); 193 | point p((C * E - B * F) / (A * E - B * D), (A * F - C * D) / (A * E - B * D)); 194 | return circle(p, (p - a).len()); 195 | } 196 | circle minCircle(point P[], int N) { // `1-based` 197 | if (N == 1) return circle(P[1], 0.0); 198 | random_shuffle(P + 1, P + N + 1); circle O = minCircle(P[1], P[2]); 199 | Rep(i, 1, N) if(!O.inside(P[i])) { O = minCircle(P[1], P[i]); 200 | Foru(j, 1, i) if(!O.inside(P[j])) { O = minCircle(P[i], P[j]); 201 | Foru(k, 1, j) if(!O.inside(P[k])) O = minCircle(P[i], P[j], P[k]); } 202 | } return O; 203 | } 204 | -------------------------------------------------------------------------------- /src/Computational Geometry/3D Convex Cut.cpp: -------------------------------------------------------------------------------- 1 | vector > convexCut(const vector > &pss, const point &p, const point &o) { 2 | vector > res; 3 | vector sec; 4 | for (unsigned itr = 0, size = pss.size(); itr < size; ++itr) { 5 | const vector &ps = pss[itr]; 6 | int n = ps.size(); 7 | vector qs; 8 | bool dif = false; 9 | for (int i = 0; i < n; ++i) { 10 | int d1 = sign( dot(o, ps[i] - p) ); 11 | int d2 = sign( dot(o, ps[(i + 1) % n] - p) ); 12 | if (d1 <= 0) qs.push_back(ps[i]); 13 | if (d1 * d2 < 0) { 14 | point q; 15 | isFL(p, o, ps[i], ps[(i + 1) % n], q); // must return true 16 | qs.push_back(q); 17 | sec.push_back(q); 18 | } 19 | if (d1 == 0) sec.push_back(ps[i]); 20 | else dif = true; 21 | dif |= dot(o, det(ps[(i + 1) % n] - ps[i], ps[(i + 2) % n] - ps[i])) < -EPS; 22 | } 23 | if (!qs.empty() && dif) 24 | res.insert(res.end(), qs.begin(), qs.end()); 25 | } 26 | if (!sec.empty()) { 27 | vector tmp( convexHull2D(sec, o) ); 28 | res.insert(res.end(), tmp.begin(), tmp.end()); 29 | } 30 | return res; 31 | } 32 | 33 | vector > initConvex() { 34 | vector > pss(6, vector(4)); 35 | pss[0][0] = pss[1][0] = pss[2][0] = point(-INF, -INF, -INF); 36 | pss[0][3] = pss[1][1] = pss[5][2] = point(-INF, -INF, INF); 37 | pss[0][1] = pss[2][3] = pss[4][2] = point(-INF, INF, -INF); 38 | pss[0][2] = pss[5][3] = pss[4][1] = point(-INF, INF, INF); 39 | pss[1][3] = pss[2][1] = pss[3][2] = point( INF, -INF, -INF); 40 | pss[1][2] = pss[5][1] = pss[3][3] = point( INF, -INF, INF); 41 | pss[2][2] = pss[4][3] = pss[3][1] = point( INF, INF, -INF); 42 | pss[5][0] = pss[4][0] = pss[3][0] = point( INF, INF, INF); 43 | return pss; 44 | } -------------------------------------------------------------------------------- /src/Computational Geometry/3D Convex Hull.cpp: -------------------------------------------------------------------------------- 1 | namespace ConvexHull3D { 2 | #define volume(a, b, c, d) (mix(ps[b] - ps[a], ps[c] - ps[a], ps[d] - ps[a])) 3 | vector getHull(int n, point ps[]) { 4 | static int mark[MAXN][MAXN], a, b, c; 5 | int stamp = 0; 6 | bool exist = false; 7 | vector facet; 8 | random_shuffle(ps, ps + n); 9 | for (int i = 2; i < n && !exist; i++) { 10 | point ndir = det(ps[0] - ps[i], ps[1] - ps[i]); 11 | if (ndir.len() < EPS) continue; 12 | swap(ps[i], ps[2]); 13 | for (int j = i + 1; j < n && !exist; j++) 14 | if (sign(volume(0, 1, 2, j)) != 0) { 15 | exist = true; 16 | swap(ps[j], ps[3]); 17 | facet.push_back(Facet(0, 1, 2)); 18 | facet.push_back(Facet(0, 2, 1)); 19 | } 20 | } 21 | if (!exist) return ConvexHull2D(n, ps); 22 | for (int i = 0; i < n; ++i) 23 | for (int j = 0; j < n; ++j) 24 | mark[i][j] = 0; 25 | stamp = 0; 26 | for (int v = 3; v < n; ++v) { 27 | vector tmp; 28 | ++stamp; 29 | for (unsigned i = 0; i < facet.size(); i++) { 30 | a = facet[i].a; 31 | b = facet[i].b; 32 | c = facet[i].c; 33 | if (sign(volume(v, a, b, c)) < 0) 34 | mark[a][b] = mark[a][c] = 35 | mark[b][a] = mark[b][c] = 36 | mark[c][a] = mark[c][b] = stamp; 37 | else tmp.push_back(facet[i]); 38 | } facet = tmp; 39 | for (unsigned i = 0; i < tmp.size(); i++) { 40 | a = facet[i].a; b = facet[i].b; c = facet[i].c; 41 | if (mark[a][b] == stamp) facet.push_back(Facet(b, a, v)); 42 | if (mark[b][c] == stamp) facet.push_back(Facet(c, b, v)); 43 | if (mark[c][a] == stamp) facet.push_back(Facet(a, c, v)); 44 | } 45 | } return facet; 46 | } 47 | #undef volume 48 | } 49 | namespace Gravity { 50 | using ConvexHull3D::Facet; 51 | point findG(point ps[], const vector &facet) { 52 | double ws = 0; point res(0.0, 0.0, 0.0), o = ps[ facet[0].a ]; 53 | for (int i = 0, size = facet.size(); i < size; ++i) { 54 | const point &a = ps[ facet[i].a ], &b = ps[ facet[i].b ], &c = ps[ facet[i].c ]; 55 | point p = (a + b + c + o) * 0.25; 56 | double w = mix(a - o, b - o, c - o); 57 | ws += w; 58 | res = res + p * w; 59 | } res = res / ws; 60 | return res; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Computational Geometry/3D_Geometry_Base.cpp: -------------------------------------------------------------------------------- 1 | struct point { double x, y, z; // something omitted 2 | friend point det(const point &a, const point &b) { 3 | return point(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); 4 | } 5 | friend double mix(const point &a, const point &b, const point &c) { 6 | return a.x * b.y * c.z + a.y * b.z * c.x + a.z * b.x * c.y - a.z * b.y * c.x - a.x * b.z * c.y - a.y * b.x * c.z; 7 | } 8 | double distLP(const point &p1, const point &p2) const { 9 | return det(p2 - p1, *this - p1).len() / (p2 - p1).len(); 10 | } 11 | double distFP(const point &p1, const point &p2, const point &p3) const { 12 | point n = det(p2 - p1, p3 - p1); return fabs( dot(n, *this - p1) / n.len() ); 13 | } 14 | }; 15 | double distLL(const point &p1, const point &p2, const point &q1, const point &q2) { 16 | point p = q1 - p1, u = p2 - p1, v = q2 - q1; 17 | double d = u.norm() * v.norm() - dot(u, v) * dot(u, v); 18 | if (sign(d) == 0) return p1.distLP(q1, q2); 19 | double s = (dot(p, u) * v.norm() - dot(p, v) * dot(u, v)) / d; 20 | return (p1 + u * s).distLP(q1, q2); 21 | } 22 | double distSS(const point &p1, const point &p2, const point &q1, const point &q2) { 23 | point p = q1 - p1, u = p2 - p1, v = q2 - q1; 24 | double d = u.norm() * v.norm() - dot(u, v) * dot(u, v); 25 | if (sign(d) == 0) return min( min((p1 - q1).len(), (p1 - q2).len()), 26 | min((p2 - q1).len(), (p2 - q2).len())); 27 | double s1 = (dot(p, u) * v.norm() - dot(p, v) * dot(u, v)) / d; 28 | double s2 = (dot(p, v) * u.norm() - dot(p, u) * dot(u, v)) / d; 29 | if (s1 < 0.0) s1 = 0.0; if (s1 > 1.0) s1 = 1.0; 30 | if (s2 < 0.0) s2 = 0.0; if (s2 > 1.0) s2 = 1.0; 31 | point r1 = p1 + u * s1; point r2 = q1 + v * s2; 32 | return (r1 - r2).len(); 33 | } 34 | bool isFL(const point &p, const point &o, const point &q1, const point &q2, point &res) { 35 | double a = dot(o, q2 - p), b = dot(o, q1 - p), d = a - b; 36 | if (sign(d) == 0) return false; 37 | res = (q1 * a - q2 * b) / d; 38 | return true; 39 | } 40 | bool isFF(const point &p1, const point &o1, const point &p2, const point &o2, point &a, point &b) { 41 | point e = det(o1, o2), v = det(o1, e); 42 | double d = dot(o2, v); if (sign(d) == 0) return false; 43 | point q = p1 + v * (dot(o2, p2 - p1) / d); 44 | a = q; b = q + e; 45 | return true; 46 | } -------------------------------------------------------------------------------- /src/Computational Geometry/Circle.cpp: -------------------------------------------------------------------------------- 1 | struct circle { 2 | point o; 3 | double r, r2; // r ^ 2 4 | circle(): o(), r(0.0), r2(0.0) {} 5 | circle(const point &o, const double &r): o(o), r(r), r2(r * r) {} 6 | bool inside(const point &a) { return sign((a - o).norm() - r2) <= 0; } 7 | bool intersectWithLine(const point &S, const point &T, point &A, point &B) const { // guarantee det(OA, OB) >= 0 8 | if (sign(det(o - S, T - S)) > 0) 9 | return intersectWithLine(T, S, A, B); 10 | double h = dist(S, T, o); 11 | if (sign(h - r) > 0) return false; 12 | double l = Sqrt(r2 - sqr(h)); 13 | point mm = (T - S).unit().rot(-PI / 2) * h + o; 14 | point vv = (T - S).unit() * l; 15 | A = mm - vv; 16 | B = mm + vv; 17 | return true; 18 | } 19 | bool contain(const circle &b) const { 20 | return sign(b.r + (o - b.o).len() - r) <= 0; 21 | } 22 | 23 | bool disjunct(const circle &b) const { 24 | return sign(b.r + r - (o - b.o).len()) <= 0; 25 | } 26 | }; 27 | 28 | bool twoCircleIntersect(const circle &a, const circle &b, point &A, point &B) { // a, b should not be the same 29 | if (a.contain(b) || b.contain(a) || a.disjunct(b)) return 0; 30 | double s1 = (a.o - b.o).len(); 31 | double s2 = (a.r2 - b.r2) / s1; 32 | double aa = (s1 + s2) / 2; 33 | double bb = (s1 - s2) / 2; 34 | double h = Sqrt(a.r2 - sqr(aa)); 35 | point mm = (b.o - a.o) * (aa / (aa + bb)) + a.o; 36 | point vv = (b.o - a.o).unit().rot(PI / 2) * h; // rot(x, y) => (y, -x) 37 | A = mm + vv; 38 | B = mm - vv; 39 | return 1; 40 | } 41 | 42 | double twoCircleIntersectArea(const circle &a, const circle &b) { 43 | if (a.r < b.r) return twoCircleIntersectArea(b, a); 44 | double ans = 0; 45 | double d = (a.o - b.o).len(); 46 | if (d + EPS > a.r + b.r) return 0; 47 | if (d < a.r - b.r + EPS) return PI * b.r2; 48 | double a1 = arcCos((a.r2 + sqr(d) - b.r2) * 0.5 / a.r / d); 49 | double a2 = arcCos((b.r2 + sqr(d) - a.r2) * 0.5 / b.r / d); 50 | ans -= d * a.r * sin(a1); 51 | ans += a1 * a.r2 + a2 * b.r2; 52 | return ans; 53 | } 54 | 55 | circle minCircle(const point &a, const point &b) { return circle((a + b) * 0.5, (b - a).len() * 0.5); } 56 | 57 | circle minCircle(const point &a, const point &b, const point &c) { // WARNING: Obtuse triangle is not considered 58 | double A = 2 * a.x - 2 * b.x; 59 | double B = 2 * a.y - 2 * b.y; 60 | double C = a.x * a.x + a.y * a.y - b.x * b.x - b.y * b.y; 61 | double D = 2 * a.x - 2 * c.x; 62 | double E = 2 * a.y - 2 * c.y; 63 | double F = a.x * a.x + a.y * a.y - c.x * c.x - c.y * c.y; 64 | point p((C * E - B * F) / (A * E - B * D), (A * F - C * D) / (A * E - B * D)); 65 | return circle(p, (p - a).len()); 66 | } 67 | 68 | circle minCircle(point P[], int N) { 69 | if (N == 1) return circle(P[1], 0.0); 70 | random_shuffle(P + 1, P + N + 1); 71 | circle O = minCircle(P[1], P[2]); 72 | Rep(i, 3, N) if(!O.inside(P[i])) { 73 | O = minCircle(P[1], P[i]); 74 | Foru(j, 2, i) if(!O.inside(P[j])) { 75 | O = minCircle(P[i], P[j]); 76 | Foru(k, 1, j) if(!O.inside(P[k])) 77 | O = minCircle(P[i], P[j], P[k]); 78 | } 79 | } 80 | return O; 81 | } 82 | -------------------------------------------------------------------------------- /src/Computational Geometry/CircleKCover.cpp: -------------------------------------------------------------------------------- 1 | struct Event { point p; double alpha; int add; // `构造函数省略` 2 | bool operator < (const Event &other) const { return alpha < other.alpha; } }; 3 | void circleKCover(circle *c, int N, double *area) { // `$area[k]$ : 至少被覆盖$k$次` 4 | static bool overlap[MAXN][MAXN], g[MAXN][MAXN]; 5 | Rep(i, 0, N + 1) area[i] = 0.0; Rep(i, 1, N) Rep(j, 1, N) overlap[i][j] = c[i].contain(c[j]); 6 | Rep(i, 1, N) Rep(j, 1, N) g[i][j] = !(overlap[i][j] || overlap[j][i] || c[i].disjunct(c[j])); 7 | Rep(i, 1, N) { static Event events[MAXN * 2 + 1]; int totE = 0, cnt = 1; 8 | Rep(j, 1, N) if (j != i && overlap[j][i]) ++cnt; 9 | Rep(j, 1, N) if (j != i && g[i][j]) { 10 | circle &a = c[i], &b = c[j]; double l = (a.o - b.o).norm(); 11 | double s = ((a.r - b.r) * (a.r + b.r) / l + 1) * 0.5; 12 | double t = sqrt(-(l - sqr(a.r - b.r)) * (l - sqr(a.r + b.r)) / (l * l * 4.0)); 13 | point dir = b.o - a.o, nDir = point(-dir.y, dir.x); 14 | point aa = a.o + dir * s + nDir * t; 15 | point bb = a.o + dir * s - nDir * t; 16 | double A = atan2(aa.y - a.o.y, aa.x - a.o.x); 17 | double B = atan2(bb.y - a.o.y, bb.x - a.o.x); 18 | events[totE++] = Event(bb, B, 1); events[totE++] = Event(aa, A, -1); if (B > A) ++cnt; 19 | } if (totE == 0) { area[cnt] += PI * c[i].rSquare; continue; } 20 | sort(events, events + totE); events[totE] = events[0]; 21 | Foru(j, 0, totE) { 22 | cnt += events[j].add; area[cnt] += 0.5 * det(events[j].p, events[j + 1].p); 23 | double theta = events[j + 1].alpha - events[j].alpha; if (theta < 0) theta += 2.0 * PI; 24 | area[cnt] += 0.5 * c[i].rSquare * (theta - sin(theta)); 25 | }}} -------------------------------------------------------------------------------- /src/Computational Geometry/ClosestPair.cpp: -------------------------------------------------------------------------------- 1 | int N; point p[maxn]; 2 | bool cmpByX(const point &a, const point &b) { return sign(a.x - b.x) < 0; } 3 | bool cmpByY(const int &a, const int &b) { return p[a].y < p[b].y; } 4 | double minimalDistance(point *c, int n, int *ys) { 5 | double ret = 1e+20; 6 | if (n < 20) { 7 | Foru(i, 0, n) Foru(j, i + 1, n) cMin(ret, (c[i] - c[j]).len() ); 8 | sort(ys, ys + n, cmpByY); return ret; 9 | } static int mergeTo[maxn]; 10 | int mid = n / 2; double xmid = c[mid].x; 11 | ret = min(minimalDistance(c, mid, ys), minimalDistance(c + mid, n - mid, ys + mid)); 12 | merge(ys, ys + mid, ys + mid, ys + n, mergeTo, cmpByY); 13 | copy(mergeTo, mergeTo + n, ys); 14 | Foru(i, 0, n) { 15 | while (i < n && sign(fabs(p[ys[i]].x - xmid) - ret) > 0) ++i; 16 | int cnt = 0; 17 | Foru(j, i + 1, n) 18 | if (sign(p[ys[j]].y - p[ys[i]].y - ret) > 0) break; 19 | else if (sign(fabs(p[ys[j]].x - xmid) - ret) <= 0) { 20 | ret = min(ret, (p[ys[i]] - p[ys[j]]).len()); 21 | if (++cnt >= 10) break; 22 | } 23 | } return ret; 24 | } 25 | double work() { 26 | sort(p, p + n, cmpByX); Foru(i, 0, n) ys[i] = i; return minimalDistance(p, n, ys); 27 | } -------------------------------------------------------------------------------- /src/Computational Geometry/Convex Hull && Convex Diameter.cpp: -------------------------------------------------------------------------------- 1 | vector convexHull(int n, point ps[]) { // `counter-clockwise, strict` 2 | static point qs[MAXN * 2]; 3 | sort(ps, ps + n, cmpByXY); 4 | if (n <= 2) return vector(ps, ps + n); 5 | int k = 0; 6 | for (int i = 0; i < n; qs[k++] = ps[i++]) 7 | while (k > 1 && det(qs[k - 1] - qs[k - 2], ps[i] - qs[k - 1]) < EPS) --k; 8 | for (int i = n - 2, t = k; i >= 0; qs[k++] = ps[i--]) 9 | while (k > t && det(qs[k - 1] - qs[k - 2], ps[i] - qs[k - 1]) < EPS) --k; 10 | return vector(qs, qs + k); 11 | } 12 | double convexDiameter(int n, point ps[]) { 13 | if (n < 2) return 0; if (n == 2) return (ps[1] - ps[0]).len(); 14 | double k, ans = 0; 15 | for (int x = 0, y = 1, nx, ny; x < n; ++x) { 16 | for(nx = (x == n - 1) ? (0) : (x + 1); ; y = ny) { 17 | ny = (y == n - 1) ? (0) : (y + 1); 18 | if ( sign(k = det(ps[nx] - ps[x], ps[ny] - ps[y])) <= 0) break; 19 | } ans = max(ans, (ps[x] - ps[y]).len()); 20 | if (sign(k) == 0) ans = max(ans, (ps[x] - ps[ny]).len()); 21 | } return ans; 22 | } -------------------------------------------------------------------------------- /src/Computational Geometry/DistOnBall.cpp: -------------------------------------------------------------------------------- 1 | double distOnBall(double lati1, double longi1, double lati2, double longi2, double R) { 2 | lati1 *= PI / 180; longi1 *= PI / 180; 3 | lati2 *= PI / 180; longi2 *= PI / 180; 4 | double x1 = cos(lati1) * sin(longi1); 5 | double y1 = cos(lati1) * cos(longi1); 6 | double z1 = sin(lati1); 7 | double x2 = cos(lati2) * sin(longi2); 8 | double y2 = cos(lati2) * cos(longi2); 9 | double z2 = sin(lati2); 10 | double theta = acos(x1 * x2 + y1 * y2 + z1 * z2); 11 | return R * theta; 12 | } -------------------------------------------------------------------------------- /src/Computational Geometry/DistOnCuboid.cpp: -------------------------------------------------------------------------------- 1 | int r; 2 | void turn(int i, int j, int x, int y, int z, int x0, int y0, int L, int W, int H) { 3 | if (z == 0) r = min(r, x * x + y * y); 4 | else { 5 | if (i >= 0 && i < 2) turn(i + 1, j, x0 + L + z, y, x0 + L - x, x0 + L, y0, H, W, L); 6 | if (j >= 0 && j < 2) turn(i, j + 1, x, y0 + W + z, y0 + W - y, x0, y0 + W, L, H, W); 7 | if (i <= 0 && i > -2) turn(i - 1, j, x0 - z, y, x - x0, x0 - H, y0, H, W, L); 8 | if (j <= 0 && j > -2) turn(i, j - 1, x, y0 - z, y - y0, x0, y0 - H, L, H, W); 9 | } 10 | } 11 | int calc(int L, int H, int W, int x1, int y1, int z1, int x2, int y2, int z2) { 12 | if (z1 != 0 && z1 != H) 13 | if (y1 == 0 || y1 == W) swap(y1, z1), swap(y2, z2), swap(W, H); 14 | else swap(x1, z1), swap(x2, z2), swap(L, H); 15 | if (z1 == H) z1 = 0, z2 = H - z2; 16 | r = INF; turn(0, 0, x2 - x1, y2 - y1, z2, -x1, -y1, L, W, H); 17 | return r; 18 | } -------------------------------------------------------------------------------- /src/Computational Geometry/Farmland.cpp: -------------------------------------------------------------------------------- 1 | struct node { int begin[MAXN], *end; } a[MAXN]; // `按对 $p[i]$ 的极角的 atan2 值排序` 2 | bool check(int n, point p[], int b1, int b2, bool vis[MAXN][MAXN]) { 3 | static pii l[MAXN * 2 + 1]; static bool used[MAXN]; 4 | int tp(0), *k, p, p1, p2; double area(0.0); 5 | for (l[0] = pii(b1, b2); ; ) { 6 | vis[p1 = l[tp].first][p2 = l[tp].second] = true; 7 | area += det(p[p1], p[p2]); 8 | for (k = a[p2].begin; k != a[p2].end; ++k) if (*k == p1) break; 9 | k = (k == a[p2].begin) ? (a[p2].end - 1) : (k - 1); 10 | if ((l[++tp] = pii(p2, *k)) == l[0]) break; 11 | } if (sign(area) < 0 || tp < 3) return false; 12 | Rep(i, 1, n) used[i] = false; 13 | for (int i = 0; i < tp; ++i) if (used[p = l[i].first]) return false; else used[p] = true; 14 | return true; // `a face with tp vertices` 15 | } 16 | int countFaces(int n, point p[]) { 17 | static bool vis[MAXN][MAXN]; int ans = 0; 18 | Rep(x, 1, n) Rep(y, 1, n) vis[x][y] = false; 19 | Rep(x, 1, n) for (int *itr = a[x].begin; itr != a[x].end; ++itr) if (!vis[x][*itr]) 20 | if (check(n, p, x, *itr, vis)) ++ans; 21 | return ans; 22 | } -------------------------------------------------------------------------------- /src/Computational Geometry/Fermat Point Of A Quadrilateral.cpp: -------------------------------------------------------------------------------- 1 | typedef complex Tpoint; 2 | const double eps = 1e-8; 3 | const double sqrt3 = sqrt(3.0); 4 | bool cmp(const Tpoint &a, const Tpoint &b) { 5 | return a.real() < b.real() - eps || (a.real() < b.real() + eps && a.imag() < b.imag()); 6 | } 7 | Tpoint rotate(const Tpoint &a, const Tpoint &b, const Tpoint &c) { 8 | Tpoint d = b - a; d = Tpoint(-d.imag(), d.real()); 9 | if (Sign(cross(a, b, c)) == Sign(cross(a, b, a + d))) d *= -1.0; 10 | return unit(d); 11 | } 12 | Tpoint p[10], a[10], b[10]; 13 | int N, T; 14 | double totlen(const Tpoint &p, const Tpoint &a, const Tpoint &b, const Tpoint &c) { 15 | return abs(p - a) + abs(p - b) + abs(p - c); 16 | } 17 | double fermat(const Tpoint &x, const Tpoint &y, const Tpoint &z, Tpoint &cp) { 18 | a[0] = a[3] = x; a[1] = a[4] = y; a[2] = a[5] = z; 19 | double len = 1e100, len2; 20 | for (int i = 0; i < 3; i++) { 21 | len2 = totlen(a[i], x, y, z); 22 | if (len2 < len) len = len2, cp = a[i]; 23 | } 24 | for (int i = 0; i < 3; i++) { 25 | b[i] = rotate(a[i + 1], a[i], a[i + 2]); 26 | b[i] = (a[i + 1] + a[i]) / 2.0 + b[i] * (abs(a[i + 1] - a[i]) * sqrt3 / 2.0); 27 | } 28 | b[3] = b[0]; 29 | Tpoint cp2 = intersect(b[0], a[2], b[1], a[3]); 30 | len2 = totlen(cp2, x, y, z); 31 | if (len2 < len) len = len2, cp = cp2; 32 | return len; 33 | } 34 | double getans(const Tpoint &a) { 35 | double len = 0; for (int i = 0; i < N; i++) len += abs(a - p[i]); 36 | return len; 37 | } 38 | double mindist(const Tpoint &p, const Tpoint &a, const Tpoint &b, const Tpoint &c, const Tpoint &d) { 39 | return min( min(abs(p - a), abs(p - b)), min(abs(p - c), abs(p - d))); 40 | } 41 | int main() { 42 | N = 4; 43 | for (cin >> T; T; T--) { 44 | double ret = 1e100, len_cur, len_before, len1, len2, len; 45 | Tpoint cp, cp1, cp2; 46 | Foru(i, 0, N) cin >> p[i]; 47 | Foru(i, 0, N) ret = min(ret, getans(p[i])); 48 | Foru(i, 1, N) Foru(j, 1, N) if (j != i) Foru(k, 1, N) if (k != i && k != j) { 49 | cMin(ret, abs(p[0] - p[i]) + abs(p[j] - p[k]) 50 | + min( min(abs(p[0] - p[j]), abs(p[0] - p[k])), 51 | min(abs(p[i] - p[j]), abs(p[i] - p[k])) 52 | )); 53 | ret = min(ret, getans(intersect(p[0], p[i], p[j], p[k]))); 54 | } 55 | Foru(i, 0, N) Foru(j, i + 1, N) Foru(k, j + 1, N) { 56 | double len = fermat(p[i], p[j], p[k], cp); 57 | ret = min(ret, len + mindist(p[6 - i - j - k], p[i], p[j], p[k], cp)); 58 | } 59 | sort(p, p + N, cmp); 60 | for (int i = 1; i < N; i++) { 61 | cp1 = (p[0] + p[i]) / 2.0; 62 | int j, k; 63 | for (j = 1; j < N && j == i; j++); 64 | for (k = 6 - i - j, len_before = 1e100; ; ) { 65 | len1 = fermat(cp1, p[j], p[k], cp2); 66 | len1 = fermat(cp2, p[0], p[i], cp1); 67 | len = len1 + abs(cp2 - p[j]) + abs(cp2 - p[k]); 68 | if (len < len_before - (1e-6)) len_before = len; 69 | else break; 70 | } ret = min(ret, len_before); 71 | } printf("%.4f\n", ret); 72 | } 73 | return 0; 74 | } -------------------------------------------------------------------------------- /src/Computational Geometry/Half Plane Intersection.cpp: -------------------------------------------------------------------------------- 1 | struct Border { 2 | point p1, p2; double alpha; 3 | Border() : p1(), p2(), alpha(0.0) {} 4 | Border(const point &a, const point &b): p1(a), p2(b), alpha( atan2(p2.y - p1.y, p2.x - p1.x) ) {} 5 | bool operator == (const Border &b) const { return sign(alpha - b.alpha) == 0; } 6 | bool operator < (const Border &b) const { 7 | int c = sign(alpha - b.alpha); if (c != 0) return c > 0; 8 | return sign(det(b.p2 - b.p1, p1 - b.p1)) >= 0; 9 | } 10 | }; 11 | point isBorder(const Border &a, const Border &b) { // a and b should not be parallel 12 | point is; lineIntersect(a.p1, a.p2, b.p1, b.p2, is); return is; 13 | } 14 | bool checkBorder(const Border &a, const Border &b, const Border &me) { 15 | point is; lineIntersect(a.p1, a.p2, b.p1, b.p2, is); 16 | return sign(det(me.p2 - me.p1, is - me.p1)) > 0; 17 | } 18 | double HPI(int N, Border border[]) { 19 | static Border que[MAXN * 2 + 1]; static point ps[MAXN]; 20 | int head = 0, tail = 0, cnt = 0; // [head, tail) 21 | sort(border, border + N); N = unique(border, border + N) - border; 22 | for (int i = 0; i < N; ++i) { 23 | Border &cur = border[i]; 24 | while (head + 1 < tail && !checkBorder(que[tail - 2], que[tail - 1], cur)) --tail; 25 | while (head + 1 < tail && !checkBorder(que[head], que[head + 1], cur)) ++head; 26 | que[tail++] = cur; 27 | } while (head + 1 < tail && !checkBorder(que[tail - 2], que[tail - 1], que[head])) --tail; 28 | while (head + 1 < tail && !checkBorder(que[head], que[head + 1], que[tail - 1])) ++head; 29 | if (tail - head <= 2) return 0.0; 30 | Foru(i, head, tail) ps[cnt++] = isBorder(que[i], que[(i + 1 == tail) ? (head) : (i + 1)]); 31 | double area = 0; Foru(i, 0, cnt) area += det(ps[i], ps[(i + 1) % cnt]); 32 | return fabs(area * 0.5); // or (-area * 0.5) 33 | } -------------------------------------------------------------------------------- /src/Computational Geometry/Max Area Empty Convex Hull.cpp: -------------------------------------------------------------------------------- 1 | inline bool toUpRight(const point &a, const point &b) { 2 | int c = sign(b.y - a.y); if (c > 0) return true; 3 | return c == 0 && sign(b.x - a.x) > 0; 4 | } 5 | inline bool cmpByPolarAngle(const point &a, const point &b) { // `counter-clockwise, shorter first if they share the same polar angle` 6 | int c = sign(det(a, b)); if (c != 0) return c > 0; 7 | return sign(b.len() - a.len()) > 0; 8 | } 9 | double maxEmptyConvexHull(int N, point p[]) { 10 | static double dp[MAXN][MAXN]; 11 | static point vec[MAXN]; 12 | static int seq[MAXN]; // `empty triangles formed with $(0, 0), vec[o], vec[ seq[i] ]$` 13 | double ans = 0.0; 14 | Rep(o, 1, N) { 15 | int totVec = 0; 16 | Rep(i, 1, N) if (toUpRight(p[o], p[i])) vec[++totVec] = p[i] - p[o]; 17 | sort(vec + 1, vec + totVec + 1, cmpByPolarAngle); 18 | Rep(i, 1, totVec) Rep(j, 1, totVec) dp[i][j] = 0.0; 19 | Rep(k, 2, totVec) { 20 | int i = k - 1; 21 | while (i > 0 && sign( det(vec[k], vec[i]) ) == 0) --i; 22 | int totSeq = 0; 23 | for (int j; i > 0; i = j) { 24 | seq[++totSeq] = i; 25 | for (j = i - 1; j > 0 && sign(det(vec[i] - vec[k], vec[j] - vec[k])) > 0; --j); 26 | double v = det(vec[i], vec[k]) * 0.5; 27 | if (j > 0) v += dp[i][j]; 28 | dp[k][i] = v; 29 | cMax(ans, v); 30 | } for (int i = totSeq - 1; i >= 1; --i) cMax( dp[k][ seq[i] ], dp[k][seq[i + 1]] ); 31 | } 32 | } return ans; 33 | } -------------------------------------------------------------------------------- /src/Computational Geometry/MinBall.cpp: -------------------------------------------------------------------------------- 1 | int outCnt; point out[4], res; double radius; 2 | void ball() { 3 | static point q[3]; 4 | static double m[3][3], sol[3], L[3], det; 5 | int i, j; res = point(0.0, 0.0, 0.0); radius = 0.0; 6 | switch (outCnt) { 7 | case 1: res = out[0]; break; 8 | case 2: res = (out[0] + out[1]) * 0.5; radius = (res - out[0]).norm(); 9 | break; 10 | case 3: 11 | q[0] = out[1] - out[0]; q[1] = out[2] - out[0]; 12 | for (i = 0; i < 2; ++i) for (j = 0; j < 2; ++j) 13 | m[i][j] = dot(q[i], q[j]) * 2.0; 14 | for (i = 0; i < 2; ++i) sol[i] = dot(q[i], q[i]); 15 | det = m[0][0] * m[1][1] - m[0][1] * m[1][0]; 16 | if (sign(det) == 0) return; 17 | L[0] = (sol[0] * m[1][1] - sol[1] * m[0][1]) / det; 18 | L[1] = (sol[1] * m[0][0] - sol[0] * m[1][0]) / det; 19 | res = out[0] + q[0] * L[0] + q[1] * L[1]; 20 | radius = (res - out[0]).norm(); 21 | break; 22 | case 4: 23 | q[0] = out[1] - out[0]; q[1] = out[2] - out[0]; q[2] = out[3] - out[0]; 24 | for (i = 0; i < 3; ++i) for (j = 0; j < 3; ++j) m[i][j] = dot(q[i], q[j]) * 2; 25 | for (i = 0; i < 3; ++i) sol[i] = dot(q[i], q[i]); 26 | det = m[0][0] * m[1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0] 27 | + m[0][2] * m[2][1] * m[1][0] - m[0][2] * m[1][1] * m[2][0] 28 | - m[0][1] * m[1][0] * m[2][2] - m[0][0] * m[1][2] * m[2][1]; 29 | if (sign(det) == 0) return; 30 | for (j = 0; j < 3; ++j) { for (i = 0; i < 3; ++i) m[i][j] = sol[i]; 31 | L[j] = (m[0][0] * m[1][1] * m[2][2] + m[0][1] * m[1][2] * m[2][0] 32 | + m[0][2] * m[2][1] * m[1][0] - m[0][2] * m[1][1] * m[2][0] 33 | - m[0][1] * m[1][0] * m[2][2] - m[0][0] * m[1][2] * m[2][1]) / det; 34 | for (i = 0; i < 3; ++i) m[i][j] = dot(q[i], q[j]) * 2; 35 | } res = out[0]; 36 | for (i = 0; i < 3; ++i) res += q[i] * L[i]; radius = (res - out[0]).norm(); 37 | } 38 | } 39 | void minball(int n, point pt[]) { 40 | ball(); 41 | if (outCnt < 4) for (int i = 0; i < n; ++i) 42 | if ((res - pt[i]).norm() > +radius + EPS) { 43 | out[outCnt] = pt[i]; ++outCnt; minball(i, pt); --outCnt; 44 | if (i > 0) { 45 | point Tt = pt[i]; 46 | memmove(&pt[1], &pt[0], sizeof(point) * i); 47 | pt[0] = Tt; 48 | } 49 | } 50 | } 51 | pair main(int npoint, point pt[]) { // 0-based 52 | random_shuffle(pt, pt + npoint); radius = -1; 53 | for (int i = 0; i < npoint; i++) { if ((res - pt[i]).norm() > EPS + radius) { 54 | outCnt = 1; out[0] = pt[i]; minball(i, pt); } } 55 | return make_pair(res, sqrt(radius)); 56 | } -------------------------------------------------------------------------------- /src/Computational Geometry/Point.cpp: -------------------------------------------------------------------------------- 1 | #define EPS 1e-7 2 | #define PI 3.1415926535897932384626 3 | 4 | inline int sign(const double &a, const double &eps = EPS) { return a < -eps ? -1 : int(a > eps); } 5 | inline double sqr(const double &x) { return x * x; } 6 | inline double Sqrt(const double &x) { return x < 0 ? 0 : sqrt(x); } 7 | 8 | inline double arcSin(const double &a) { 9 | if (a <= -1.0) return -PI / 2; 10 | if (a >= 1.0) return PI / 2; 11 | return asin(a); 12 | } 13 | 14 | inline double arcCos(const double &a) { 15 | if (a <= -1.0) return PI; 16 | if (a >= 1.0) return 0; 17 | return acos(a); 18 | } 19 | 20 | struct point { 21 | double x, y; 22 | point(): x(0.0), y(0.0) {} 23 | point(const double &x, const double &y): x(x), y(y) {} 24 | point operator + (const point &rhs) const { return point(x + rhs.x, y + rhs.y); } 25 | point operator - (const point &rhs) const { return point(x - rhs.x, y - rhs.y); } 26 | point operator * (const double &k) const { return point(x * k, y * k); } 27 | point operator / (const double &k) const { return point(x / k, y / k); } 28 | double len() const { return hypot(x, y); } 29 | double norm() const { return x * x + y * y; } 30 | point unit() const { double k = len(); return point(x / k, y / k); } 31 | point rot(const double &a) const { return point(x * cos(a) - y * sin(a), x * sin(a) + y * cos(a)); } 32 | friend double dot(const point &a, const point &b) { return a.x * b.x + a.y * b.y; } 33 | friend double det(const point &a, const point &b) { return a.x * b.y - a.y * b.x; } 34 | friend double dist(const point &a, const point &b, const point &c) { // dist from C to AB 35 | return fabs(det(a - c, b - c) / (a - b).len()); 36 | } 37 | friend double angle(const point &a, const point &b) { // angle between a and b 38 | return arcCos(dot(a, b) / a.len() / b.len()); 39 | } 40 | }; 41 | 42 | bool onSeg(const point &a, const point &b, const point &c) { // C is not strict on AB 43 | return sign(dot(a - c, b - c)) <= 0 && sign(det(b - a, c - a)) == 0; 44 | } 45 | 46 | bool lineIntersect(const point &a, const point &b, const point &c, const point &d, point &e) { 47 | double s1 = det(c - a, d - a); 48 | double s2 = det(d - b, c - b); 49 | if (!sign(s1 + s2)) return 0; 50 | e = (b - a) * (s1 / (s1 + s2)) + a; 51 | return 1; 52 | } 53 | 54 | bool segIntersect(const point &a, const point &b, const point &c, const point &d, point &e) { // A simpler version 55 | double s1 = det(c - a, d - a), s2 = det(d - b, c - b); 56 | if (!sign(s1 + s2)) return 0; 57 | e = (b - a) * (s1 / (s1 + s2)) + a; 58 | return onSeg(a, b, e) && onSeg(c, d, e); 59 | } 60 | 61 | // returns 0 if not intersect, 1 if proper intersect, 2 if improper intersect 62 | int iCnt; 63 | int segIntersectCheck(const point &a, const point &b, const point &c, const point &d, point &o) { 64 | static double s1, s2, s3, s4; 65 | int d1 = sign(s1 = det(b - a, c - a)), d2 = sign(s2 = det(b - a, d - a)); 66 | int d3 = sign(s3 = det(d - c, a - c)), d4 = sign(s4 = det(d - c, b - c)); 67 | if ((d1 ^ d2) == -2 && (d3 ^ d4) == -2) { 68 | o = (c * s2 - d * s1) / (s2 - s1); 69 | return 1; 70 | } 71 | iCnt = 0; 72 | if (d1 == 0 && onSeg(a, b, c)) o = c, ++iCnt; 73 | if (d2 == 0 && onSeg(a, b, d)) o = d, ++iCnt; 74 | if (d3 == 0 && onSeg(c, d, a)) o = a, ++iCnt; 75 | if (d4 == 0 && onSeg(c, d, b)) o = b, ++iCnt; 76 | return iCnt ? 2 : 0; 77 | } 78 | -------------------------------------------------------------------------------- /src/Computational Geometry/Polygon Circle Intersection.cpp: -------------------------------------------------------------------------------- 1 | 2 | int N; 3 | double R; // circle: x ^ 2 + y ^ 2 <= R ^ 2 4 | point info[maxn]; 5 | 6 | double triangleCircleIntersection(point pa, point pb) { 7 | if (pa.len() < pb.len()) swap(pa, pb); 8 | if (pb.len() < eps) return 0; 9 | point pc = pb - pa; 10 | double a = pb.len(), b = pa.len(), c = pc.len(); 11 | double cosB = dot(pb, pc) / a / c, B = acos(cosB); 12 | double cosC = dot(pa, pb) / a / b, C = acos(cosC); 13 | double S, h, theta; 14 | if (a > R) { 15 | S = C * 0.5 * R * R; 16 | h = a * b * sin(C) / c; 17 | if (h < R && B < PI * 0.5) 18 | S -= acos(h / R) * R * R - h * sqrt(R * R - h * h); 19 | } else if (b > R) { 20 | theta = PI - B - asin(sin(B) / R * a); 21 | S = 0.5 * a * R * sin(theta) + (C - theta) * 0.5 * R * R; 22 | } else { 23 | S = 0.5 * sin(C) * a * b; 24 | } 25 | return S; 26 | } 27 | 28 | double polygonCircleIntersection() { 29 | double S = 0; 30 | info[N] = info[0]; 31 | for (int i = 0; i < N; ++i) S += triangleCircleIntersection(info[i], info[i + 1]) * sign(det(info[i], info[i + 1])); 32 | return fabs(S); 33 | } 34 | -------------------------------------------------------------------------------- /src/Computational Geometry/Polygon.cpp: -------------------------------------------------------------------------------- 1 | struct Polygon { // stored in [0, n) 2 | int n; point ps[MAXN]; 3 | Polygon cut(const point &a, const point &b) { 4 | static Polygon res; static point o; res.n = 0; 5 | for (int i = 0; i < n; ++i) { 6 | int s1 = sign(det(ps[i] - a, b - a)); 7 | int s2 = sign(det(ps[(i + 1) % n] - a, b - a)); 8 | if (s1 <= 0) res.ps[res.n++] = ps[i]; 9 | if (s1 * s2 < 0) { 10 | lineIntersect(a, b, ps[i], ps[(i + 1) % n], o); 11 | res.ps[res.n++] = o; 12 | } 13 | } return res; 14 | } 15 | bool contain(const point &p) const { // 1 if on border or inner, 0 if outter 16 | static point A, B; int res = 0; 17 | for (int i = 0; i < n; ++i) { 18 | A = ps[i]; B = ps[(i + 1) % n]; 19 | if (p.onSeg(A, B)) return 1; 20 | if (sign(A.y - B.y) <= 0) swap(A, B); 21 | if (sign(p.y - A.y) > 0) continue; 22 | if (sign(p.y - B.y) <= 0) continue; 23 | res += (int)(sign(det(B - p, A - p)) > 0); 24 | } return res & 1; 25 | } 26 | #define qs(x) (ps[x] - ps[0]) 27 | bool convexContain(point p) const { // `counter-clockwise` 28 | point q = qs(n - 1); p = p - ps[0]; 29 | if (!p.inAngle(qs(1), q)) return false; 30 | int L = 0, R = n - 1; 31 | while (L + 1 < R) { int M((L + R) >> 1); 32 | if (p.inAngle(qs(M), q)) L = M; else R = M; 33 | } if (L == 0) return false; point l(qs(L)), r(qs(R)); 34 | return sign( fabs(det(l, p)) + fabs(det(p, r)) + fabs(det(r - l, p - l)) - det(l, r) ) == 0; 35 | } 36 | #undef qs 37 | double isPLAtan2(const point &a, const point &b) { 38 | double k = (b - a).alpha(); if (k < 0) k += 2 * PI; 39 | return k; 40 | } 41 | point isPL_Get(const point &a, const point &b, const point &s1, const point &s2) { 42 | double k1 = det(b - a, s1 - a), k2 = det(b - a, s2 - a); 43 | if (sign(k1) == 0) return s1; 44 | if (sign(k2) == 0) return s2; 45 | return (s1 * k2 - s2 * k1) / (k2 - k1); 46 | } 47 | int isPL_Dic(const point &a, const point &b, int l, int r) { 48 | int s = (det(b - a, ps[l] - a) < 0) ? -1 : 1; 49 | while (l <= r) { 50 | int mid = (l + r) / 2; 51 | if (det(b - a, ps[mid] - a) * s <= 0) r = mid - 1; 52 | else l = mid + 1; 53 | } 54 | return r + 1; 55 | } 56 | int isPL_Find(double k, double w[]) { 57 | if (k <= w[0] || k > w[n - 1]) return 0; 58 | int l = 0, r = n - 1, mid; 59 | while (l <= r) { 60 | mid = (l + r) / 2; 61 | if (w[mid] >= k) r = mid - 1; 62 | else l = mid + 1; 63 | } return r + 1; 64 | } 65 | bool isPL(const point &a, const point &b, point &cp1, point &cp2) { // `$O (log N)$` 66 | static double w[MAXN * 2]; // `pay attention to the array size` 67 | for (int i = 0; i <= n; ++i) ps[i + n] = ps[i]; 68 | for (int i = 0; i < n; ++i) w[i] = w[i + n] = isPLAtan2(ps[i], ps[i + 1]); 69 | int i = isPL_Find(isPLAtan2(a, b), w); 70 | int j = isPL_Find(isPLAtan2(b, a), w); 71 | double k1 = det(b - a, ps[i] - a), k2 = det(b - a, ps[j] - a); 72 | if (sign(k1) * sign(k2) > 0) return false; // `no intersection` 73 | if (sign(k1) == 0 || sign(k2) == 0) { // `intersect with a point or a line in the convex` 74 | if (sign(k1) == 0) { 75 | if (sign(det(b - a, ps[i + 1] - a)) == 0) cp1 = ps[i], cp2 = ps[i + 1]; 76 | else cp1 = cp2 = ps[i]; 77 | return true; 78 | } 79 | if (sign(k2) == 0) { 80 | if (sign(det(b - a, ps[j + 1] - a)) == 0) cp1 = ps[j], cp2 = ps[j + 1]; 81 | else cp1 = cp2 = ps[j]; 82 | } 83 | return true; 84 | } 85 | if (i > j) swap(i, j); 86 | int x = isPL_Dic(a, b, i, j), y = isPL_Dic(a, b, j, i + n); 87 | cp1 = isPL_Get(a, b, ps[x - 1], ps[x]); 88 | cp2 = isPL_Get(a, b, ps[y - 1], ps[y]); 89 | return true; 90 | } 91 | double getI(const point &O) const { 92 | if (n <= 2) return 0; 93 | point G(0.0, 0.0); 94 | double S = 0.0, I = 0.0; 95 | for (int i = 0; i < n; ++i) { 96 | const point &x = ps[i], &y = ps[(i + 1) % n]; 97 | double d = det(x, y); 98 | G = G + (x + y) * d / 3.0; 99 | S += d; 100 | } G = G / S; 101 | for (int i = 0; i < n; ++i) { 102 | point x = ps[i] - G, y = ps[(i + 1) % n] - G; 103 | I += fabs(det(x, y)) * (x.norm() + dot(x, y) + y.norm()); 104 | } 105 | return I = I / 12.0 + fabs(S * 0.5) * (O - G).norm(); 106 | } 107 | }; 108 | -------------------------------------------------------------------------------- /src/Computational Geometry/Voronoi.cpp: -------------------------------------------------------------------------------- 1 | #define Oi(e) ((e)->oi) 2 | #define Dt(e) ((e)->dt) 3 | #define On(e) ((e)->on) 4 | #define Op(e) ((e)->op) 5 | #define Dn(e) ((e)->dn) 6 | #define Dp(e) ((e)->dp) 7 | #define Other(e, p) ((e)->oi == p ? (e)->dt : (e)->oi) 8 | #define Next(e, p) ((e)->oi == p ? (e)->on : (e)->dn) 9 | #define Prev(e, p) ((e)->oi == p ? (e)->op : (e)->dp) 10 | #define V(p1, p2, u, v) (u = p2->x - p1->x, v = p2->y - p1->y) 11 | #define C2(u1, v1, u2, v2) (u1 * v2 - v1 * u2) 12 | #define C3(p1, p2, p3) ((p2->x - p1->x) * (p3->y - p1->y) - (p2->y - p1->y) * (p3->x - p1->x)) 13 | #define Dot(u1, v1, u2, v2) (u1 * u2 + v1 * v2) 14 | #define dis(a,b) (sqrt( (a->x - b->x) * (a->x - b->x) + (a->y - b->y) * (a->y - b->y) )) 15 | const int maxn = 110024; 16 | const int aix = 4; 17 | const double eps = 1e-7; 18 | int n, M, k; 19 | struct gEdge { 20 | int u, v; double w; 21 | bool operator <(const gEdge &e1) const { return w < e1.w - eps; } 22 | } E[aix * maxn], MST[maxn]; 23 | struct point { 24 | double x, y; int index; edge *in; 25 | bool operator <(const point &p1) const { return x < p1.x - eps || (abs(x - p1.x) <= eps && y < p1.y - eps); } 26 | }; 27 | struct edge { point *oi, *dt; edge *on, *op, *dn, *dp; }; 28 | 29 | point p[maxn], *Q[maxn]; 30 | edge mem[aix * maxn], *elist[aix * maxn]; 31 | int nfree; 32 | void Alloc_memory() { nfree = aix * n; edge *e = mem; for (int i = 0; i < nfree; i++) elist[i] = e++; } 33 | void Splice(edge *a, edge *b, point *v) { 34 | edge *next; 35 | if (Oi(a) == v) next = On(a), On(a) = b; else next = Dn(a), Dn(a) = b; 36 | if (Oi(next) == v) Op(next) = b; else Dp(next) = b; 37 | if (Oi(b) == v) On(b) = next, Op(b) = a; else Dn(b) = next, Dp(b) = a; 38 | } 39 | edge *Make_edge(point *u, point *v) { 40 | edge *e = elist[--nfree]; 41 | e->on = e->op = e->dn = e->dp = e; e->oi = u; e->dt = v; 42 | if (!u->in) u->in = e; 43 | if (!v->in) v->in = e; 44 | return e; 45 | } 46 | edge *Join(edge *a, point *u, edge *b, point *v, int side) { 47 | edge *e = Make_edge(u, v); 48 | if (side == 1) { 49 | if (Oi(a) == u) Splice(Op(a), e, u); 50 | else Splice(Dp(a), e, u); 51 | Splice(b, e, v); 52 | } else { 53 | Splice(a, e, u); 54 | if (Oi(b) == v) Splice(Op(b), e, v); 55 | else Splice(Dp(b), e, v); 56 | } return e; 57 | } 58 | void Remove(edge *e) { 59 | point *u = Oi(e), *v = Dt(e); 60 | if (u->in == e) u->in = e->on; 61 | if (v->in == e) v->in = e->dn; 62 | if (Oi(e->on) == u) e->on->op = e->op; else e->on->dp = e->op; 63 | if (Oi(e->op) == u) e->op->on = e->on; else e->op->dn = e->on; 64 | if (Oi(e->dn) == v) e->dn->op = e->dp; else e->dn->dp = e->dp; 65 | if (Oi(e->dp) == v) e->dp->on = e->dn; else e->dp->dn = e->dn; 66 | elist[nfree++] = e; 67 | } 68 | void Low_tangent(edge *e_l, point *o_l, edge *e_r, point *o_r, edge **l_low, point **OL, edge **r_low, point **OR) { 69 | for (point *d_l = Other(e_l, o_l), *d_r = Other(e_r, o_r); ; ) 70 | if (C3(o_l, o_r, d_l) < -eps) e_l = Prev(e_l, d_l), o_l = d_l, d_l = Other(e_l, o_l); 71 | else if (C3(o_l, o_r, d_r) < -eps) e_r = Next(e_r, d_r), o_r = d_r, d_r = Other(e_r, o_r); 72 | else break; 73 | *OL = o_l, *OR = o_r; *l_low = e_l, *r_low = e_r; 74 | } 75 | void Merge(edge *lr, point *s, edge *rl, point *u, edge **tangent) { 76 | double l1, l2, l3, l4, r1, r2, r3, r4, cot_L, cot_R, u1, v1, u2, v2, n1, cot_n, P1, cot_P; 77 | point *O, *D, *OR, *OL; edge *B, *L, *R; 78 | Low_tangent(lr, s, rl, u, &L, &OL, &R, &OR); 79 | for (*tangent = B = Join(L, OL, R, OR, 0), O = OL, D = OR; ; ) { 80 | edge *El = Next(B, O), *Er = Prev(B, D), *next, *prev; 81 | point *l = Other(El, O), *r = Other(Er, D); 82 | V(l, O, l1, l2); V(l, D, l3, l4); V(r, O, r1, r2); V(r, D, r3, r4); 83 | double cl = C2(l1, l2, l3, l4), cr = C2(r1, r2, r3, r4); 84 | bool BL = cl > eps, BR = cr > eps; 85 | if (!BL && !BR) break; 86 | if (BL) { 87 | double dl = Dot(l1, l2, l3, l4); 88 | for (cot_L = dl / cl; ; Remove(El), El = next, cot_L = cot_n) { 89 | next = Next(El, O); V(Other(next, O), O, u1, v1); V(Other(next, O), D, u2, v2); 90 | n1 = C2(u1, v1, u2, v2); if (!(n1 > eps)) break; 91 | cot_n = Dot(u1, v1, u2, v2) / n1; 92 | if (cot_n > cot_L) break; 93 | } 94 | } if (BR) { 95 | double dr = Dot(r1, r2, r3, r4); 96 | for (cot_R = dr / cr; ; Remove(Er), Er = prev, cot_R = cot_P) { 97 | prev = Prev(Er, D); V(Other(prev, D), O, u1, v1); V(Other(prev, D), D, u2, v2); 98 | P1 = C2(u1, v1, u2, v2); if (!(P1 > eps)) break; 99 | cot_P = Dot(u1, v1, u2, v2) / P1; 100 | if (cot_P > cot_R) break; 101 | } 102 | } l = Other(El, O); r = Other(Er, D); 103 | if (!BL || (BL && BR && cot_R < cot_L)) B = Join(B, O, Er, r, 0), D = r; 104 | else B = Join(El, l, B, D, 0), O = l; 105 | } 106 | } 107 | void Divide(int s, int t, edge **L, edge **R) { 108 | edge *a, *b, *c, *ll, *lr, *rl, *rr, *tangent; 109 | int n = t - s + 1; 110 | if (n == 2) *L = *R = Make_edge(Q[s], Q[t]); 111 | else if (n == 3) { 112 | a = Make_edge(Q[s], Q[s + 1]), b = Make_edge(Q[s + 1], Q[t]); 113 | Splice(a, b, Q[s + 1]); 114 | double v = C3(Q[s], Q[s + 1], Q[t]); 115 | if (v > eps) c = Join(a, Q[s], b, Q[t], 0), *L = a, *R = b; 116 | else if (v < -eps) c = Join(a, Q[s], b, Q[t], 1), *L = c, *R = c; 117 | else *L = a, *R = b; 118 | } else if (n > 3) { 119 | int split = (s + t) / 2; 120 | Divide(s, split, &ll, &lr); Divide(split + 1, t, &rl, &rr); 121 | Merge(lr, Q[split], rl, Q[split + 1], &tangent); 122 | if (Oi(tangent) == Q[s]) ll = tangent; 123 | if (Dt(tangent) == Q[t]) rr = tangent; 124 | *L = ll; *R = rr; 125 | } 126 | } 127 | void Make_Graph() { 128 | edge *start, *e; point *u, *v; 129 | for (int i = 0; i < n; i++) { 130 | start = e = (u = &p[i])->in; 131 | do{ v = Other(e, u); 132 | if (u < v) E[M++].u = (u - p, v - p, dis(u, v)); // M < aix * maxn 133 | } while ((e = Next(e, u)) != start); 134 | } 135 | } 136 | int b[maxn]; 137 | int Find(int x) { while (x != b[x]) { b[x] = b[b[x]]; x = b[x]; } return x; } 138 | void Kruskal() { 139 | memset(b, 0, sizeof(b)); sort(E, E + M); 140 | for (int i = 0; i < n; i++) b[i] = i; 141 | for (int i = 0, kk = 0; i < M && kk < n - 1; i++) { 142 | int m1 = Find(E[i].u), m2 = Find(E[i].v); 143 | if (m1 != m2) b[m1] = m2, MST[kk++] = E[i]; 144 | } 145 | } 146 | void solve() { 147 | scanf("%d", &n); 148 | for (int i = 0; i < n; i++) scanf("%lf%lf", &p[i].x, &p[i].y), p[i].index = i, p[i].in = NULL; 149 | Alloc_memory(); sort(p, p + n); 150 | for (int i = 0; i < n; i++) Q[i] = p + i; 151 | edge *L, *R; Divide(0, n - 1, &L, &R); 152 | M = 0; Make_Graph(); Kruskal(); 153 | } 154 | int main() { solve(); return 0; } -------------------------------------------------------------------------------- /src/Computational Geometry/isPL.cpp: -------------------------------------------------------------------------------- 1 | int isPL(point a, point b, vector &res) { // `点逆时针给出,无三点共线` 2 | static double theta[MAXN]; 3 | for (int i = 0; i < n; ++i) theta[i] = (list[(i + 1) % n] - list[i]).atan2(); 4 | double delta = theta[0]; 5 | for (int i = 0; i < n; ++i) theta[i] = normalize(theta[i] - delta); 6 | int x = lower_bound(theta, theta + n, normalize((b - a).atan2() - delta)) - theta; 7 | int y = lower_bound(theta, theta + n, normalize((a - b).atan2() - delta)) - theta; 8 | for (int k = 0; k <= 1; ++k, swap(a, b), swap(x, y)) { 9 | if (y < x) y += n; 10 | int l = x, r = y, m; 11 | while (l + 1 < r) { 12 | if (sign(det(b - a, list[(m = (l + r) / 2) % n] - a)) < 0) l = m; 13 | else r = m; 14 | } 15 | l %= n, r %= n; 16 | if (sign(det(b - a, list[r] - list[l])) == 0) { 17 | if (sign(det(b - a, list[l] - a)) == 0) 18 | return -l; // `直线与 $(list[l], list[r])$ 重合` 19 | } 20 | else { 21 | point p; lineIntersect(list[l], list[r], a, b, p); 22 | if (p.onSeg(list[l], list[r])) 23 | res.push_back(p); 24 | } 25 | } 26 | return res.size(); 27 | } 28 | -------------------------------------------------------------------------------- /src/Data Structure/Dynamic Convex Hull (Insertion Only).cpp: -------------------------------------------------------------------------------- 1 | #define x first // `upperHull $\leftarrow (x, y)$` 2 | #define y second // `lowerHull $\leftarrow (x, -y)$` 3 | typedef map mii; 4 | typedef map::iterator mit; 5 | struct point { point(const mit &p): x(p->first), y(p->second) {} }; 6 | inline bool checkInside(mii &a, const point &p) { // `border inclusive` 7 | int x = p.x, y = p.y; mit p1 = a.lower_bound(x); 8 | if (p1 == a.end()) return false; if (p1->x == x) return y <= p1->y; 9 | if (p1 == a.begin()) return false; mit p2(p1--); 10 | return sign(det(p - point(p1), point(p2) - p)) >= 0; 11 | } inline void addPoint(mii &a, const point &p) { // `no collinear points` 12 | int x = p.x, y = p.y; mit pnt = a.insert(make_pair(x, y)).first, p1, p2; 13 | for (pnt->y = y; ; a.erase(p2)) { 14 | p1 = pnt; if (++p1 == a.end()) break; 15 | p2 = p1; if (++p1 == a.end()) break; 16 | if (det(point(p2) - p, point(p1) - p) < 0) break; 17 | } for ( ; ; a.erase(p2)) { 18 | if ((p1 = pnt) == a.begin()) break; 19 | if (--p1 == a.begin()) break; p2 = p1--; 20 | if (det(point(p2) - p, point(p1) - p) > 0) break; 21 | } 22 | } -------------------------------------------------------------------------------- /src/Data Structure/Functional Treap.cpp: -------------------------------------------------------------------------------- 1 | inline bool randomBySize(int a, int b) { 2 | static long long seed = 1; 3 | return (seed = seed * 48271 % 2147483647) * (a + b) < 2147483647LL * a; 4 | } 5 | tree merge(tree x, tree y) { 6 | if (x == null) return y; if (y == null) return x; 7 | tree t = NULL; 8 | if (randomBySize(x->size, y->size)) t = newNode(x), t->r = merge(x->r, y); 9 | else t = newNode(y), t->l = merge(x, y->l); 10 | update(t); return t; 11 | } 12 | void splitByKey(tree t, int k, tree &l, tree &r) { // `$[-\infty, k) [k, +infty)$` 13 | if (t == null) l = r = null; 14 | else if (t->key < k) l = newNode(t), splitByKey(t->r, k, l->r, r), update(l); 15 | else r = newNode(t), splitByKey(t->l, k, l, r->l), update(r); 16 | } 17 | void splitBySize(tree t, int k, tree &l, tree &r) { // `$[1, k) [k, +\infty)$` 18 | static int s; if (t == null) l = r = null; 19 | else if ((s = t->l->size + 1) < k) l = newNode(t), splitBySize(t->r, k - s, l->r, r), update(l); 20 | else r = newNode(t), splitBySize(t->l, k, l, r->l), update(r); 21 | } -------------------------------------------------------------------------------- /src/Data Structure/KDTree.cpp: -------------------------------------------------------------------------------- 1 | struct Point { int x, y; }; 2 | struct Rectangle { 3 | int lx , rx , ly , ry; 4 | void set(const Point &p) { lx = rx = p.x; ly = ry = p.y; } 5 | void merge(const Point &o) { 6 | lx = min(lx, o.x); rx = max(rx, o.x); ly = min(ly, o.y); ry = max(ry, o.y); 7 | } void merge(const Rectangle &o) { 8 | lx = min(lx , o.lx); rx = max(rx , o.rx); ly = min(ly , o.ly); ry = max(ry , o.ry); 9 | } LL dist(const Point &p) { 10 | LL res = 0; 11 | if (p.x < lx) res += sqr(lx - p.x); else if (p.x > rx) res += sqr(p.x - rx); 12 | if (p.y < ly) res += sqr(ly - p.y); else if (p.y > ry) res += sqr(p.y - ry); 13 | return res; 14 | } 15 | }; 16 | struct Node { int child[2]; Point p; Rectangle rect; }; 17 | const int MAX_N = 1111111; 18 | const LL INF = 100000000; 19 | int n, m, tot, root; LL result; 20 | Point a[MAX_N], p; Node tree[MAX_N]; 21 | int build(int s, int t, bool d) { 22 | int k = ++tot, mid = (s + t) >> 1; 23 | nth_element(a + s, a + mid , a + t, d ? cmpXY : cmpYX); 24 | tree[k].p = a[mid]; tree[k].rect.set(a[mid]); tree[k].child[0] = tree[k].child[1] = 0; 25 | if (s < mid) 26 | tree[k].child[0] = build(s, mid , d ^ 1), tree[k].rect.merge(tree[tree[k].child[0]].rect); 27 | if (mid + 1 < t) 28 | tree[k].child[1] = build(mid + 1, t, d ^ 1), tree[k].rect.merge(tree[tree[k].child[1]].rect); 29 | return k; 30 | } 31 | int insert(int root, bool d) { 32 | if (root == 0) { 33 | tree[++tot].p = p; tree[tot].rect.set(p); tree[tot].child[0] = tree[tot].child[1] = 0; 34 | return tot; 35 | } tree[root].rect.merge(p); 36 | if ((d && cmpXY(p, tree[root].p)) || (!d && cmpYX(p, tree[root].p))) 37 | tree[root].child[0] = insert(tree[root].child[0], d ^ 1); 38 | else tree[root].child[1] = insert(tree[root].child[1], d ^ 1); 39 | return root; 40 | } 41 | void query(int k, bool d) { 42 | if (tree[k].rect.dist(p) >= result) return; 43 | cMin(result, dist(tree[k].p, p)); 44 | if ((d && cmpXY(p, tree[k].p)) || (!d && cmpYX(p, tree[k].p))) { 45 | if (tree[k].child[0]) query(tree[k].child[0], d ^ 1); 46 | if (tree[k].child[1]) query(tree[k].child[1], d ^ 1); 47 | } else { 48 | if (tree[k].child[1]) query(tree[k].child[1], d ^ 1); 49 | if (tree[k].child[0]) query(tree[k].child[0], d ^ 1); 50 | } 51 | } 52 | void example(int n) { 53 | root = tot = 0; scan(a); root = build(0, n, 0); // `init, $a[0 \ldots n - 1]$` 54 | scan(p); root = insert(root, 0); // `insert` 55 | scan(p); result = INF; ans = query(root, 0); // `query` 56 | } -------------------------------------------------------------------------------- /src/Data Structure/KDTree_2.cpp: -------------------------------------------------------------------------------- 1 | struct Point { int x, y, id; }; 2 | struct Rectangle { 3 | int lx, rx, ly, ry; 4 | void set(const Point &p) { lx = rx = p.x; ly = ry = p.y; } 5 | void merge(const Rectangle &o) { 6 | lx = min(lx, o.lx); rx = max(rx, o.rx); ly = min(ly, o.ly); ry = max(ry, o.ry); 7 | } 8 | LL dist(const Point &p) { LL res = 0; 9 | res += max(sqr(rx - p.x), sqr(lx - p.x)); 10 | res += max(sqr(ry - p.y), sqr(ly - p.y)); 11 | return res; 12 | } 13 | }; struct Node { Point p; Rectangle rect; }; 14 | const int MAX_N = 111111; 15 | const LL INF = 1LL << 60; 16 | int n, m; 17 | Point a[MAX_N], b[MAX_N ]; 18 | Node tree[MAX_N * 3]; 19 | Point p; // `p is the query point` 20 | pair result[22]; 21 | void build(int k, int s, int t, bool d) { 22 | int mid = (s + t) >> 1; 23 | nth_element(a + s, a + mid , a + t, d ? cmpX : cmpY); 24 | tree[k].p = a[mid]; 25 | tree[k].rect.set(a[mid]); 26 | if (s < mid) 27 | build(k << 1, s, mid , d ^ 1), tree[k].rect.merge(tree[k << 1]. rect); 28 | if (mid + 1 < t) 29 | build(k << 1 | 1, mid + 1, t, d ^ 1), tree[k].rect.merge(tree[k << 1 | 1]. rect); 30 | } 31 | void query(int k, int s, int t, bool d, int kth) { 32 | if (tree[k].rect.dist(p) < result[kth].first) return; 33 | pair tmp(dist(tree[k].p, p), -tree[k].p.id); 34 | for (int i = 1; i <= kth; i++) if (tmp > result[i]) { 35 | for (int j = kth + 1; j > i; j--) result[j] = result[j - 1]; result[i] = tmp; 36 | break; 37 | } 38 | int mid = (s + t) >> 1; 39 | if ((d && cmpX(p, tree[k].p)) || (!d && cmpY(p, tree[k].p))) { 40 | if (mid + 1 < t) query(k << 1 | 1, mid + 1, t, d ^ 1, kth); 41 | if (s < mid) query(k << 1, s, mid , d ^ 1, kth); 42 | } else { 43 | if (s < mid) query(k << 1, s, mid , d ^ 1, kth); 44 | if (mid + 1 < t) query(k << 1 | 1, mid + 1, t, d ^ 1, kth); 45 | } 46 | } 47 | void example(int n) { 48 | scan(a); build(1, 0, n, 0); // `init, $a[0 \ldots n - 1]$` 49 | scan(p, k); // `query` 50 | Rep(j, 1, k) result[j].first = -1; 51 | query(1, 0, n, 0, k); ans = -result[k].second + 1; 52 | } -------------------------------------------------------------------------------- /src/Data Structure/Leftist Heap.cpp: -------------------------------------------------------------------------------- 1 | tree merge(tree a, tree b) { 2 | if (a == null) return b; 3 | if (b == null) return a; 4 | if (a->key > b->key) swap(a, b); 5 | a->rc = merge(a->rc, b); 6 | a->rc->fa = a; 7 | if (a->lc->dist < a->rc->dist) swap(a->lc, a->rc); 8 | a->dist = a->rc->dist + 1; 9 | return a; 10 | } 11 | void erase(tree t) { 12 | tree x = t->fa, y = merge(t->lc, t->rc); 13 | if (y != null) y->fa = x; 14 | if (x == null) root = y; 15 | else 16 | for ((x->lc == t ? x->lc : x->rc) = y; x != null; y = x, x = x->fa) { 17 | if (x->lc->dist < x->rc->dist) swap(x->lc, x->rc); 18 | if (x->rc->dist + 1 == x->dist) return; 19 | x->dist = x->rc->dist + 1; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Data Structure/Link Cut Tree.cpp: -------------------------------------------------------------------------------- 1 | struct node { int rev; node *pre, *ch[2]; } base[MAXN], nil, *null; 2 | typedef node *tree; 3 | #define isRoot(x) (x->pre->ch[0] != x && x->pre->ch[1] != x) 4 | #define isRight(x) (x->pre->ch[1] == x) 5 | inline void MakeRev(tree t) { if (t != null) { t->rev ^= 1; swap(t->ch[0], t->ch[1]); } } 6 | inline void PushDown(tree t) { if (t->rev) { MakeRev(t->ch[0]); MakeRev(t->ch[1]); t->rev = 0; } } 7 | inline void Rotate(tree x) { 8 | tree y = x->pre; PushDown(y); PushDown(x); 9 | int d = isRight(x); 10 | if (!isRoot(y)) y->pre->ch[isRight(y)] = x; x->pre = y->pre; 11 | if ((y->ch[d] = x->ch[!d]) != null) y->ch[d]->pre = y; 12 | x->ch[!d] = y; y->pre = x; Update(y); 13 | } 14 | inline void Splay(tree x) { 15 | PushDown(x); for (tree y; !isRoot(x); Rotate(x)) { 16 | y = x->pre; if (!isRoot(y)) Rotate(isRight(x) != isRight(y) ? x : y); 17 | } Update(x); 18 | } 19 | inline void Splay(tree x, tree to) { 20 | PushDown(x); for (tree y; (y = x->pre) != to; Rotate(x)) if (y->pre != to) 21 | Rotate(isRight(x) != isRight(y) ? x : y); 22 | Update(x); 23 | } 24 | inline tree Access(tree t) { 25 | tree last = null; for (; t != null; last = t, t = t->pre) Splay(t),t->ch[1] = last, Update(t); 26 | return last; 27 | } 28 | inline void MakeRoot(tree t) { Access(t); Splay(t); MakeRev(t); } 29 | inline tree FindRoot(tree t) { Access(t); Splay(t); tree last = null; 30 | for ( ; t != null; last = t, t = t->ch[0]) PushDown(t); Splay(last); return last; 31 | } 32 | inline void Join(tree x, tree y) { MakeRoot(y); y->pre = x; } 33 | inline void Cut(tree t) {Access(t); Splay(t); t->ch[0]->pre = null; t->ch[0] = null; Update(t);} 34 | inline void Cut(tree x, tree y) { 35 | tree upper = (Access(x), Access(y)); 36 | if (upper == x) { Splay(x); y->pre = null; x->ch[1] = null; Update(x); } 37 | else if (upper == y) { Access(x); Splay(y); x->pre = null; y->ch[1] = null; Update(y); } 38 | else assert(0); // `impossible to happen` 39 | } 40 | inline int Query(tree a, tree b) { // `query the cost in path a <-> b, lca inclusive` 41 | Access(a); tree c = Access(b); // c is lca 42 | int v1 = c->ch[1]->maxCost; Access(a); 43 | int v2 = c->ch[1]->maxCost; 44 | return max(max(v1, v2), c->cost); 45 | } 46 | void Init() { 47 | null = &nil; null->ch[0] = null->ch[1] = null->pre = null; null->rev = 0; 48 | Rep(i, 1, N) { node &n = base[i]; n.rev = 0; n.pre = n.ch[0] = n.ch[1] = null; } 49 | } -------------------------------------------------------------------------------- /src/Data Structure/Treap.cpp: -------------------------------------------------------------------------------- 1 | struct node { int key, prio, size; node *ch[2]; } base[MAXN], *top, *root, *null, nil; 2 | typedef node *tree; 3 | tree newNode(int key) { 4 | static int seed = 3312; 5 | top->key = key; top->prio = seed = int(seed * 48271LL % 2147483647); 6 | top->size = 1; top->ch[0] = top->ch[1] = null; return top++; 7 | } 8 | void Rotate(tree &x, int d) { 9 | tree y = x->ch[!d]; x->ch[!d] = y->ch[d]; y->ch[d] = x; y->size = x->size; 10 | x->size = x->ch[0]->size + 1 + x->ch[1]->size; x = y; 11 | } 12 | void Insert(tree &t, int key) { 13 | if (t == null) t = newNode(key); 14 | else { int d = t->key < key; Insert(t->ch[d], key); ++t->size; 15 | if (t->ch[d]->prio < t->prio) Rotate(t, !d); 16 | } 17 | } 18 | void Delete(tree &t, int key) { 19 | if (t->key != key) { Delete(t->ch[t->key < key], key); --t->size; } 20 | else if (t->ch[0] == null) t = t->ch[1]; 21 | else if (t->ch[1] == null) t = t->ch[0]; 22 | else { int d = t->ch[0]->prio < t->ch[1]->prio; 23 | Rotate(t, d); Delete(t->ch[d], key); --t->size; 24 | } 25 | } -------------------------------------------------------------------------------- /src/Data Structure/TreeDecomposition - Full.cpp: -------------------------------------------------------------------------------- 1 | int N, fa[MAXN], dep[MAXN], Q[MAXN], size[MAXN], own[MAXN]; 2 | int LCA(int x, int y) { if (x == y) return x; 3 | for ( ; ; x = fa[own[x]]) { 4 | if (dep[x] < dep[y]) swap(x, y); if (own[x] == own[y]) return y; 5 | if (dep[own[x]] < dep[own[y]]) swap(x, y); 6 | } return -1; 7 | } 8 | void Decomposion() { 9 | static int path[MAXN]; int x, y, a, next, head = 0, tail = 0, cnt; 10 | for (fa[1] = -1, dep[1] = 0, Q[++tail] = 1; head < tail; ) 11 | for (edge e(fir[x = Q[++head]]); e; e = e->next) if ( (y = e->to) != fa[x] ) 12 | fa[y] = x, dep[y] = dep[x] + 1, Q[++tail] = y; 13 | for (int i = N; i >= 1; --i) { int &res = size[x = Q[i]] = 1; 14 | for (edge e(fir[x]); e; e = e->next) if ( (y = e->to) != fa[x] ) res += size[y]; 15 | } for (int i = 1; i <= N; ++i) own[i] = -1; 16 | for (int i = 1; i <= N; ++i) if (own[a = Q[i]] == -1) 17 | for (x = a, cnt = 0; ; x = next) { 18 | next = -1; own[x] = a; path[++cnt] = x; 19 | for (edge e(fir[x]); e; e = e->next) if ( (y = e->to) != fa[x] ) 20 | if (next == -1 || size[y] > size[next]) next = y; 21 | if (next == -1) { tree[a].init(cnt, path); break; } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Data Structure/TreeDecomposition.cpp: -------------------------------------------------------------------------------- 1 | int N, fa[MAXN], dep[MAXN], que[MAXN], size[MAXN], own[MAXN]; 2 | int LCA(int x, int y) { if (x == y) return x; 3 | for ( ; ; x = fa[own[x]]) { 4 | if (dep[x] < dep[y]) swap(x, y); if (own[x] == own[y]) return y; 5 | if (dep[own[x]] < dep[own[y]]) swap(x, y); 6 | } return -1; 7 | } 8 | void Decomposion() { 9 | static int path[MAXN]; int x, y, a, next, head = 0, tail = 0, cnt; // BFS omitted 10 | for (int i = 1; i <= N; ++i) if (own[a = que[i]] == -1) 11 | for (x = a, cnt = 0; ; x = next) { next = -1; own[x] = a; path[++cnt] = x; 12 | for (edge e(fir[x]); e; e = e->next) if ( (y = e->to) != fa[x] ) 13 | if (next == -1 || size[y] > size[next]) next = y; 14 | if (next == -1) { tree[a].init(cnt, path); break; } 15 | } 16 | } -------------------------------------------------------------------------------- /src/Data Structure/Usage Of Rope.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using __gnu_cxx::crope; using __gnu_cxx::rope; 3 | a = b.substr(from, len); // `$[from, from + len)$` 4 | a = b.substr(from); // `$[from, from]$` 5 | b.c_str(); // `might lead to memory leaks` 6 | b.delete_c_str(); // `delete the c\_{}str that created before` 7 | a.insert(p, str); // `insert str before position $p$` 8 | a.erase(i, n); // `erase $[i, i + n)$` -------------------------------------------------------------------------------- /src/Graph Theory/Blossom Algorithm.cpp: -------------------------------------------------------------------------------- 1 | namespace Blossom { 2 | int n, head, tail, S, T, lca; 3 | int match[MAXN], Q[MAXN], pred[MAXN], label[MAXN], inq[MAXN], inb[MAXN]; 4 | vector link[MAXN]; 5 | inline void push(int x) { Q[tail++] = x; inq[x] = true; } 6 | int findCommonAncestor(int x, int y) { 7 | static bool inPath[MAXN]; for (int i = 0; i < n; ++i) inPath[i] = 0; 8 | for ( ; ; x = pred[ match[x] ]) { x = label[x]; inPath[x] = true; if (x == S) break; } 9 | for ( ; ; y = pred[ match[y] ]) { y = label[y]; if (inPath[y]) break; } return y; 10 | } 11 | void resetTrace(int x, int lca) { 12 | while (label[x] != lca) { int y = match[x]; inb[ label[x] ] = inb[ label[y] ] = true; 13 | x = pred[y]; if (label[x] != lca) pred[x] = y; }} 14 | void blossomContract(int x, int y) { 15 | lca = findCommonAncestor(x, y); 16 | Foru(i, 0, n) inb[i] = 0; resetTrace(x, lca); resetTrace(y, lca); 17 | if (label[x] != lca) pred[x] = y; if (label[y] != lca) pred[y] = x; 18 | Foru(i, 0, n) if (inb[ label[i] ]) { label[i] = lca; if (!inq[i]) push(i); } 19 | } 20 | bool findAugmentingPath() { 21 | Foru(i, 0, n) pred[i] = -1, label[i] = i, inq[i] = 0; 22 | int x, y, z; head = tail = 0; 23 | for (push(S); head < tail; ) for (int i = (int)link[x = Q[head++]].size() - 1; i >= 0; --i) { 24 | y = link[x][i]; if (label[x] == label[y] || x == match[y]) continue; 25 | if (y == S || (match[y] >= 0 && pred[ match[y] ] >= 0)) blossomContract(x, y); 26 | else if (pred[y] == -1) { 27 | pred[y] = x; if (match[y] >= 0) push(match[y]); 28 | else { 29 | for (x = y; x >= 0; x = z) { 30 | y = pred[x], z = match[y]; match[x] = y, match[y] = x; 31 | } return true; }}} return false; 32 | } 33 | int findMaxMatching() { 34 | int ans = 0; Foru(i, 0, n) match[i] = -1; 35 | for (S = 0; S < n; ++S) if (match[S] == -1) if (findAugmentingPath()) ++ans; 36 | return ans; 37 | } 38 | } -------------------------------------------------------------------------------- /src/Graph Theory/Dynamic MST(Offline).cpp: -------------------------------------------------------------------------------- 1 | const int maxn = 100000 + 5; 2 | const int maxm = 1000000 + 5; 3 | const int maxq = 1000000 + 5; 4 | const int qsize = maxm + 3 * maxq; 5 | int n, m, Q, x[qsize], y[qsize], z[qsize], qx[maxq], qy[maxq], a[maxn], *tz; 6 | int kx[maxn], ky[maxn], kt, vd[maxn], id[maxm], app[maxm]; 7 | bool extra[maxm]; 8 | void init() { 9 | scanf("%d%d", &n, &m); for (int i = 0; i < m; i++) scanf("%d%d%d", x + i, y + i, z + i); 10 | scanf("%d", &Q); for (int i = 0; i < Q; i++) { scanf("%d%d", qx + i, qy + i); qx[i]--; } 11 | } 12 | int find(int x) { 13 | int root = x, next; while (a[root]) root = a[root]; 14 | while ((next = a[x]) != 0) a[x] = root, x = next; return root; 15 | } 16 | inline bool cmp(const int &a, const int &b) { return tz[a] < tz[b]; } 17 | void solve(int *qx, int *qy, int Q, int n, int *x, int *y, int *z, int m, long long ans) { 18 | int ri, rj; 19 | if (Q == 1) { 20 | for (int i = 1; i <= n; i++) a[i] = 0; z[qx[0]] = qy[0]; 21 | for (int i = 0; i < m; i++) id[i] = i; 22 | tz = z; sort(id, id + m, cmp); 23 | for (int i = 0; i < m; i++) { 24 | ri = find(x[id[i]]); rj = find(y[id[i]]); 25 | if (ri != rj) ans += z[id[i]], a[ri] = rj; 26 | } printf("%I64d\n", ans); 27 | return; 28 | } int tm = kt = 0, n2 = 0, m2 = 0; 29 | for (int i = 1; i <= n; i++) a[i] = 0; 30 | for (int i = 0; i < Q; i++) { 31 | ri = find(x[qx[i]]); rj = find(y[qx[i]]); if (ri != rj) a[ri] = rj; 32 | } 33 | for (int i = 0; i < m; i++) extra[i] = true; 34 | for (int i = 0; i < Q; i++) extra[qx[i]] = false; 35 | for (int i = 0; i < m; i++) if (extra[i]) id[tm++] = i; 36 | tz = z; sort(id, id + tm, cmp); 37 | for (int i = 0; i < tm; i++) { 38 | ri = find(x[id[i]]); rj = find(y[id[i]]); 39 | if (ri != rj) 40 | a[ri] = rj, ans += z[id[i]], kx[kt] = x[id[i]], ky[kt] = y[id[i]], kt++; 41 | } 42 | for (int i = 1; i <= n; i++) a[i] = 0; 43 | for (int i = 0; i < kt; i++) a[find(kx[i])] = find(ky[i]); 44 | for (int i = 1; i <= n; i++) if (a[i] == 0) vd[i] = ++n2; 45 | for (int i = 1; i <= n; i++) if (a[i] != 0) vd[i] = vd[find(i)]; 46 | int *Nx = x + m, *Ny = y + m, *Nz = z + m; 47 | for (int i = 0; i < m; i++) app[i] = -1; 48 | for (int i = 0; i < Q; i++) 49 | if (app[qx[i]] == -1) 50 | Nx[m2] = vd[x[qx[i]]], Ny[m2] = vd[y[qx[i]]], Nz[m2] = z[qx[i]], app[qx[i]] = m2, m2++; 51 | for (int i = 0; i < Q; i++) { 52 | z[qx[i]] = qy[i]; 53 | qx[i] = app[qx[i]]; 54 | } 55 | for (int i = 1; i <= n2; i++) a[i] = 0; 56 | for (int i = 0; i < tm; i++) { 57 | ri = find(vd[x[id[i]]]); rj = find(vd[y[id[i]]]); 58 | if (ri != rj) 59 | a[ri] = rj, Nx[m2] = vd[x[id[i]]], Ny[m2] = vd[y[id[i]]], Nz[m2] = z[id[i]], m2++; 60 | } 61 | int mid = Q / 2; 62 | solve(qx, qy, mid, n2, Nx, Ny, Nz, m2, ans); 63 | solve(qx + mid, qy + mid, Q - mid, n2, Nx, Ny, Nz, m2, ans); 64 | } 65 | void work() { if (Q) solve(qx, qy, Q, n, x, y, z, m, 0); } 66 | int main() { init(); work(); return 0; } -------------------------------------------------------------------------------- /src/Graph Theory/EulerianWalk.cpp: -------------------------------------------------------------------------------- 1 | vector eulerianWalk(int N, int S) { 2 | static int res[MAXM], stack[MAXN]; static edge cur[MAXN]; 3 | int rcnt = 0, top = 0, x; for (int i = 1; i <= N; ++i) cur[i] = fir[i]; 4 | for (stack[top++] = S; top; ) { 5 | for (x = stack[--top]; ; ) { 6 | edge &e = cur[x]; if (e == NULL) break; 7 | stack[top++] = x; x = e->to; e = e->next; 8 | // 对于无向图需要删掉反向边 9 | } res[rcnt++] = x; 10 | } reverse(res, res + rcnt); return vector(res, res + rcnt); 11 | } -------------------------------------------------------------------------------- /src/Graph Theory/Highest Level Preflow-Push.cpp: -------------------------------------------------------------------------------- 1 | namespace Network { 2 | int S, T, Ncnt, hsize, heap[MAXN], h[MAXN], inq[MAXN], Q[MAXN], vh[MAXN * 2 + 1]; 3 | LL E[MAXN]; edge cur[MAXN]; 4 | inline void pushFlow(int x, int y, edge e) { 5 | int d = (int)min(E[x], (LL)e->c); 6 | E[x] -= d; e->c -= d; E[y] += d; e->op->c += d; 7 | } inline bool heapCmp(int x, int y) { return h[x] < h[y]; } 8 | inline void hpush(int x) { 9 | inq[x] = true; heap[++hsize] = x; push_heap(heap + 1, heap + hsize + 1, heapCmp); 10 | } inline void hpop(int x) { 11 | inq[x] = false; pop_heap(heap + 1, heap + hsize + 1, heapCmp); --hsize; 12 | } LL maxFlow() { 13 | int head = 0, tail = 0, x, y, h0; 14 | memset(h, 63, sizeof(int) * (Ncnt + 1)); 15 | memset(vh, 0, sizeof(int) * (2 * Ncnt + 2)); 16 | memset(E, 0, sizeof(LL) * (Ncnt + 1)); 17 | memset(inq, 0, sizeof(int) * (Ncnt + 1)); 18 | memcpy(cur, fir, sizeof(edge) * (Ncnt + 1)); 19 | for (Q[++tail] = T, h[T] = 0; head < tail; ) 20 | for (edge e(fir[x = Q[++head]]); e; e = e->next) if (e->op->c) 21 | if (h[y = e->to] >= INF) h[y] = h[x] + 1, Q[++tail] = y; 22 | if (h[S] >= Ncnt) return 0; 23 | h[S] = Ncnt; E[S] = LL_INF; 24 | for (int i = 1; i <= Ncnt; ++i) if (h[i] <= Ncnt) ++vh[ h[i] ]; 25 | hsize = 0; 26 | for (edge e(fir[S]); e; e = e->next) if (e->c && h[y = e->to] < Ncnt) { 27 | pushFlow(S, y, e); if (!inq[y] && y != S && y != T) hpush(y); 28 | } while (hsize) { 29 | bool good = false; 30 | for (edge &e(cur[x = heap[1]]); e; e = e->next) if (e->c) 31 | if (h[x] == h[y = e->to] + 1) { 32 | good = true; pushFlow(x, y, e); if (E[x] == 0) hpop(x); 33 | if (inq[y] == false && y != S && y != T) hpush(y); 34 | break; 35 | } 36 | if (!good) { // relabel 37 | hpop(x); --vh[ h0 = h[x] ]; 38 | int &minH = h[x] = INF; cur[x] = NULL; 39 | for (edge e(fir[x]); e; e = e->next) if (e->c) 40 | if ( cMin(minH, h[e->to] + 1) ) cur[x] = fir[x]; 41 | hpush(x); ++vh[ h[x] ]; 42 | if (vh[h0] == 0 && h0 < Ncnt) { 43 | hsize = 0; 44 | for (int i = 1; i <= Ncnt; ++i) { 45 | if (h[i] > h0 && h[i] < Ncnt) --vh[ h[i] ], ++vh[ h[i] = Ncnt + 1 ]; 46 | if (i != S && i != T && E[i]) heap[++hsize] = i; 47 | } make_heap(heap + 1, heap + hsize + 1, heapCmp); 48 | } 49 | } 50 | } return E[T]; 51 | } 52 | } -------------------------------------------------------------------------------- /src/Graph Theory/HopcroftKarp.cpp: -------------------------------------------------------------------------------- 1 | int N, M, level[MAXN], matchX[MAXN], matchY[MAXN]; 2 | bool used[MAXN]; 3 | bool DFS(int x) { 4 | used[x] = true; for (edge e(fir[x]); e; e = e->next) { 5 | int y = e->to, z = matchY[y]; 6 | if (z == -1 || (!used[z] && level[x] < level[z] && DFS(z))) { 7 | matchX[x] = y; matchY[y] = x; return true; 8 | } 9 | } return false; 10 | } 11 | int maxMatch() { 12 | for (int i = 0; i < N; ++i) used[i] = false; 13 | for (int i = 0; i < N; ++i) matchX[i] = -1; 14 | for (int i = 0; i < M; ++i) matchY[i] = -1; 15 | for (int i = 0; i < N; ++i) level[i] = -1; 16 | int match = 0, d; 17 | for ( ; ; match += d) { 18 | static int Q[MAXN * 2 + 1]; 19 | int head = 0, tail = d = 0; 20 | for (int x = 0; x < N; ++x) level[x] = -1; 21 | for (int x = 0; x < N; ++x) if (matchX[x] == -1) 22 | level[x] = 0, Q[++tail] = x; 23 | while (head < tail) 24 | for (edge e(fir[x = Q[++head]]); e; e = e->next) { 25 | int y = e->to, z = matchY[y]; 26 | if (z != -1 && level[z] < 0) level[z] = level[x] + 1, Q[++tail] = z; 27 | } 28 | for (int x = 0; x < N; ++x) used[x] = false; 29 | for (int x = 0; x < N; ++x) if (matchX[x] == -1) if (DFS(x)) ++d; 30 | if (d == 0) break; 31 | } return match; 32 | } -------------------------------------------------------------------------------- /src/Graph Theory/K-shortest Path (Repeat is allowed).cpp: -------------------------------------------------------------------------------- 1 | #define for_each(it, v) for (vector::iterator it = (v).begin(); it != (v).end(); ++it) 2 | const int MAX_N = 10000, MAX_M = 50000, MAX_K = 10000, INF = 1000000000; 3 | struct Edge { int from, to, weight; }; 4 | struct HeapNode { Edge* edge; int depth; HeapNode* child[4]; }; // child[0..1] for heap G, child[2..3] for heap out edge 5 | 6 | int n, m, k, s, t; Edge* edge[MAX_M]; 7 | int dist[MAX_N]; Edge* prev[MAX_N]; 8 | vector graph[MAX_N]; vector graphR[MAX_N]; 9 | HeapNode* nullNode; HeapNode* heapTop[MAX_N]; 10 | 11 | HeapNode* createHeap(HeapNode* curNode, HeapNode* newNode) { 12 | if (curNode == nullNode) return newNode; HeapNode* rootNode = new HeapNode; 13 | memcpy(rootNode, curNode, sizeof(HeapNode)); 14 | if (newNode->edge->weight < curNode->edge->weight) { 15 | rootNode->edge = newNode->edge; rootNode->child[2] = newNode->child[2]; rootNode->child[3] = newNode->child[3]; 16 | newNode->edge = curNode->edge; newNode->child[2] = curNode->child[2]; newNode->child[3] = curNode->child[3]; 17 | } if (rootNode->child[0]->depth < rootNode->child[1]->depth) rootNode->child[0] = createHeap(rootNode->child[0], newNode); 18 | else rootNode->child[1] = createHeap(rootNode->child[1], newNode); 19 | rootNode->depth = max(rootNode->child[0]->depth, rootNode->child[1]->depth) + 1; 20 | return rootNode; 21 | } 22 | bool heapNodeMoreThan(HeapNode* node1, HeapNode* node2) { return node1->edge->weight > node2->edge->weight; } 23 | 24 | int main() { 25 | scanf("%d%d%d", &n, &m, &k); scanf("%d%d", &s, &t); s--, t--; 26 | while (m--) { Edge* newEdge = new Edge; 27 | int i, j, w; scanf("%d%d%d", &i, &j, &w); 28 | i--, j--; newEdge->from = i; newEdge->to = j; newEdge->weight = w; 29 | graph[i].push_back(newEdge); graphR[j].push_back(newEdge); 30 | } 31 | //Dijkstra 32 | queue dfsOrder; memset(dist, -1, sizeof(dist)); 33 | typedef pair > DijkstraQueueItem; 34 | priority_queue, greater > dq; 35 | dq.push(make_pair(0, make_pair(t, (Edge*) NULL))); 36 | while (!dq.empty()) { 37 | int d = dq.top().first; int i = dq.top().second.first; 38 | Edge* edge = dq.top().second.second; dq.pop(); 39 | if (dist[i] != -1) continue; 40 | dist[i] = d; prev[i] = edge; dfsOrder.push(i); 41 | for_each(it, graphR[i]) dq.push(make_pair(d + (*it)->weight, make_pair((*it)->from, *it))); 42 | } 43 | //Create edge heap 44 | nullNode = new HeapNode; nullNode->depth = 0; nullNode->edge = new Edge; nullNode->edge->weight = INF; 45 | fill(nullNode->child, nullNode->child + 4, nullNode); 46 | while (!dfsOrder.empty()) { 47 | int i = dfsOrder.front(); dfsOrder.pop(); 48 | if (prev[i] == NULL) heapTop[i] = nullNode; 49 | else heapTop[i] = heapTop[prev[i]->to]; 50 | vector heapNodeList; 51 | for_each(it, graph[i]) { int j = (*it)->to; if (dist[j] == -1) continue; 52 | (*it)->weight += dist[j] - dist[i]; if (prev[i] != *it) { 53 | HeapNode* curNode = new HeapNode; 54 | fill(curNode->child, curNode->child + 4, nullNode); 55 | curNode->depth = 1; curNode->edge = *it; 56 | heapNodeList.push_back(curNode); 57 | } 58 | } if (!heapNodeList.empty()) { //Create heap out 59 | make_heap(heapNodeList.begin(), heapNodeList.end(), heapNodeMoreThan); 60 | int size = heapNodeList.size(); 61 | for (int p = 0; p < size; p++) { 62 | heapNodeList[p]->child[2] = 2 * p + 1 < size ? heapNodeList[2 * p + 1] : nullNode; 63 | heapNodeList[p]->child[3] = 2 * p + 2 < size ? heapNodeList[2 * p + 2] : nullNode; 64 | } heapTop[i] = createHeap(heapTop[i], heapNodeList.front()); 65 | } 66 | } //Walk on DAG 67 | typedef pair DAGQueueItem; 68 | priority_queue, greater > aq; 69 | if (dist[s] == -1) printf("NO\n"); 70 | else { printf("%d\n", dist[s]); 71 | if (heapTop[s] != nullNode) aq.push(make_pair(dist[s] + heapTop[s]->edge->weight, heapTop[s])); 72 | } k--; while (k--) { 73 | if (aq.empty()) { printf("NO\n"); continue; } 74 | long long d = aq.top().first; HeapNode* curNode = aq.top().second; aq.pop(); 75 | printf("%I64d\n", d); 76 | if (heapTop[curNode->edge->to] != nullNode) 77 | aq.push(make_pair(d + heapTop[curNode->edge->to]->edge->weight, heapTop[curNode->edge->to])); 78 | for (int i = 0; i < 4; i++) if (curNode->child[i] != nullNode) 79 | aq.push(make_pair(d - curNode->edge->weight + curNode->child[i]->edge->weight, curNode->child[i])); 80 | } return 0; 81 | } -------------------------------------------------------------------------------- /src/Graph Theory/K-shortest Path (Repeat is not allowed).cpp: -------------------------------------------------------------------------------- 1 | int Num[10005][205], Path[10005][205], dev[10005], from[10005], value[10005], dist[205], Next[205], Graph[205][205]; 2 | int N, M, K, s, t, tot, cnt; bool forbid[205], hasNext[10005][205]; 3 | struct cmp { 4 | bool operator()(const int &a, const int &b) { 5 | int *i, *j; if (value[a] != value[b]) return value[a] > value[b]; 6 | for (i = Path[a], j = Path[b]; (*i) == (*j); i++, j++); 7 | return (*i) > (*j); 8 | } 9 | }; 10 | void Check(int idx, int st, int *path, int &res) { 11 | int i, j; for (i = 0; i < N; i++) dist[i] = 1000000000, Next[i] = t; 12 | dist[t] = 0; forbid[t] = true; j = t; 13 | for ( ; ; ) { 14 | for (i = 0; i < N; i++) if (!forbid[i] && (i != st || !hasNext[idx][j]) && (dist[j] + Graph[i][j] < dist[i] || (dist[j] + Graph[i][j] == dist[i] && j < Next[i]))) 15 | Next[i] = j, dist[i] = dist[j] + Graph[i][j]; 16 | j = -1; for (i = 0; i < N; i++) if (!forbid[i] && (j == -1 || dist[i] < dist[j])) j = i; 17 | if (j == -1) break; forbid[j] = 1; if (j == st) break; 18 | } res += dist[st]; for (i = st; i != t; i = Next[i], path++) (*path) = i; (*path) = i; 19 | } 20 | int main() { 21 | int i, j, k, l; 22 | while (scanf("%d%d%d%d%d", &N, &M, &K, &s, &t) && N) { 23 | priority_queue, cmp> Q; 24 | for (i = 0; i < N; i++) for (j = 0; j < N; j++) Graph[i][j] = 1000000000; 25 | for (i = 0; i < M; i++) { scanf("%d%d%d", &j, &k, &l); Graph[j - 1][k - 1] = l; } 26 | s--; t--; 27 | memset(forbid, false, sizeof(forbid)); memset(hasNext[0], false, sizeof(hasNext[0])); 28 | Check(0, s, Path[0], value[0]); dev[0] = 0; from[0] = 0; Num[0][0] = 0; Q.push(0); 29 | cnt = 1; tot = 1; 30 | for (i = 0; i < K; i++) { 31 | if (Q.empty()) break; l = Q.top(); Q.pop(); 32 | for (j = 0; j <= dev[l]; j++) Num[l][j] = Num[from[l]][j]; 33 | for (; Path[l][j] != t; j++) { 34 | memset(hasNext[tot], false, sizeof(hasNext[tot])); Num[l][j] = tot++; 35 | } for (j = 0; Path[l][j] != t; j++) hasNext[Num[l][j]][Path[l][j + 1]] = true; 36 | for (j = dev[l]; Path[l][j] != t; j++) { 37 | memset(forbid, false, sizeof(forbid)); value[cnt] = 0; 38 | for (k = 0; k < j; k++) { 39 | forbid[Path[l][k]] = true; 40 | Path[cnt][k] = Path[l][k]; 41 | value[cnt] += Graph[Path[l][k]][Path[l][k + 1]]; 42 | } Check(Num[l][j], Path[l][j], &Path[cnt][j], value[cnt]); 43 | if (value[cnt] > 2000000) continue; 44 | dev[cnt] = j; from[cnt] = l; Q.push(cnt); cnt++; 45 | } 46 | } 47 | if (i < K || value[l] > 2000000) printf("None\n"); 48 | else { 49 | for (i = 0; Path[l][i] != t; i++) printf("%d-", Path[l][i] + 1); 50 | printf("%d\n", t + 1); 51 | } 52 | } return 0; 53 | } -------------------------------------------------------------------------------- /src/Graph Theory/KM.cpp: -------------------------------------------------------------------------------- 1 | int N, Tcnt, w[MAXN][MAXN], slack[MAXN]; 2 | int lx[MAXN], linkx[MAXN], visy[MAXN], ly[MAXN], linky[MAXN], visx[MAXN]; // `初值全为0` 3 | bool DFS(int x) { visx[x] = Tcnt; 4 | Rep(y, 1, N) if(visy[y] != Tcnt) { int t = lx[x] + ly[y] - w[x][y]; 5 | if (t == 0) { visy[y] = Tcnt; 6 | if (!linky[y] || DFS(linky[y])) { linkx[x] = y; linky[y] = x; return true; } 7 | } else cMin(slack[y], t); 8 | } return false; 9 | } void KM() { 10 | Tcnt = 0; Rep(x, 1, N) Rep(y, 1, N) cMax(lx[x], w[x][y]); 11 | Rep(S, 1, N) { Rep(i, 1, N) slack[i] = INF; 12 | for (++Tcnt; !DFS(S); ++Tcnt) { int d = INF; 13 | Rep(y, 1, N) if(visy[y] != Tcnt) cMin(d, slack[y]); 14 | Rep(x, 1, N) if(visx[x] == Tcnt) lx[x] -= d; 15 | Rep(y, 1, N) if(visy[y] == Tcnt) ly[y] += d; else slack[y] -= d; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/Graph Theory/MCS.cpp: -------------------------------------------------------------------------------- 1 | class Chordal { // 1-Based, G is the Graph, must be sorted before call Check_Chordal 2 | public: // Construct will sort it automatically 3 | int v[Maxn], id[Maxn]; bool inseq[Maxn]; priority_queue > pq; 4 | vector Construct_Perfect_Elimination_Sequence(vector *G, int n) { // O(m + nlogn) 5 | vector seq(n + 1, 0); 6 | for (int i = 0; i <= n; ++i) inseq[i] = false, sort(G[i].begin(), G[i].end()), v[i] = 0; 7 | int cur = n; pair Mx; while(!pq.empty()) pq.pop(); pq.push(make_pair(0, 1)); 8 | for (int i = n; i >= 1; --i) { 9 | while (!pq.empty() && (Mx = pq.top(), inseq[Mx.second] || Mx.first != v[Mx.second])) pq.pop(); 10 | id[Mx.second] = cur; 11 | int x = seq[cur--] = Mx.second, sz = (int)G[Mx.second].size(); inseq[x] = true; 12 | for (int j = 0; j < sz; ++j) { 13 | int y = G[x][j]; if(!inseq[y]) pq.push(make_pair(++v[y], y)); 14 | } 15 | } return seq; 16 | } 17 | bool Check_Chordal(vector *G, vector &seq, int n) { // O(n + mlogn), plz gen seq first 18 | bool isChordal = true; 19 | for (int i = n - 1; i >= 1 && isChordal; --i) { 20 | int x = seq[i], sz, y = -1; 21 | if ((sz = (int)G[x].size()) == 0) continue; 22 | for(int j = 0; j < sz; ++j) { 23 | if (id[G[x][j]] < i) continue; 24 | if (y == -1 || id[y] > id[G[x][j]]) y = G[x][j]; 25 | } if (y == -1) continue; 26 | for (int j = 0; j < sz; ++j) { 27 | int y1 = G[x][j]; if (id[y1] < i) continue; 28 | if (y1 == y || binary_search(G[y].begin(), G[y].end(), y1)) continue; 29 | isChordal = false; break; 30 | } 31 | } return isChordal; 32 | } 33 | }; -------------------------------------------------------------------------------- /src/Graph Theory/MaxClique.cpp: -------------------------------------------------------------------------------- 1 | namespace MaxClique { // 1-based 2 | int g[MAXN][MAXN], len[MAXN], list[MAXN][MAXN], mc[MAXN], ans, found; 3 | void DFS(int size) { 4 | if (len[size] == 0) { if (size > ans) ans = size, found = true; return; } 5 | for (int k = 0; k < len[size] && !found; ++k) { 6 | if (size + len[size] - k <= ans) break; 7 | int i = list[size][k]; if (size + mc[i] <= ans) break; 8 | for (int j = k + 1, len[size + 1] = 0; j < len[size]; ++j) if (g[i][list[size][j]]) 9 | list[size + 1][len[size + 1]++] = list[size][j]; 10 | DFS(size + 1); 11 | } 12 | } 13 | int work(int n) { 14 | mc[n] = ans = 1; for (int i = n - 1; i; --i) { found = false; len[1] = 0; 15 | for (int j = i + 1; j <= n; ++j) if (g[i][j]) list[1][len[1]++] = j; 16 | DFS(1); mc[i] = ans; 17 | } return ans; 18 | } 19 | } -------------------------------------------------------------------------------- /src/Graph Theory/MaxCliqueCounting.cpp: -------------------------------------------------------------------------------- 1 | namespace MaxCliqueCounting { 2 | int n, ans; 3 | int ne[MAXN], ce[MAXN]; 4 | int g[MAXN][MAXN], list[MAXN][MAXN]; 5 | void dfs(int size) { 6 | int i, j, k, t, cnt, best = 0; 7 | bool bb; 8 | if (ne[size] == ce[size]) { 9 | if (ce[size] == 0) 10 | ++ans; 11 | return; 12 | } 13 | for (t = 0, i = 1; i <= ne[size]; ++i) { 14 | for (cnt = 0, j = ne[size] + 1; j <= ce[size]; ++j) 15 | if (!g[list[size][i]][list[size][j]]) 16 | ++cnt; 17 | if (t == 0 || cnt < best) 18 | t = i, best = cnt; 19 | } 20 | if (t && best <= 0) 21 | return; 22 | for (k = ne[size] + 1; k <= ce[size]; ++k) { 23 | if (t > 0) { 24 | for (i = k; i <= ce[size]; ++i) 25 | if (!g[list[size][t]][list[size][i]]) 26 | break; 27 | swap(list[size][k], list[size][i]); 28 | } 29 | i = list[size][k]; 30 | ne[size + 1] = ce[size + 1] = 0; 31 | for (j = 1; j < k; ++j) 32 | if (g[i][list[size][j]]) 33 | list[size + 1][++ne[size + 1]] = list[size][j]; 34 | for (ce[size + 1] = ne[size + 1], j = k + 1; j <= ce[size]; ++j) 35 | if (g[i][list[size][j]]) 36 | list[size + 1][++ce[size + 1]] = list[size][j]; 37 | dfs(size + 1); 38 | ++ne[size]; 39 | --best; 40 | for (j = k + 1, cnt = 0; j <= ce[size]; ++j) 41 | if (!g[i][list[size][j]]) 42 | ++cnt; 43 | if (t == 0 || cnt < best) 44 | t = k, best = cnt; 45 | if (t && best <= 0) 46 | break; 47 | } 48 | } 49 | void work() { 50 | int i; 51 | ne[0] = 0; 52 | ce[0] = 0; 53 | for (i = 1; i <= n; ++i) 54 | list[0][++ce[0]] = i; 55 | ans = 0; 56 | dfs(0); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Graph Theory/Maxflow.cpp: -------------------------------------------------------------------------------- 1 | namespace Maxflow { 2 | int h[MAXNODE], vh[MAXNODE], S, T, Ncnt; edge cur[MAXNODE], pe[MAXNODE]; 3 | void init(int _S, int _T, int _Ncnt) { S = _S; T = _T; Ncnt = _Ncnt; } 4 | int maxflow() { 5 | static int Q[MAXNODE]; int x, y, augc, flow = 0, head = 0, tail = 0; edge e; 6 | Rep(i, 0, Ncnt) cur[i] = fir[i]; Rep(i, 0, Ncnt) h[i] = INF; Rep(i, 0, Ncnt) vh[i] = 0; 7 | for (Q[++tail] = T, h[T] = 0; head < tail; ) { 8 | x = Q[++head]; ++vh[ h[x] ]; 9 | for (e = fir[x]; e; e = e->next) if (e->op->c) 10 | if (h[y = e->to] >= INF) h[y] = h[x] + 1, Q[++tail] = y; 11 | } for (x = S; h[S] < Ncnt; ) { 12 | for (e = cur[x]; e; e = e->next) if (e->c) 13 | if (h[y = e->to] + 1 == h[x]) { cur[x] = pe[y] = e; x = y; break; } 14 | if (!e) { 15 | if (--vh[ h[x] ] == 0) break; h[x] = Ncnt; cur[x] = NULL; 16 | for (e = fir[x]; e; e = e->next) if (e->c) 17 | if ( cMin( h[x], h[e->to] + 1 ) ) cur[x] = e; 18 | ++vh[ h[x] ]; 19 | if (x != S) x = pe[x]->op->to; 20 | } else if (x == T) { augc = INF; 21 | for (x = T; x != S; x = pe[x]->op->to) cMin(augc, pe[x]->c); 22 | for (x = T; x != S; x = pe[x]->op->to) { 23 | pe[x]->c -= augc; pe[x]->op->c += augc; 24 | } flow += augc; 25 | } 26 | } return flow; 27 | } 28 | } -------------------------------------------------------------------------------- /src/Graph Theory/Minimum Optimum branchings.cpp: -------------------------------------------------------------------------------- 1 | namespace EdmondsAlgorithm { // O(ElogE + V^2) !!! 0-based !!! 2 | struct enode { int from, c, key, delta, dep; enode *ch[2], *next; 3 | } ebase[maxm], *etop, *fir[maxn], nil, *null, *inEdge[maxn], *chs[maxn]; 4 | typedef enode *edge; typedef enode *tree; 5 | int n, m, setFa[maxn], deg[maxn], que[maxn]; 6 | inline void pushDown(tree x) { if (x->delta) { 7 | x->ch[0]->key += x->delta; x->ch[0]->delta += x->delta; 8 | x->ch[1]->key += x->delta; x->ch[1]->delta += x->delta; x->delta = 0; 9 | }} 10 | tree merge(tree x, tree y) { 11 | if (x == null) return y; if (y == null) return x; 12 | if (x->key > y->key) swap(x, y); pushDown(x); x->ch[1] = merge(x->ch[1], y); 13 | if (x->ch[0]->dep < x->ch[1]->dep) swap(x->ch[0], x->ch[1]); 14 | x->dep = x->ch[1]->dep + 1; return x; 15 | } 16 | void addEdge(int u, int v, int w) { 17 | etop->from = u; etop->c = etop->key = w; etop->delta = etop->dep = 0; 18 | etop->next = fir[v]; etop->ch[0] = etop->ch[1] = null; 19 | fir[v] = etop; inEdge[v] = merge(inEdge[v], etop++); 20 | } 21 | void deleteMin(tree &r) { pushDown(r); r = merge(r->ch[0], r->ch[1]); } 22 | int findSet(int x) { return setFa[x] == x ? x : setFa[x] = findSet(setFa[x]); } 23 | void clear(int V, int E) { 24 | null = &nil; null->ch[0] = null->ch[1] = null; null->dep = -1; 25 | n = V; m = E; etop = ebase; Foru(i, 0, V) fir[i] = NULL; Foru(i, 0, V) inEdge[i] = null; 26 | } 27 | int solve(int root) { int res = 0, head, tail; 28 | for (int i = 0; i < n; ++i) setFa[i] = i; 29 | for ( ; ; ) { memset(deg, 0, sizeof(int) * n); chs[root] = inEdge[root]; 30 | for (int i = 0; i < n; ++i) if (i != root && setFa[i] == i) { 31 | while (findSet(inEdge[i]->from) == findSet(i)) deleteMin(inEdge[i]); 32 | ++deg[ findSet((chs[i] = inEdge[i])->from) ]; 33 | } 34 | for (int i = head = tail = 0; i < n; ++i) 35 | if (i != root && setFa[i] == i && deg[i] == 0) que[tail++] = i; 36 | while (head < tail) { 37 | int x = findSet(chs[que[head++]]->from); 38 | if (--deg[x] == 0) que[tail++] = x; 39 | } bool found = false; 40 | for (int i = 0; i < n; ++i) if (i != root && setFa[i] == i && deg[i] > 0) { 41 | int j = i; tree temp = null; found = true; 42 | do {setFa[j = findSet(chs[j]->from)] = i; 43 | deleteMin(inEdge[j]); res += chs[j]->key; 44 | inEdge[j]->key -= chs[j]->key; inEdge[j]->delta -= chs[j]->key; 45 | temp = merge(temp, inEdge[j]); 46 | } while (j != i); inEdge[i] = temp; 47 | } if (!found) break; 48 | } for (int i = 0; i < n; ++ i) if (i != root && setFa[i] == i) res += chs[i]->key; 49 | return res; 50 | } 51 | } 52 | namespace ChuLiu { // O(V ^ 3) !!! 1-based !!! 53 | int n, used[maxn], pass[maxn], eg[maxn], more, que[maxn], g[maxn][maxn]; 54 | void combine(int id, int &sum) { int tot = 0, from, i, j, k; 55 | for ( ; id != 0 && !pass[id]; id = eg[id]) que[tot++] = id, pass[id] = 1; 56 | for (from = 0; from < tot && que[from] != id; from++); 57 | if (from == tot) return; more = 1; 58 | for (i = from; i < tot; i++) { 59 | sum += g[eg[que[i]]][que[i]]; if (i == from) continue; 60 | for (j = used[que[i]] = 1; j <= n; j++) if (!used[j]) 61 | if (g[que[i]][j] < g[id][j]) g[id][j] = g[que[i]][j]; 62 | } 63 | for (i = 1; i <= n; i++) if (!used[i] && i != id) 64 | for (j = from; j < tot; j++) { 65 | k = que[j]; if (g[i][id] > g[i][k] - g[eg[k]][k]) 66 | g[i][id] = g[i][k] - g[eg[k]][k]; 67 | } 68 | } 69 | void clear(int V) { n = V; Rep(i, 1, V) Rep(j, 1, V) g[i][j] = inf; } 70 | int solve(int root) { 71 | int i, j, k, sum = 0; memset(used, 0, sizeof(int) * (n + 1)); 72 | for (more = 1; more; ) { 73 | more = 0; memset(eg, 0, sizeof(int) * (n + 1)); 74 | for (i = 1; i <= n; i++) if (!used[i] && i != root) { 75 | for (j = 1, k = 0; j <= n; j++) if (!used[j] && i != j) 76 | if (k == 0 || g[j][i] < g[k][i]) k = j; 77 | eg[i] = k; 78 | } memset(pass, 0, sizeof(int) * (n + 1)); 79 | for (i = 1; i <= n; i++) if (!used[i] && !pass[i] && i != root) 80 | combine(i, sum); 81 | } for (i = 1; i <= n; i++) if (!used[i] && i != root) sum += g[eg[i]][i]; 82 | return sum; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/Graph Theory/StableMatching.cpp: -------------------------------------------------------------------------------- 1 | namespace StableMatching { 2 | int pairM[MAXN], pairW[MAXN], p[MAXN]; 3 | // init: pairM[0...n - 1] = pairW[0...n - 1] = -1, p[0...n - 1] = 0 4 | void stableMatching(int n, int orderM[MAXN][MAXN], int preferW[MAXN][MAXN]) { 5 | for (int i = 0; i < n; i++) while (pairM[i] < 0) { 6 | int w = orderM[i][p[i]++], m = pairW[w]; 7 | if (m == -1) pairM[i] = w, pairW[w] = i; 8 | else if (preferW[w][i] < preferW[w][m]) 9 | pairM[m] = -1, pairM[i] = w, pairW[w] = i, i = m; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/Graph Theory/Stoer-Wagner.cpp: -------------------------------------------------------------------------------- 1 | int minCut(int N, int G[MAXN][MAXN]) { // 0-based 2 | static int weight[MAXN], used[MAXN]; int ans = INT_MAX; 3 | while (N > 1) { 4 | for (int i = 0; i < N; ++i) used[i] = false; used[0] = true; 5 | for (int i = 0; i < N; ++i) weight[i] = G[i][0]; 6 | int S = -1, T = 0; 7 | for (int _r = 2; _r <= N; ++_r) { // N - 1 selections 8 | int x = -1; 9 | for (int i = 0; i < N; ++i) if (!used[i]) 10 | if (x == -1 || weight[i] > weight[x]) x = i; 11 | for (int i = 0; i < N; ++i) weight[i] += G[x][i]; 12 | S = T; T = x; used[x] = true; 13 | } ans = min(ans, weight[T]); 14 | for (int i = 0; i < N; ++i) G[i][S] += G[i][T], G[S][i] += G[i][T]; 15 | G[S][S] = 0; --N; 16 | for (int i = 0; i <= N; ++i) swap(G[i][T], G[i][N]); 17 | for (int i = 0; i < N; ++i) swap(G[T][i], G[N][i]); 18 | } return ans; 19 | } -------------------------------------------------------------------------------- /src/Graph Theory/TwoSat SCC.cpp: -------------------------------------------------------------------------------- 1 | namespace SCC { 2 | int code[MAXN * 2], seq[MAXN * 2], sCnt; 3 | void DFS_1(int x) { code[x] = 1; 4 | for (edge e(fir[x]); e; e = e->next) if (code[e->to] == -1) DFS_1(e->to); 5 | seq[++sCnt] = x; 6 | } void DFS_2(int x) { code[x] = sCnt; 7 | for (edge e(fir2[x]); e; e = e->next) if (code[e->to] == -1) DFS_2(e->to); } 8 | void SCC(int N) { 9 | sCnt = 0; for (int i = 1; i <= N; ++i) code[i] = -1; 10 | for (int i = 1; i <= N; ++i) if (code[i] == -1) DFS_1(i); 11 | sCnt = 0; for (int i = 1; i <= N; ++i) code[i] = -1; 12 | for (int i = N; i >= 1; --i) if (code[seq[i]] == -1) { 13 | ++sCnt; DFS_2(seq[i]); } 14 | } 15 | }// true - 2i - 1 16 | // false - 2i 17 | bool TwoSat() { SCC::SCC(N + N); 18 | // if code[2i - 1] = code[2i]: no solution 19 | // if code[2i - 1] > code[2i]: i selected. else i not selected 20 | } -------------------------------------------------------------------------------- /src/Math/ExGcd.cpp: -------------------------------------------------------------------------------- 1 | void exgcd(LL x, LL y, LL &a0, LL &b0, LL &g) { 2 | LL a1 = b0 = 0, b1 = a0 = 1, t; 3 | while (y != 0) { 4 | t = a0 - x / y * a1, a0 = a1, a1 = t; 5 | t = b0 - x / y * b1, b0 = b1, b1 = t; 6 | t = x % y, x = y, y = t; 7 | } if (x < 0) a0 = -a0, b0 = -b0, x = -x; 8 | g = x; 9 | } -------------------------------------------------------------------------------- /src/Math/FFT.cpp: -------------------------------------------------------------------------------- 1 | namespace FFT { 2 | #define mul(a, b) (Complex(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x)) 3 | struct Complex {}; // `something omitted` 4 | void FFT(Complex P[], int n, int oper) { 5 | for (int i = 1, j = 0; i < n - 1; i++) { 6 | for (int s = n; j ^= s >>= 1, ~j & s; ); 7 | if (i < j) swap(P[i], P[j]); 8 | } 9 | for (int d = 0; (1 << d) < n; d++) { 10 | int m = 1 << d, m2 = m * 2; 11 | double p0 = PI / m * oper; 12 | Complex unit_p0(cos(p0), sin(p0)); 13 | for (int i = 0; i < n; i += m2) { 14 | Complex unit(1.0, 0.0); 15 | for (int j = 0; j < m; j++) { 16 | Complex &P1 = P[i + j + m], &P2 = P[i + j]; 17 | Complex t = mul(unit, P1); 18 | P1 = Complex(P2.x - t.x, P2.y - t.y); 19 | P2 = Complex(P2.x + t.x, P2.y - t.y); 20 | unit = mul(unit, unit_p0); 21 | }}}} 22 | vector doFFT(const vector &a, const vector &b) { 23 | vector ret(max(0, (int) a.size() + (int) b.size() - 1), 0); 24 | static Complex A[MAXB], B[MAXB], C[MAXB]; 25 | int len = 1; while (len < (int)ret.size()) len *= 2; 26 | for (int i = 0; i < len; i++) A[i] = i < (int)a.size() ? a[i] : 0; 27 | for (int i = 0; i < len; i++) B[i] = i < (int)b.size() ? b[i] : 0; 28 | FFT(A, len, 1); FFT(B, len, 1); 29 | for (int i = 0; i < len; i++) C[i] = mul(A[i], B[i]); 30 | FFT(C, len, -1); 31 | for (int i = 0; i < (int)ret.size(); i++) 32 | ret[i] = (int) (C[i].x / len + 0.5); 33 | return ret; 34 | } 35 | } -------------------------------------------------------------------------------- /src/Math/FFT_Integer.cpp: -------------------------------------------------------------------------------- 1 | namespace FFT { 2 | // `替代方案: $23068673( = 11 * 2 ^ {21} + 1)$, 原根为 $3$` 3 | const int MOD = 786433, PRIMITIVE_ROOT = 10; // `$3 * 2 ^ {18} + 1$` 4 | const int MAXB = 1 << 20; 5 | int getMod(int downLimit) { // `或者现场自己找一个MOD` 6 | for (int c = 3; ; ++c) { int t = (c << 21) | 1; 7 | if (t >= downLimit && isPrime(t)) return t; 8 | }} 9 | int modInv(int a) { return a <= 1 ? a : (long long) (MOD - MOD / a) * modInv(MOD % a) % MOD; } 10 | void NTT(int P[], int n, int oper) { 11 | for (int i = 1, j = 0; i < n - 1; i++) { 12 | for (int s = n; j ^= s >>= 1, ~j & s;); 13 | if (i < j) swap(P[i], P[j]); 14 | } 15 | for (int d = 0; (1 << d) < n; d++) { 16 | int m = 1 << d, m2 = m * 2; 17 | long long unit_p0 = powMod(PRIMITIVE_ROOT, (MOD - 1) / m2); 18 | if (oper < 0) unit_p0 = modInv(unit_p0); 19 | for (int i = 0; i < n; i += m2) { 20 | long long unit = 1; 21 | for (int j = 0; j < m; j++) { 22 | int &P1 = P[i + j + m], &P2 = P[i + j]; 23 | int t = unit * P1 % MOD; 24 | P1 = (P2 - t + MOD) % MOD; P2 = (P2 + t) % MOD; 25 | unit = unit * unit_p0 % MOD; 26 | }}}} 27 | vector mul(const vector &a, const vector &b) { 28 | vector ret(max(0, (int) a.size() + (int) b.size() - 1), 0); 29 | static int A[MAXB], B[MAXB], C[MAXB]; 30 | int len = 1; while (len < (int)ret.size()) len <<= 1; 31 | for (int i = 0; i < len; i++) A[i] = i < (int)a.size() ? a[i] : 0; 32 | for (int i = 0; i < len; i++) B[i] = i < (int)b.size() ? b[i] : 0; 33 | NTT(A, len, 1); NTT(B, len, 1); 34 | for (int i = 0; i < len; i++) C[i] = (long long) A[i] * B[i] % MOD; 35 | NTT(C, len, -1); for (int i = 0, inv = modInv(len); i < (int)ret.size(); i++) ret[i] = (long long) C[i] * inv % MOD; 36 | return ret; 37 | } 38 | } -------------------------------------------------------------------------------- /src/Math/GaussElimination.cpp: -------------------------------------------------------------------------------- 1 | #define Zero(x) (fabs(x) <= EPS) 2 | bool GaussElimination(double G[MAXN][MAXM], int N, int M) { 3 | int rb = 1; memset(res, 0, sizeof(res)); 4 | Rep(i_th, 1, N) { int maxRow = 0; 5 | Rep(row, rb, N) if (!Zero(G[row][i_th])) 6 | if (!maxRow || fabs(G[row][i_th]) > fabs(G[maxRow][i_th])) 7 | maxRow = row; 8 | if (!maxRow) continue; 9 | swapRow(G[rb], G[maxRow]); 10 | maxRow = rb++; 11 | Rep(row, 1, N) if (row != maxRow && !Zero(G[row][i_th])) { 12 | double coef = G[row][i_th] / G[maxRow][i_th]; 13 | Rep(col, 0, M) G[row][col] -= coef * G[maxRow][col]; 14 | } 15 | } 16 | Rep(row, 1, N) if (!Zero(G[row][0])) { 17 | int i_th = 1; 18 | for ( ; i_th <= M; ++i_th) if (!Zero(G[row][i_th])) break; 19 | if (i_th > N) return false; 20 | res[i_th] = G[row][0] / G[row][i_th]; 21 | } 22 | return true; 23 | } -------------------------------------------------------------------------------- /src/Math/HighterResidue.cpp: -------------------------------------------------------------------------------- 1 | vector HigherResidue(int p, int N, int a) { 2 | if ((a %= p) == 0) return vector(1, 0); 3 | int g = findPrimitiveRoot(p), m = modLog(g, a, p); // `$g ^ m \equiv a \pmod(p)$` 4 | if (m == -1) return vector(0); 5 | LL B = p - 1, x, y, d; exgcd(N, B, x, y, d); 6 | if (m % d != 0) return vector(0); 7 | vector ret; 8 | x = (x * (m / d) % B + B) % B; // `g ^ B \pmod(p) \equiv g ^ (p - 1) \pmod(p) \equiv 1` 9 | for (int i = 0, delta = B / d; i < d; ++i) { 10 | x = (x + delta) % B; ret.push_back((int)powMod(g, x, p)); 11 | } sort(ret.begin(), ret.end()); 12 | ret.resize(unique(ret.begin(), ret.end()) - ret.begin()); 13 | return ret; 14 | } -------------------------------------------------------------------------------- /src/Math/Linear Congruence.cpp: -------------------------------------------------------------------------------- 1 | // Warning: Pay Attention to Integer Overflow ! 2 | 3 | int gcd(int a, int b) { 4 | if (a < 0) a = -a; 5 | if (b < 0) b = -b; 6 | if (a == 0 || b == 0) return a + b; 7 | for (int c; (c = a % b) != 0; a = b, b = c); 8 | return b; 9 | } 10 | 11 | int powMod(int a, int d, int MOD) { 12 | int res = 1; 13 | for ( ; d; d >>= 1) { 14 | if (d & 1) 15 | res = res * a % MOD; 16 | a = a * a % MOD; 17 | } 18 | return res; 19 | } 20 | 21 | int modInv(int a, int p) { 22 | if (a <= 1) return a % p; 23 | int ret = -(p / a) * modInv(p % a, p) % p; 24 | return (ret == 0) ? (ret) : (ret + p); 25 | } 26 | 27 | bool congruence(int n, int A[], int B[], int M[], int &x, int &m) { 28 | x = 0; 29 | m = 1; 30 | for (int i = 0; i < n; ++i) { 31 | int a = A[i] * m, b = B[i] - A[i] * x, d = gcd(a, M[i]); 32 | if (b % d != 0) 33 | return false; 34 | x += m * (b / d * modInv(a / d, M[i] / d) % (M[i] / d)); 35 | m *= M[i] / d; 36 | } 37 | x %= m; 38 | return true; 39 | } 40 | -------------------------------------------------------------------------------- /src/Math/Linear Recursive Equation.cpp: -------------------------------------------------------------------------------- 1 | vector recFormula(int n, int k[], int m) { 2 | vector c(n + 1, 0); 3 | if (m < n) c[m] = 1; 4 | else { 5 | static int a[MAX_K * 2 + 1]; 6 | vector b = recFormula(n, k, m >> 1); 7 | for (int i = 0; i < n + n; ++i) a[i] = 0; 8 | int s = m & 1; 9 | for (int i = 0; i < n; i++) { 10 | for (int j = 0; j < n; j++) a[i + j + s] += b[i] * b[j]; 11 | c[n] += b[i]; 12 | } c[n] = (c[n] + 1) * b[n]; 13 | for (int i = n * 2 - 1; i >= n; i--) { 14 | int add = a[i]; if (add == 0) continue; 15 | for (int j = 0; j < n; j++) a[i - n + j] += k[j] * add; 16 | c[n] += add; 17 | } for (int i = 0; i < n; ++i) c[i] = a[i]; 18 | } return c; 19 | } -------------------------------------------------------------------------------- /src/Math/MillerRabin.cpp: -------------------------------------------------------------------------------- 1 | bool test(LL n, int base) { 2 | LL m = n - 1, ret = 0; int s = 0; 3 | for ( ; m % 2 == 0; ++s) m >>= 1; ret = pow_mod(base, m, n); 4 | if (ret == 1 || ret == n - 1) return true; 5 | for (--s; s >= 0; --s) { 6 | ret = multiply_mod(ret, ret, n); if (ret == n - 1) return true; 7 | } return false; 8 | } 9 | LL special[7] = { 10 | 1373653LL, 25326001LL, 11 | 3215031751LL, 25000000000LL, 12 | 2152302898747LL, 3474749660383LL, 341550071728321LL}; 13 | /* 14 | * n < 2047 test[] = {2} 15 | * n < 1,373,653 test[] = {2, 3} 16 | * n < 9,080,191 test[] = {31, 73} 17 | * n < 25,326,001 test[] = {2, 3, 5} 18 | * n < 4,759,123,141 test[] = {2, 7, 61} 19 | * n < 1,122,004,669,633 test[] = {2, 13, 23, 1662803} 20 | * n < 2,152,302,898,747 test[] = {2, 3, 5, 7, 11} 21 | * n < 3,474,749,660,383 test[] = {2, 3, 5, 7, 11, 13} 22 | * n < 341,550,071,728,321 test[] = {2, 3, 5, 7, 11, 13, 17} 23 | * n < 3,825,123,056,546,413,051 test[] = {2, 3, 5, 7, 11, 13, 17, 19, 23} 24 | */ 25 | bool is_prime(LL n) { 26 | if (n < 2) return false; 27 | if (n < 4) return true; 28 | if (!test(n, 2) || !test(n, 3)) return false; 29 | if (n < special[0]) return true; 30 | if (!test(n, 5)) return false; 31 | if (n < special[1]) return true; 32 | if (!test(n, 7)) return false; 33 | if (n == special[2]) return false; 34 | if (n < special[3]) return true; 35 | if (!test(n, 11)) return false; 36 | if (n < special[4]) return true; 37 | if (!test(n, 13)) return false; 38 | if (n < special[5]) return true; 39 | if (!test(n, 17)) return false; 40 | if (n < special[6]) return true; 41 | return test(n, 19) && test(n, 23) && test(n, 29) && test(n, 31) && test(n, 37); 42 | } -------------------------------------------------------------------------------- /src/Math/ModLog.cpp: -------------------------------------------------------------------------------- 1 | int modLog(int A, int B, int C) { 2 | static pii baby[MAX_SQRT_C + 11]; 3 | int d = 0; LL k = 1, D = 1; B %= C; 4 | for (int i = 0; i < 100; ++i, k = k * A % C) // `$[0, \log C]$` 5 | if (k == B) return i; 6 | for (int g; ; ++d) { 7 | g = gcd(A, C); if (g == 1) break; 8 | if (B % g != 0) return -1; 9 | B /= g; C /= g; D = (A / g * D) % C; 10 | } int m = (int) ceil(sqrt((double) C)); k = 1; 11 | for (int i = 0; i <= m; ++i, k = k * A % C) baby[i] = pii(k, i); 12 | sort(baby, baby + m + 1); // [0, m] 13 | int n = unique(baby, baby + m + 1, equalFirst) - baby, am = powMod(A, m, C); 14 | for (int i = 0; i <= m; ++i) { 15 | LL e, x, y; exgcd(D, C, x, y, e); e = x * B % C; 16 | if (e < 0) e += C; 17 | if (e >= 0) { 18 | int k = lower_bound(baby, baby + n, pii(e, -1)) - baby; 19 | if (baby[k].first == e) return i * m + baby[k].second + d; 20 | } D = D * am % C; 21 | } return -1; 22 | } -------------------------------------------------------------------------------- /src/Math/Nth Residue.cpp: -------------------------------------------------------------------------------- 1 | vector solve(int p, int N, int a) { 2 | if ((a %= p) == 0) return vector(1, 0); 3 | int g = findPrimitiveRoot(p), m = modLog(g, a, p); // g ^ m = a (mod p) 4 | if (m == -1) return vector(0); 5 | LL B = p - 1, x, y, d; exgcd(N, B, x, y, d); 6 | if (m % d != 0) return vector(0); 7 | vector ret; x = (x * (m / d) % B + B) % B; // g ^ B mod p = g ^ (p - 1) mod p = 1 8 | for (int i = 0, delta = B / d; i < d; ++i) { 9 | x = (x + delta) % B; ret.push_back((int)powMod(g, x, p)); 10 | } sort(ret.begin(), ret.end()); 11 | ret.resize(unique(ret.begin(), ret.end()) - ret.begin()); 12 | return ret; 13 | } -------------------------------------------------------------------------------- /src/Math/Pell.cpp: -------------------------------------------------------------------------------- 1 | pair Pell(int n) { 2 | static ULL p[50] = {0, 1}, q[50] = {1, 0}, g[50] = {0, 0}, h[50] = {0, 1}, a[50]; 3 | ULL t = a[2] = Sqrt(n); 4 | for (int i = 2; ; ++i) { 5 | g[i] = -g[i - 1] + a[i] * h[i - 1]; 6 | h[i] = (n - g[i] * g[i]) / h[i - 1]; 7 | a[i + 1] = (g[i] + t) / h[i]; 8 | p[i] = a[i] * p[i - 1] + p[i - 2]; 9 | q[i] = a[i] * q[i - 1] + q[i - 2]; 10 | if (p[i] * p[i] - n * q[i] * q[i] == 1) return make_pair(p[i], q[i]); 11 | } return make_pair(-1, -1); 12 | } 13 | -------------------------------------------------------------------------------- /src/Math/PollardRho.cpp: -------------------------------------------------------------------------------- 1 | LL pollardRho(LL n, LL seed) { 2 | LL x, y, head = 1, tail = 2; x = y = random() % (n - 1) + 1; 3 | for ( ; ; ) { 4 | x = addMod(multiplyMod(x, x, n), seed, n); 5 | if (x == y) return n; LL d = gcd(myAbs(x - y), n); 6 | if (1 < d && d < n) return d; 7 | if (++head == tail) y = x, tail <<= 1; 8 | }} vector divisors; 9 | void factorize(LL n) { // `需要保证 n > 1` 10 | if (isPrime(n)) divisors.push_back(n); 11 | else { LL d = n; 12 | while (d >= n) d = pollardRho(n, random() % (n - 1) + 1); 13 | factorize(n / d); factorize(d); 14 | }} -------------------------------------------------------------------------------- /src/Math/PrimitiveRoot.cpp: -------------------------------------------------------------------------------- 1 | vector findPrimitiveRoot(int N) { 2 | if (N <= 4) return vector(1, max(1, N - 1)); 3 | static int factor[100]; 4 | int phi = N, totF = 0; 5 | { // `check no solution and calculate phi` 6 | int M = N, k = 0; 7 | if (~M & 1) M >>= 1, phi >>= 1; 8 | if (~M & 1) return vector(0); 9 | for (int d = 3; d * d <= M; ++d) if (M % d == 0) { 10 | if (++k > 1) return vector(0); 11 | for (phi -= phi / d; M % d == 0; M /= d); 12 | } if (M > 1) { 13 | if (++k > 1) return vector(0); phi -= phi / M; 14 | } 15 | } { // `factorize phi` 16 | int M = phi; 17 | for (int d = 2; d * d <= M; ++d) if (M % d == 0) { 18 | for ( ; M % d == 0; M /= d); factor[++totF] = d; 19 | } if (M > 1) factor[++totF] = M; 20 | } vector ans; 21 | for (int g = 2; g <= N; ++g) if (Gcd(g, N) == 1) { 22 | bool good = true; 23 | for (int i = 1; i <= totF && good; ++i) 24 | if (powMod(g, phi / factor[i], N) == 1) good = false; 25 | if (!good) continue; 26 | for (int i = 1, gp = g; i <= phi; ++i, gp = (LL)gp * g % N) 27 | if (Gcd(i, phi) == 1) ans.push_back(gp); 28 | break; 29 | } sort(ans.begin(), ans.end()); 30 | return ans; 31 | } -------------------------------------------------------------------------------- /src/Math/QuadraticResidue.cpp: -------------------------------------------------------------------------------- 1 | inline int normalize(LL a, int P) { a %= P; return a < 0 ? a + P : a; } 2 | vector QuadraticResidue(LL a, LL b, LL c, int P) { 3 | int h, t; LL r1, r2, delta, pb = 0; 4 | a = normalize(a, P); b = normalize(b, P); c = normalize(c, P); 5 | if (P == 2) { vector res; 6 | if (c % P == 0) res.push_back(0); 7 | if ((a + b + c) % P == 0) res.push_back(1); 8 | return res; 9 | } delta = b * rev(a + a, P) % P; 10 | a = normalize(-c * rev(a, P) + delta * delta, P); 11 | if (powMod(a, P / 2, P) + 1 == P) return vector(0); 12 | for (t = 0, h = P / 2; h % 2 == 0; ++t, h /= 2); 13 | r1 = powMod(a, h / 2, P); 14 | if (t > 0) { do b = random() % (P - 2) + 2; 15 | while (powMod(b, P / 2, P) + 1 != P); } 16 | for (int i = 1; i <= t; ++i) { 17 | LL d = r1 * r1 % P * a % P; 18 | for (int j = 1; j <= t - i; ++j) d = d * d % P; 19 | if (d + 1 == P) r1 = r1 * pb % P; pb = pb * pb % P; 20 | } r1 = a * r1 % P; r2 = P - r1; 21 | r1 = normalize(r1 - delta, P); r2 = normalize(r2 - delta, P); 22 | if (r1 > r2) swap(r1, r2); vector res(1, r1); 23 | if (r1 != r2) res.push_back(r2); 24 | return res; 25 | } -------------------------------------------------------------------------------- /src/Math/Romberg.cpp: -------------------------------------------------------------------------------- 1 | template double Romberg(const T&f, double a, double b, double eps = 1e-8) { 2 | vector t; double h = b - a, last, now; int k = 1, i = 1; 3 | t.push_back(h * (f(a) + f(b)) / 2); // `梯形` 4 | do { 5 | last = t.back(); now = 0; double x = a + h / 2; 6 | for (int j = 0; j < k; ++j, x += h) now += f(x); 7 | now = (t[0] + h * now) / 2; double k1 = 4.0 / 3.0, k2 = 1.0 / 3.0; 8 | for (int j = 0; j < i; ++j, k1 = k2 + 1) { 9 | double tmp = k1 * now - k2 * t[j]; 10 | t[j] = now; now = tmp; k2 /= 4 * k1 - k2; // `防止溢出` 11 | } t.push_back(now); k *= 2; h /= 2; ++i; 12 | } while (fabs(last - now) > eps); 13 | return t.back(); 14 | } -------------------------------------------------------------------------------- /src/Math/Root Of Polynomial.cpp: -------------------------------------------------------------------------------- 1 | const double error = 1e-12; 2 | const double infi = 1e+12; 3 | int n; double a[10], x[10]; 4 | double f(double a[], int n, double x) { 5 | double tmp = 1, sum = 0; 6 | for (int i = 0; i <= n; i++) sum = sum + a[i] * tmp, tmp = tmp * x; 7 | return sum; 8 | } 9 | double binary(double l, double r, double a[], int n) { 10 | int sl = sign(f(a, n, l)), sr = sign(f(a, n, r)); 11 | if (sl == 0) return l; if (sr == 0) return r; 12 | if (sl * sr > 0) return infi; 13 | while (r - l > error) { 14 | double mid = (l + r) / 2; 15 | int ss = sign(f(a, n, mid)); 16 | if (ss == 0) return mid; 17 | if (ss * sl > 0) l = mid; else r = mid; 18 | } return l; 19 | } 20 | void solve(int n, double a[], double x[], int &nx) { 21 | if (n == 1) { x[1] = -a[0] / a[1]; nx = 1; return; } 22 | double da[10], dx[10]; int ndx; 23 | for (int i = n; i >= 1; i--) da[i - 1] = a[i] * i; 24 | solve(n - 1, da, dx, ndx); nx = 0; 25 | if (ndx == 0) { 26 | double tmp = binary(-infi, infi, a, n); 27 | if (tmp < infi) x[++nx] = tmp; return; 28 | } double tmp = binary(-infi, dx[1], a, n); 29 | if (tmp < infi) x[++nx] = tmp; 30 | for (int i = 1; i <= ndx - 1; i++) { 31 | tmp = binary(dx[i], dx[i + 1], a, n); 32 | if (tmp < infi) x[++nx] = tmp; 33 | } tmp = binary(dx[ndx], infi, a, n); 34 | if (tmp < infi) x[++nx] = tmp; 35 | } 36 | int main() { 37 | scanf("%d", &n); 38 | for (int i = n; i >= 0; i--) scanf("%lf", &a[i]); 39 | int nx; solve(n, a, x, nx); 40 | for (int i = 1; i <= nx; i++) printf("%0.6f\n", x[i]); 41 | return 0; 42 | } -------------------------------------------------------------------------------- /src/Math/SimplexCpp.cpp: -------------------------------------------------------------------------------- 1 | const int MAXN = 11000, MAXM = 1100; 2 | // `here MAXN is the MAX number of conditions, MAXM is the MAX number of vars` 3 | 4 | int avali[MAXM], avacnt; 5 | double A[MAXN][MAXM]; 6 | double b[MAXN], c[MAXM]; 7 | double* simplex(int n, int m) { 8 | // `here n is the number of conditions, m is the number of vars` 9 | m++; 10 | int r = n, s = m - 1; 11 | static double D[MAXN + 2][MAXM + 1]; 12 | static int ix[MAXN + MAXM]; 13 | for (int i = 0; i < n + m; i++) ix[i] = i; 14 | for (int i = 0; i < n; i++) { 15 | for (int j = 0; j < m - 1; j++) D[i][j] = -A[i][j]; 16 | D[i][m - 1] = 1; 17 | D[i][m] = b[i]; 18 | if (D[r][m] > D[i][m]) r = i; 19 | } 20 | for (int j = 0; j < m - 1; j++) D[n][j] = c[j]; 21 | D[n + 1][m - 1] = -1; 22 | for (double d; ; ) { 23 | if (r < n) { 24 | int t = ix[s]; ix[s] = ix[r + m]; ix[r + m] = t; 25 | D[r][s] = 1.0 / D[r][s]; 26 | for (int j = 0; j <= m; j++) if (j != s) D[r][j] *= -D[r][s]; 27 | avacnt = 0; 28 | for (int i = 0; i <= m; ++i) 29 | if(fabs(D[r][i]) > EPS) 30 | avali[avacnt++] = i; 31 | for (int i = 0; i <= n + 1; i++) if (i != r) { 32 | if(fabs(D[i][s]) < EPS) continue; 33 | double *cur1 = D[i], *cur2 = D[r], tmp = D[i][s]; 34 | //for (int j = 0; j <= m; j++) if (j != s) cur1[j] += cur2[j] * tmp; 35 | for(int j = 0; j < avacnt; ++j) if(avali[j] != s) cur1[avali[j]] += cur2[avali[j]] * tmp; 36 | D[i][s] *= D[r][s]; 37 | } 38 | } 39 | r = -1; s = -1; 40 | for (int j = 0; j < m; j++) if (s < 0 || ix[s] > ix[j]) { 41 | if (D[n + 1][j] > EPS || D[n + 1][j] > -EPS && D[n][j] > EPS) s = j; 42 | } 43 | if (s < 0) break; 44 | for (int i = 0; i < n; i++) if (D[i][s] < -EPS) { 45 | if (r < 0 || (d = D[r][m] / D[r][s] - D[i][m] / D[i][s]) < -EPS 46 | || d < EPS && ix[r + m] > ix[i + m]) 47 | r = i; 48 | } 49 | if (r < 0) return null; // `非有界` 50 | } 51 | if (D[n + 1][m] < -EPS) return null; // `无法执行` 52 | static double x[MAXM - 1]; 53 | for (int i = m; i < n + m; i++) if (ix[i] < m - 1) x[ix[i]] = D[i - m][m]; 54 | return x; // `值为 $D[n][m]$` 55 | } 56 | -------------------------------------------------------------------------------- /src/Math/SimplexJava.java: -------------------------------------------------------------------------------- 1 | double[] simplex(double[][] A, double[] b, double[] c) { 2 | int n = A.length, m = A[0].length + 1, r = n, s = m - 1; 3 | double[][] D = new double[n + 2][m + 1]; 4 | int[] ix = new int[n + m]; 5 | for (int i = 0; i < n + m; i++) ix[i] = i; 6 | for (int i = 0; i < n; i++) { 7 | for (int j = 0; j < m - 1; j++) D[i][j] = -A[i][j]; 8 | D[i][m - 1] = 1; D[i][m] = b[i]; if (D[r][m] > D[i][m]) r = i; 9 | } 10 | for (int j = 0; j < m - 1; j++) D[n][j] = c[j]; 11 | D[n + 1][m - 1] = -1; 12 | for (double d; ; ) { 13 | if (r < n) { 14 | int t = ix[s]; ix[s] = ix[r + m]; ix[r + m] = t; D[r][s] = 1.0 / D[r][s]; 15 | for (int j = 0; j <= m; j++) if (j != s) D[r][j] *= -D[r][s]; 16 | for (int i = 0; i <= n + 1; i++) if (i != r) { 17 | for (int j = 0; j <= m; j++) if (j != s) D[i][j] += D[r][j] * D[i][s]; 18 | D[i][s] *= D[r][s]; 19 | } 20 | } r = -1; s = -1; 21 | for (int j = 0; j < m; j++) if (s < 0 || ix[s] > ix[j]) { 22 | if (D[n + 1][j] > EPS || D[n + 1][j] > -EPS && D[n][j] > EPS) s = j; 23 | } 24 | if (s < 0) break; 25 | for (int i = 0; i < n; i++) if (D[i][s] < -EPS) { 26 | if (r < 0 || (d = D[r][m] / D[r][s] - D[i][m] / D[i][s]) < -EPS 27 | || d < EPS && ix[r + m] > ix[i + m]) 28 | r = i; 29 | } 30 | if (r < 0) return null; // `非有界` 31 | } if (D[n + 1][m] < -EPS) return null; // `无法执行` 32 | double[] x = new double[m - 1]; 33 | for (int i = m; i < n + m; i++) if (ix[i] < m - 1) x[ix[i]] = D[i - m][m]; 34 | return x; // `值为 D[n][m]` 35 | } -------------------------------------------------------------------------------- /src/Others/C Split.cpp: -------------------------------------------------------------------------------- 1 | for (char *tok = strtok(ins, delimiters); tok; tok = strtok(NULL, delimiters)) 2 | puts(tok); // '会破坏原字符串ins' -------------------------------------------------------------------------------- /src/Others/DotsBelowLine.cpp: -------------------------------------------------------------------------------- 1 | LL count(LL n, LL a, LL b, LL m) { 2 | if (b == 0) return n * (a / m); 3 | if (a >= m) return n * (a / m) + count(n, a % m, b, m); 4 | if (b >= m) return (n - 1) * n / 2 * (b / m) + count(n, a, b % m, m); 5 | return count((a + b * n) / m, (a + b * n) % m, m, b); 6 | } -------------------------------------------------------------------------------- /src/Others/Expression Evaluation.cpp: -------------------------------------------------------------------------------- 1 | inline int getLevel(char ch) { 2 | switch (ch) { case '+': case '-': return 0; case '*': return 1; } return -1; 3 | } 4 | int evaluate(char *&p, int level) { 5 | int res; 6 | if (level == 2) { 7 | if (*p == '(') ++p, res = evaluate(p, 0); 8 | else res = isdigit(*p) ? *p - '0' : value[*p - 'a']; 9 | ++p; return res; 10 | } res = evaluate(p, level + 1); 11 | for (int next; *p && getLevel(*p) == level; ) { 12 | char op = *p++; next = evaluate(p, level + 1); 13 | switch (op) { 14 | case '+': res += next; break; 15 | case '-': res -= next; break; 16 | case '*': res *= next; break; 17 | } 18 | } return res; 19 | } 20 | int makeEvaluation(char *str) { char *p = str; return evaluate(p, 0); } -------------------------------------------------------------------------------- /src/Others/Java Polynomial.java: -------------------------------------------------------------------------------- 1 | class Polynomial { 2 | final static Polynomial ZERO = new Polynomial(new int[] { 0 }); 3 | final static Polynomial ONE = new Polynomial(new int[] { 1 }); 4 | final static Polynomial X = new Polynomial(new int[] { 0, 1 }); 5 | int[] coef; 6 | static Polynomial valueOf(int val) { return new Polynomial(new int[] { val }); } 7 | Polynomial(int[] coef) { this.coef = Arrays.copyOf(coef, coef.length); } 8 | Polynomial add(Polynomial o, int mod); // omitted 9 | Polynomial subtract(Polynomial o, int mod); // omitted 10 | Polynomial multiply(Polynomial o, int mod); // omitted 11 | Polynomial scale(int o, int mod);// omitted 12 | public String toString() { 13 | int n = coef.length; String ret = ""; 14 | for (int i = n - 1; i > 0; --i) if (coef[i] != 0) 15 | ret += coef[i] + "x^" + i + "+"; 16 | return ret + coef[0]; 17 | } 18 | static Polynomial lagrangeInterpolation(int[] x, int[] y, int mod) { 19 | int n = x.length; Polynomial ret = Polynomial.ZERO; 20 | for (int i = 0; i < n; ++i) { 21 | Polynomial poly = Polynomial.valueOf(y[i]); 22 | for (int j = 0; j < n; ++j) if (i != j) { 23 | poly = poly.multiply( 24 | Polynomial.X.subtract(Polynomial.valueOf(x[j]), mod), mod); 25 | poly = poly.scale(powMod(x[i] - x[j] + mod, mod - 2, mod), mod); 26 | } ret = ret.add(poly, mod); 27 | } return ret; 28 | } 29 | } -------------------------------------------------------------------------------- /src/Others/Josephus.cpp: -------------------------------------------------------------------------------- 1 | int josephus(int n, int m, int k) { int x = -1; 2 | for (int i = n - k + 1; i <= n; i++) x = (x + m) % i; return x; 3 | } 4 | int invJosephus(int n, int m, int x) { 5 | for (int i = n; ; i--) { if (x == i) return n - i; x = (x - m % i + i) % i; } 6 | } -------------------------------------------------------------------------------- /src/Others/K Disjoint LIS.cpp: -------------------------------------------------------------------------------- 1 | int G[MAXN][MAXN]; 2 | void insertYoung(int v) { 3 | for (int x = 1, y = INT_MAX; ; ++x) { 4 | Down(y, *G[x]); while (y > 0 && G[x][y] >= v) --y; 5 | if (++y > *G[x]) { ++*G[x]; G[x][y] = v; break; } 6 | else swap(G[x][y], v); 7 | } 8 | } 9 | int solve(int N, int seq[]) { 10 | Rep(i, 1, N) *G[i] = 0; 11 | Rep(i, 1, N) insertYoung(seq[i]); 12 | printf("%d\n", *G[1] + *G[2]); 13 | return 0; 14 | } -------------------------------------------------------------------------------- /src/Others/LCSFast.cpp: -------------------------------------------------------------------------------- 1 | ULL *a, *b, *s, c, d; 2 | for (i = 0, a = appear[(int)B[k]], b = row[max(k - 1, 0)], s = X; i < bitSetLen; ++i) 3 | *s++ = *a++ | *b++; // `X = row[i - 1] or appear[ B[i] ]` 4 | for (i = 0, a = dp, c = d = 0; i < bitSetLen; ++a, c = d, ++i) 5 | d = *a >> 63, *a = ~((*a << 1) + c); // `row[i] = -((row[i] << 1) + 1)` 6 | for (i = 0, a = dp, b = X, c = 0; i < bitSetLen; ++a, ++b, ++i) 7 | d = *b + c, c = (*a >= -d), *a += d; // `row[i] += X` 8 | for (i = 0, a = dp, b = X; i < bitSetLen; ++a, ++b, ++i) 9 | *a = (*a ^ *b) & *b; // `row[i] = X and (row[i] xor X)` 10 | -------------------------------------------------------------------------------- /src/Others/Long Long Multi and Mod.cpp: -------------------------------------------------------------------------------- 1 | LL multiplyMod(LL a, LL b, LL P) { // `需要保证 a 和 b 非负` 2 | LL t = (a * b - LL((long double)a / P * b + 1e-3) * P) % P; 3 | return t < 0 : t + P : t; 4 | } -------------------------------------------------------------------------------- /src/Others/Manhattan MST.cpp: -------------------------------------------------------------------------------- 1 | const int INF = 1000000005; 2 | struct TreeEdge { 3 | int x, y, z; void make(int _x, int _y, int _z) { x = _x; y = _y; z = _z; } 4 | } data[maxn * 4]; 5 | int n, x[maxn], y[maxn], px[maxn], py[maxn], id[maxn], tree[maxn], node[maxn], val[maxn], fa[maxn]; 6 | bool operator < (const TreeEdge& x, const TreeEdge& y) { return x.z < y.z; } 7 | bool cmp1(int a, int b) { return x[a] < x[b]; } 8 | bool cmp2(int a, int b) { return y[a] < y[b]; } 9 | bool cmp3(int a, int b) { return (y[a] - x[a] < y[b] - x[b] || (y[a] - x[a] == y[b] - x[b] && y[a] > y[b])); } 10 | bool cmp4(int a, int b) { return (y[a] - x[a] > y[b] - x[b] || (y[a] - x[a] == y[b] - x[b] && x[a] > x[b])); } 11 | bool cmp5(int a, int b) { return (x[a] + y[a] > x[b] + y[b] || (x[a] + y[a] == x[b] + y[b] && x[a] < x[b])); } 12 | bool cmp6(int a, int b) { return (x[a] + y[a] < x[b] + y[b] || (x[a] + y[a] == x[b] + y[b] && y[a] > y[b])); } 13 | void Change_X() { 14 | for (int i = 0; i < n; ++i) val[i] = x[i]; 15 | for (int i = 0; i < n; ++i) id[i] = i; 16 | sort(id, id + n, cmp1); 17 | int cntM = 1, last = val[id[0]]; px[id[0]] = 1; 18 | for (int i = 1; i < n; ++i) { 19 | if (val[id[i]] > last) ++cntM, last = val[id[i]]; 20 | px[id[i]] = cntM; 21 | } 22 | } 23 | void Change_Y() { 24 | for (int i = 0; i < n; ++i) val[i] = y[i]; 25 | for (int i = 0; i < n; ++i) id[i] = i; 26 | sort(id, id + n, cmp2); 27 | int cntM = 1, last = val[id[0]]; py[id[0]] = 1; 28 | for (int i = 1; i < n; ++i) { 29 | if (val[id[i]] > last) 30 | ++cntM, last = val[id[i]]; 31 | py[id[i]] = cntM; 32 | } 33 | } 34 | inline int Cost(int a, int b) { return abs(x[a] - x[b]) + abs(y[a] - y[b]); } 35 | int find(int x) { return (fa[x] == x) ? x : (fa[x] = find(fa[x])); } 36 | int main() { 37 | for (int i = 0; i < n; ++i) scanf("%d%d", x + i, y + i); 38 | Change_X(); Change_Y(); 39 | int cntE = 0; for (int i = 0; i < n; ++i) id[i] = i; 40 | sort(id, id + n, cmp3); 41 | for (int i = 1; i <= n; ++i) tree[i] = INF, node[i] = -1; 42 | for (int i = 0; i < n; ++i) { 43 | int Min = INF, Tnode = -1; 44 | for (int k = py[id[i]]; k <= n; k += k & (-k)) 45 | if (tree[k] < Min) Min = tree[k], Tnode = node[k]; 46 | if (Tnode >= 0) data[cntE++].make(id[i], Tnode, Cost(id[i], Tnode)); 47 | int tmp = x[id[i]] + y[id[i]]; 48 | for (int k = py[id[i]]; k; k -= k & (-k)) 49 | if (tmp < tree[k]) tree[k] = tmp, node[k] = id[i]; 50 | } sort(id, id + n, cmp4); 51 | for (int i = 1; i <= n; ++i) tree[i] = INF, node[i] = -1; 52 | for (int i = 0; i < n; ++i) { 53 | int Min = INF, Tnode = -1; 54 | for (int k = px[id[i]]; k <= n; k += k & (-k)) 55 | if (tree[k] < Min) Min = tree[k], Tnode = node[k]; 56 | if (Tnode >= 0) data[cntE++].make(id[i], Tnode, Cost(id[i], Tnode)); 57 | int tmp = x[id[i]] + y[id[i]]; 58 | for (int k = px[id[i]]; k; k -= k & (-k)) 59 | if (tmp < tree[k]) tree[k] = tmp, node[k] = id[i]; 60 | } 61 | sort(id, id + n, cmp5); 62 | for (int i = 1; i <= n; ++i) tree[i] = INF, node[i] = -1; 63 | for (int i = 0; i < n; ++i) { 64 | int Min = INF, Tnode = -1; 65 | for (int k = px[id[i]]; k; k -= k & (-k)) 66 | if (tree[k] < Min) Min = tree[k], Tnode = node[k]; 67 | if (Tnode >= 0) data[cntE++].make(id[i], Tnode, Cost(id[i], Tnode)); 68 | int tmp = -x[id[i]] + y[id[i]]; 69 | for (int k = px[id[i]]; k <= n; k += k & (-k)) 70 | if (tmp < tree[k]) tree[k] = tmp, node[k] = id[i]; 71 | } sort(id, id + n, cmp6); 72 | for (int i = 1; i <= n; ++i) tree[i] = INF, node[i] = -1; 73 | for (int i = 0; i < n; ++i) { 74 | int Min = INF, Tnode = -1; 75 | for (int k = py[id[i]]; k <= n; k += k & (-k)) 76 | if (tree[k] < Min) Min = tree[k], Tnode = node[k]; 77 | if (Tnode >= 0) data[cntE++].make(id[i], Tnode, Cost(id[i], Tnode)); 78 | int tmp = -x[id[i]] + y[id[i]]; 79 | for (int k = py[id[i]]; k; k -= k & (-k)) 80 | if (tmp < tree[k]) tree[k] = tmp, node[k] = id[i]; 81 | } 82 | long long Ans = 0; sort(data, data + cntE); 83 | for (int i = 0; i < n; ++i) fa[i] = i; 84 | for (int i = 0; i < cntE; ++i) if (find(data[i].x) != find(data[i].y)) { 85 | Ans += data[i].z; 86 | fa[fa[data[i].x]] = fa[data[i].y]; 87 | } cout << Ans << endl; 88 | } -------------------------------------------------------------------------------- /src/Others/MinimalColoring.cpp: -------------------------------------------------------------------------------- 1 | const int MAXN = 133; 2 | 3 | namespace MinimalColoring { 4 | // seems to be 0-based ? 5 | int n, s, t, b[MAXN], res[MAXN], id[MAXN]; 6 | int minLimit; 7 | bool g[MAXN][MAXN]; 8 | 9 | void coloring() { // answer is stored in res[] 10 | for (int i = 0; i <= n; ++i) b[i] = 0; 11 | for (int i = 0; i <= n; ++i) res[i] = 0; 12 | for (int i = 0; i <= n; ++i) id[i] = i; 13 | for (s = 0, t = 1; t <= n; ++t) { 14 | int p = t; 15 | for (int i = t; i < n; ++i) { 16 | if (g[ id[t - 1] ][ id[i] ]) ++b[ id[i] ]; 17 | if (b[ id[p] ] < b[ id[i] ]) p = i; 18 | } 19 | swap(id[t], id[p]); 20 | if (b[ id[t] ] == 0) { 21 | minLimit = n + 1; 22 | dfs(new int[n], s, 0); 23 | s = t; 24 | } 25 | } 26 | } 27 | 28 | void dfs(int *is, int p, int k) { 29 | if (k >= minLimit) return; 30 | if (p == t) { 31 | for (int i = s; i < t; i++) res[id[i]] = is[i]; 32 | minLimit = k; 33 | } 34 | else { 35 | bool used = new bool[k + 1]; 36 | for (int i = 0; i < p; i++) if (g[ id[p] ][ id[i] ]) used[ is[i] ] = true; 37 | for (int i = 0; i <= k; i++) if (!used[i]) { 38 | int backUp = is[p]; 39 | is[p] = i; 40 | dfs(is, p + 1, max(k, i + 1)); 41 | is[p] = backUp; 42 | } 43 | delete[] used; 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/Others/Multiple Cover - Full.cpp: -------------------------------------------------------------------------------- 1 | namespace DLX { 2 | struct node { int x, y; node *l, *r, *u, *d; } base[MAX * MAX], *top, *head; 3 | typedef node *link; 4 | int row, col, nGE, ans, stamp, cntc[MAX], vis[MAX]; 5 | vector eachRow[MAX], eachCol[MAX]; 6 | inline void addElement(int x, int y) { 7 | top->x = x; top->y = y; top->l = top->r = top->u = top->d = NULL; 8 | eachRow[x].push_back(top); eachCol[y].push_back(top++); 9 | } 10 | void init(int _row, int _col, int _nGE) { 11 | row = _row; col = _col; nGE = _nGE; top = base; stamp = 0; 12 | for (int i = 0; i <= col; ++i) vis[i] = 0; 13 | for (int i = 0; i <= row; ++i) eachRow[i].clear(); 14 | for (int i = 0; i <= col; ++i) eachCol[i].clear(); 15 | for (int i = 0; i <= col; ++i) addElement(0, i); 16 | head = eachCol[0].front(); 17 | } 18 | void build() { 19 | for (int i = 0; i <= row; ++i) { 20 | vector &v = eachRow[i]; 21 | sort(v.begin(), v.end(), cmpByY); 22 | int s = v.size(); 23 | for (int j = 0; j < s; ++j) { 24 | link l = v[j], r = v[(j + 1) % s]; l->r = r; r->l = l; 25 | } 26 | } 27 | for (int i = 0; i <= col; ++i) { 28 | vector &v = eachCol[i]; 29 | sort(v.begin(), v.end(), cmpByX); 30 | int s = v.size(); 31 | for (int j = 0; j < s; ++j) { 32 | link u = v[j], d = v[(j + 1) % s]; u->d = d; d->u = u; 33 | } 34 | } for (int i = 0; i <= col; ++i) cntc[i] = (int) eachCol[i].size() - 1; 35 | } 36 | void removeExact(link c) { 37 | c->l->r = c->r; c->r->l = c->l; 38 | for (link i = c->d; i != c; i = i->d) 39 | for (link j = i->r; j != i; j = j->r) { 40 | j->d->u = j->u; j->u->d = j->d; --cntc[j->y]; 41 | } 42 | } 43 | void resumeExact(link c) { 44 | for (link i = c->u; i != c; i = i->u) 45 | for (link j = i->l; j != i; j = j->l) { 46 | j->d->u = j; j->u->d = j; ++cntc[j->y]; 47 | } 48 | c->l->r = c; c->r->l = c; 49 | } 50 | void removeRepeat(link c) { 51 | for (link i = c->d; i != c; i = i->d) { 52 | i->l->r = i->r; i->r->l = i->l; 53 | } 54 | } 55 | void resumeRepeat(link c) { 56 | for (link i = c->u; i != c; i = i->u) { 57 | i->l->r = i; i->r->l = i; 58 | } 59 | } 60 | int calcH() { 61 | int y, res = 0; ++stamp; 62 | for (link c = head->r; (y = c->y) <= row && c != head; c = c->r) { 63 | if (vis[y] != stamp) { 64 | vis[y] = stamp; ++res; 65 | for (link i = c->d; i != c; i = i->d) 66 | for (link j = i->r; j != i; j = j->r) vis[j->y] = stamp; 67 | } 68 | } return res; 69 | } 70 | void DFS(int dep) { if (dep + calcH() >= ans) return; 71 | if (head->r->y > nGE || head->r == head) { 72 | if (ans > dep) ans = dep; return; 73 | } link c = NULL; 74 | for (link i = head->r; i->y <= nGE && i != head; i = i->r) 75 | if (!c || cntc[i->y] < cntc[c->y]) c = i; 76 | for (link i = c->d; i != c; i = i->d) { 77 | removeRepeat(i); 78 | for (link j = i->r; j != i; j = j->r) if (j->y <= nGE) removeRepeat(j); 79 | for (link j = i->r; j != i; j = j->r) if (j->y > nGE) removeExact(base + j->y); 80 | DFS(dep + 1); 81 | for (link j = i->l; j != i; j = j->l) if (j->y > nGE) resumeExact(base + j->y); 82 | for (link j = i->l; j != i; j = j->l) if (j->y <= nGE) resumeRepeat(j); 83 | resumeRepeat(i); 84 | } 85 | } 86 | int solve() { build(); ans = INF; DFS(0); return ans; } 87 | } -------------------------------------------------------------------------------- /src/Others/Multiple Cover.cpp: -------------------------------------------------------------------------------- 1 | struct node { int x, y; node *l, *r, *u, *d; } base[MAX * MAX], *top, *head; 2 | typedef node *link; 3 | int row, col, nGE, ans, stamp, cntc[MAX], vis[MAX]; 4 | void removeExact(link c) { c->l->r = c->r; c->r->l = c->l; 5 | for (link i = c->d; i != c; i = i->d) 6 | for (link j = i->r; j != i; j = j->r) j->d->u = j->u, j->u->d = j->d, --cntc[j->y]; 7 | } 8 | void resumeExact(link c) { 9 | for (link i = c->u; i != c; i = i->u) 10 | for (link j = i->l; j != i; j = j->l) j->d->u = j, j->u->d = j, ++cntc[j->y]; 11 | c->l->r = c; c->r->l = c; 12 | } 13 | void removeRepeat(link c) { for (link i = c->d; i != c; i = i->d) i->l->r = i->r, i->r->l = i->l; } 14 | void resumeRepeat(link c) { for (link i = c->u; i != c; i = i->u) i->l->r = i; i->r->l = i; } 15 | int calcH() { int y, res = 0; ++stamp; 16 | for (link c = head->r; (y = c->y) <= row && c != head; c = c->r) if (vis[y] != stamp) { 17 | vis[y] = stamp; ++res; for (link i = c->d; i != c; i = i->d) 18 | for (link j = i->r; j != i; j = j->r) vis[j->y] = stamp; 19 | } return res; 20 | } 21 | void DFS(int dep) { if (dep + calcH() >= ans) return; 22 | if (head->r->y > nGE || head->r == head) { if (ans > dep) ans = dep; return; } 23 | link c = NULL; 24 | for (link i = head->r; i->y <= nGE && i != head; i = i->r) 25 | if (!c || cntc[i->y] < cntc[c->y]) c = i; 26 | for (link i = c->d; i != c; i = i->d) { 27 | removeRepeat(i); 28 | for (link j = i->r; j != i; j = j->r) if (j->y <= nGE) removeRepeat(j); 29 | for (link j = i->r; j != i; j = j->r) if (j->y > nGE) removeExact(base + j->y); 30 | DFS(dep + 1); 31 | for (link j = i->l; j != i; j = j->l) if (j->y > nGE) resumeExact(base + j->y); 32 | for (link j = i->l; j != i; j = j->l) if (j->y <= nGE) resumeRepeat(j); 33 | resumeRepeat(i); 34 | } 35 | } -------------------------------------------------------------------------------- /src/Others/Zeller.cpp: -------------------------------------------------------------------------------- 1 | int getDay(int y, int m, int d) { 2 | if (m <= 2) m += 12, y--; 3 | if (y < 1752 || (y == 1752 && m < 9) || (y == 1752 && m == 9 && d < 3)) 4 | return (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 + 5) % 7 + 1; 5 | return (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7 + 1; 6 | } -------------------------------------------------------------------------------- /src/Others/next nCk.cpp: -------------------------------------------------------------------------------- 1 | void nCk(int n, int k) { 2 | for (int comb = (1 << k) - 1; comb < (1 << n); ) { 3 | int x = comb & -comb, y = comb + x; 4 | comb = (((comb & ~y) / x) >> 1) | y; 5 | } 6 | } -------------------------------------------------------------------------------- /src/Others/nextPermutation.java: -------------------------------------------------------------------------------- 1 | boolean nextPermutation(int[] is) { 2 | int n = is.length; 3 | for (int i = n - 1; i > 0; i--) { 4 | if (is[i - 1] < is[i]) { 5 | int j = n; while (is[i - 1] >= is[--j]); 6 | swap(is, i - 1, j); // swap is[i - 1], is[j] 7 | rev(is, i, n); // reverse is[i, n) 8 | return true; 9 | } 10 | } rev(is, 0, n); 11 | return false; 12 | } 13 | -------------------------------------------------------------------------------- /src/String Related/Aho Corasick Automaton.cpp: -------------------------------------------------------------------------------- 1 | void construct() { 2 | static tree Q[MAX_NODE]; int head = 0, tail = 0; 3 | for (root->fail = root, Q[++tail] = root; head < tail; ) { 4 | tree x = Q[++head]; 5 | // if (x->fail->danger) x->danger = true; 6 | Rep(d, 0, sigma - 1) if (!x->next[d]) 7 | x->next[d] = (x == root) ? (root) : (x->fail->next[d]); 8 | else { 9 | x->next[d]->fail = (x == root) ? (root) : (x->fail->next[d]); 10 | Q[++tail] = x->next[d]; 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /src/String Related/KMP.cpp: -------------------------------------------------------------------------------- 1 | void KMP(char *a, int la, char *b, int lb, int *next, int *ext) { 2 | --a; --b; --next; --ext; 3 | for (int i = 2, j = next[1] = 0; i <= la; i++) { 4 | while (j && a[j + 1] != a[i]) j = next[j]; if (a[j + 1] == a[i]) ++j; next[i] = j; 5 | } for (int i = 1, j = 0; i <= lb; ++i) { 6 | while (j && a[j + 1] != b[i]) j = next[j]; if (a[j + 1] == b[i]) ++j; ext[i] = j; 7 | if (j == la) j = next[j]; 8 | } 9 | } void ExKMP(char *a, int la, char *b, int lb, int *next, int *ext) { 10 | next[0] = la; for (int &j = next[1] = 0; j + 1 < la && a[j] == a[j + 1]; ++j); 11 | for (int i = 2, k = 1; i < la; ++i) { 12 | int p = k + next[k], l = next[i - k]; if (l < p - i) next[i] = l; 13 | else for (int &j = next[k = i] = max(0, p - i); i + j < la && a[j] == a[i + j]; ++j); 14 | } for (int &j = ext[0] = 0; j < la && j < lb && a[j] == b[j]; ++j); 15 | for (int i = 1, k = 0; i < lb; ++i) { 16 | int p = k + ext[k], l = next[i - k]; if (l < p - i) ext[i] = l; 17 | else for (int &j = ext[k = i] = max(0, p - i); j < la && i + j < lb && a[j] == b[i + j]; ++j); 18 | } 19 | } -------------------------------------------------------------------------------- /src/String Related/Manacher.cpp: -------------------------------------------------------------------------------- 1 | // len[i] : the max length of palindrome whose mid point is (i / 2) 2 | void Manacher(int n, char cs[], int len[]) { // 0-based, len[] must be double sized 3 | for (int i = 0; i < n + n; ++i) len[i] = 0; 4 | for (int i = 0, j = 0, k; i < n * 2; i += k, j = max(j - k, 0)) { 5 | while (i - j >= 0 && i + j + 1 < n * 2 && cs[(i - j) / 2] == cs[(i + j + 1) / 2]) j++; 6 | len[i] = j; for (k = 1; i - k >= 0 && j - k >= 0 && len[i - k] != j - k; k++) 7 | len[i + k] = min(len[i - k], j - k); 8 | } 9 | } -------------------------------------------------------------------------------- /src/String Related/Minimial Representation Of A Cyclic String.cpp: -------------------------------------------------------------------------------- 1 | int minimalRepresentation(int N, char *s) { // s must be double-sized and 0-based 2 | int i, j, k, l; for (i = 0; i < N; ++i) s[i + N] = s[i]; s[N + N] = 0; 3 | for (i = 0, j = 1; j < N; ) { 4 | for (k = 0; k < N && s[i + k] == s[j + k]; ++k); 5 | if (k >= N) break; if (s[i + k] < s[j + k]) j += k + 1; 6 | else l = i + k, i = j, j = max(l, j) + 1; 7 | } return i; // [i, i + N) is the minimal representation 8 | } 9 | -------------------------------------------------------------------------------- /src/String Related/Palindrome Automaton.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | const int C = 26; 7 | const int N = 100000; 8 | const int S = N + 2 + C; 9 | 10 | char string[N + 2]; 11 | int s, length[S], suffix[S], go[S][C]; 12 | 13 | int extend(int p, int i) { 14 | while (string[i - 1 - length[p]] != string[i]) { 15 | p = suffix[p]; 16 | } 17 | int q = suffix[p]; 18 | while (string[i - 1 - length[q]] != string[i]) { 19 | q = suffix[q]; 20 | } 21 | int c = string[i] - 'a'; 22 | int pp = go[p][c]; 23 | int qq = go[q][c]; 24 | if (pp == -1) { 25 | length[pp = go[p][c] = s ++] = length[p] + 2; 26 | suffix[pp] = qq; 27 | memset(go[pp], -1, sizeof(go[pp])); 28 | } 29 | return pp; 30 | } 31 | 32 | int main() { 33 | int tests; 34 | scanf("%d", &tests); 35 | for (int t = 1; t <= tests; ++t) { 36 | printf("Case #%d: ", t); 37 | for (int i = 0; i < C + 2; ++ i) { 38 | suffix[i] = 1; 39 | length[i] = std::min(i - 1, 1); 40 | memset(go[i], -1, sizeof(go[i])); 41 | } 42 | suffix[0] = suffix[1] = 0; 43 | for (int i = 0; i < C; ++ i) { 44 | go[0][i] = 2 + i; 45 | } 46 | s = C + 2; 47 | string[0] = '#'; 48 | scanf("%s", string + 1); 49 | int n = strlen(string + 1); 50 | int p = 0; 51 | for (int i = 1; i <= n; ++ i) { 52 | p = extend(p, i); 53 | } 54 | int result = s - (C + 2); 55 | std::sort(string + 1, string + n + 1); 56 | result += std::unique(string + 1, string + n + 1) - string - 1; 57 | printf("%d\n", result); 58 | } 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /src/String Related/Suffix Array Backup.cpp: -------------------------------------------------------------------------------- 1 | namespace SuffixArrayDoubling { 2 | int wa[MAXN], wb[MAXN], wv[MAXN], ws[MAXN]; 3 | int cmp(int *r, int a, int b, int l) { 4 | return r[a] == r[b] && r[a + l] == r[b + l]; 5 | } 6 | void da(int *r, int *sa, int n, int m) { 7 | int i, j, p, *x = wa, *y = wb, *t; 8 | for (i = 0; i < m; i++) ws[i] = 0; 9 | for (i = 0; i < n; i++) ws[x[i] = r[i]]++; 10 | for (i = 1; i < m; i++) ws[i] += ws[i - 1]; 11 | for (i = n - 1; i >= 0; i--) sa[--ws[x[i]]] = i; 12 | for (j = 1, p = 1; p < n; j *= 2, m = p) { 13 | for (p = 0, i = n - j; i < n; i++) y[p++] = i; 14 | for (i = 0; i < n; i++) if (sa[i] >= j) y[p++] = sa[i] - j; 15 | for (i = 0; i < n; i++) wv[i] = x[y[i]]; 16 | for (i = 0; i < m; i++) ws[i] = 0; 17 | for (i = 0; i < n; i++) ws[wv[i]]++; 18 | for (i = 1; i < m; i++) ws[i] += ws[i - 1]; 19 | for (i = n - 1; i >= 0; i--) sa[--ws[wv[i]]] = y[i]; 20 | for (t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n; i++) 21 | x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++; 22 | } 23 | } 24 | } 25 | namespace SuffixArrayDC3 { // `r 与 sa 大小需 3 倍` 26 | #define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb)) 27 | #define G(x) ((x) < tb ? (x) * 3 + 1 : ((x) - tb) * 3 + 2) 28 | int wa[MAXN], wb[MAXN], wv[MAXN], ws[MAXN]; 29 | int c0(int *r, int a, int b) { 30 | return r[a] == r[b] && r[a + 1] == r[b + 1] && r[a + 2] == r[b + 2]; 31 | } 32 | int c12(int k, int *r, int a, int b) { 33 | if (k == 2) return r[a] < r[b] || (r[a] == r[b] && c12(1, r, a + 1, b + 1)); 34 | else return r[a] < r[b] || (r[a] == r[b] && wv[a + 1] < wv[b + 1]); 35 | } 36 | void sort(int *r, int *a, int *b, int n, int m) { 37 | for (int i = 0; i < n; i++) wv[i] = r[a[i]]; 38 | for (int i = 0; i < m; i++) ws[i] = 0; 39 | for (int i = 0; i < n; i++) ws[wv[i]]++; 40 | for (int i = 1; i < m; i++) ws[i] += ws[i - 1]; 41 | for (int i = n - 1; i >= 0; i--) b[--ws[wv[i]]] = a[i]; 42 | } 43 | void dc3(int *r, int *sa, int n, int m) { 44 | int i, j, *rn = r + n, *san = sa + n, ta = 0, tb = (n + 1) / 3, tbc = 0, p; 45 | r[n] = r[n + 1] = 0; 46 | for (i = 0; i < n; i++) if (i % 3 != 0) wa[tbc++] = i; 47 | sort(r + 2, wa, wb, tbc, m); 48 | sort(r + 1, wb, wa, tbc, m); 49 | sort(r, wa, wb, tbc, m); 50 | for (p = 1, rn[F(wb[0])] = 0, i = 1; i < tbc; i++) 51 | rn[F(wb[i])] = c0(r, wb[i - 1], wb[i]) ? p - 1 : p++; 52 | if (p < tbc) dc3(rn, san, tbc, p); 53 | else for (i = 0; i < tbc; i++) san[rn[i]] = i; 54 | for (i = 0; i < tbc; i++) if (san[i] < tb) wb[ta++] = san[i] * 3; 55 | if (n % 3 == 1) wb[ta++] = n - 1; 56 | sort(r, wb, wa, ta, m); 57 | for (i = 0; i < tbc; i++) wv[wb[i] = G(san[i])] = i; 58 | for (i = 0, j = 0, p = 0; i < ta && j < tbc; p++) 59 | sa[p] = c12(wb[j] % 3, r, wa[i], wb[j]) ? wa[i++] : wb[j++]; 60 | for (; i < ta; p++) sa[p] = wa[i++]; 61 | for (; j < tbc; p++) sa[p] = wb[j++]; 62 | } 63 | #undef F 64 | #undef G 65 | } 66 | namespace CalcHeight { 67 | int rank[MAXN], height[MAXN]; 68 | void calheight(int *r, int *sa, int n) { 69 | int i, j, k = 0; 70 | for (i = 1; i <= n; i++) rank[sa[i]] = i; 71 | for (i = 0; i < n; height[rank[i++]] = k) 72 | for (k ? k-- : 0, j = sa[rank[i] - 1]; r[i + k] == r[j + k]; k++); 73 | } 74 | } -------------------------------------------------------------------------------- /src/String Related/Suffix Array.cpp: -------------------------------------------------------------------------------- 1 | namespace SuffixArrayDoubling { 2 | int wa[MAXN], wb[MAXN], wv[MAXN], ws[MAXN]; 3 | int cmp(int *r, int a, int b, int l) { return r[a] == r[b] && r[a + l] == r[b + l]; } 4 | void da(int *r, int *sa, int n, int m) {//the last char must be '$' 5 | int i, j, p, *x = wa, *y = wb, *t; 6 | for (i = 0; i < m; i++) ws[i] = 0; 7 | for (i = 0; i < n; i++) ws[x[i] = r[i]]++; 8 | for (i = 1; i < m; i++) ws[i] += ws[i - 1]; 9 | for (i = n - 1; i >= 0; i--) sa[--ws[x[i]]] = i; 10 | for (j = 1, p = 1; p < n; j *= 2, m = p) { 11 | for (p = 0, i = n - j; i < n; i++) y[p++] = i; 12 | for (i = 0; i < n; i++) if (sa[i] >= j) y[p++] = sa[i] - j; 13 | for (i = 0; i < n; i++) wv[i] = x[y[i]]; 14 | for (i = 0; i < m; i++) ws[i] = 0; 15 | for (i = 0; i < n; i++) ws[wv[i]]++; 16 | for (i = 1; i < m; i++) ws[i] += ws[i - 1]; 17 | for (i = n - 1; i >= 0; i--) sa[--ws[wv[i]]] = y[i]; 18 | for (t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n; i++) 19 | x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++; 20 | }}} 21 | namespace CalcHeight { 22 | int rank[MAXN], height[MAXN]; //if you add '$', remove 23 | void calheight(int *r, int *sa, int n) { //it before call this function 24 | int i, j, k = 0; for (i = 1; i <= n; i++) rank[sa[i]] = i; 25 | for (i = 0; i < n; height[rank[i++]] = k) 26 | for (k ? k-- : 0, j = sa[rank[i] - 1]; r[i + k] == r[j + k]; k++); 27 | }} 28 | -------------------------------------------------------------------------------- /src/String Related/Suffix Automaton.cpp: -------------------------------------------------------------------------------- 1 | struct node { int len; node *fa, *go[26]; } base[MAXNODE], *top = base, *root, *que[MAXNODE]; 2 | typedef node *tree; 3 | inline tree newNode(int len) { 4 | top->len = len; top->fa = NULL; memset(top->go, 0, sizeof(top->go)); return top++; 5 | } inline tree newNode(int len, tree fa, tree *go) { 6 | top->len = len; top->fa = fa; memcpy(top->go, go, sizeof(top->go)); return top++; 7 | } void construct(char *A, int N) { 8 | tree p = root = newNode(0), q, up, fa; 9 | for (int i = 0; i < N; ++i) { 10 | int w = A[i] - 'a'; up = p; p = newNode(i + 1); 11 | for ( ; up && !up->go[w]; up = up->fa) up->go[w] = p; 12 | if (!up) p->fa = root; 13 | else { q = up->go[w]; 14 | if (up->len + 1 == q->len) p->fa = q; 15 | else { fa = newNode(up->len + 1, q->fa, q->go); 16 | for (p->fa = q->fa = fa; up && up->go[w] == q; up = up->fa) up->go[w] = fa; 17 | } 18 | } 19 | } static int cnt[MAXLEN]; memset(cnt, 0, sizeof(int) * (N + 1)); 20 | for (tree i(base); i != top; ++i) ++cnt[i->len]; 21 | Rep(i, 1, N) cnt[i] += cnt[i - 1]; 22 | for (tree i(base); i != top; ++i) Q[ cnt[i->len]-- ] = i; 23 | } -------------------------------------------------------------------------------- /src/Templates/cpp_template.cpp: -------------------------------------------------------------------------------- 1 | #pragma comment(linker, "/STACK:10240000") 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define Rep(i, a, b) for(int i = (a); i <= (b); ++i) 8 | #define Foru(i, a, b) for(int i = (a); i < (b); ++i) 9 | using namespace std; 10 | typedef long long LL; 11 | typedef pair pii; 12 | namespace BufferedReader { 13 | char buff[MAX_BUFFER + 5], *ptr = buff, c; bool flag; 14 | bool nextChar(char &c) { 15 | if ( (c = *ptr++) == 0 ) { 16 | int tmp = fread(buff, 1, MAX_BUFFER, stdin); 17 | buff[tmp] = 0; if (tmp == 0) return false; 18 | ptr = buff; c = *ptr++; 19 | } return true; 20 | } 21 | bool nextUnsignedInt(unsigned int &x) { 22 | for (;;){if (!nextChar(c)) return false; if ('0'<=c && c<='9') break;} 23 | for (x=c-'0'; nextChar(c); x = x * 10 + c - '0') if (c < '0' || c > '9') break; 24 | return true; 25 | } 26 | bool nextInt(int &x) { 27 | for (;;) { if (!nextChar(c)) return false; if (c=='-' || ('0'<=c && c<='9')) break; } 28 | for ((c=='-') ? (x=0,flag=true) : (x=c-'0',flag=false); nextChar(c); x=x*10+c-'0') 29 | if (c<'0' || c>'9') break; 30 | if (flag) x=-x; return true; 31 | } 32 | }; 33 | #endif 34 | -------------------------------------------------------------------------------- /src/Templates/java_template - Full.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.*; 3 | import java.math.*; 4 | 5 | class Node implements Comparable { 6 | int key; 7 | public int compareTo(Node o) { 8 | if (key != o.key) return key < o.key ? -1 : 1; 9 | return 0; 10 | } 11 | public boolean equals(Object o) { return false; } 12 | public String toString() { return ""; } 13 | public int hashCode() { return key; } 14 | } 15 | 16 | class MyComparator implements Comparator { 17 | public int compare(Node a, Node b) { 18 | if (a.key != b.key) 19 | return a.key < b.key ? -1 : 1; 20 | return 0; 21 | } 22 | } 23 | 24 | public class Main { 25 | 26 | public void solve() { 27 | PriorityQueue Q = new PriorityQueue(); 28 | Q.offer(1); Q.poll(); Q.peek(); Q.size(); 29 | 30 | HashMap dict = new HashMap(); 31 | dict.entrySet(); dict.put(new Node(), 0); dict.containsKey(new Node()); 32 | //Map.Entry e = (Map.Entry)it.next(); e.getValue(); e.getKey(); 33 | 34 | HashSet h = new HashSet(); 35 | h.contains(new Node()); h.add(new Node()); h.remove(new Node()); 36 | 37 | Random rand = new Random(); 38 | rand.nextInt(); rand.nextDouble(); 39 | 40 | int temp = 0; 41 | BigInteger a = BigInteger.ZERO, b = new BigInteger("1"), c = BigInteger.valueOf(2); 42 | a.remainder(b); a.modPow(b, c); a.pow(temp); a.intValue(); 43 | a.isProbablePrime(temp); // 1 - 1 / 2 ^ certainty 44 | a.nextProbablePrime(); 45 | 46 | Arrays.asList(array); 47 | Arrays.sort(array, fromIndex, toIndex, comparator); 48 | Arrays.fill(array, fromIndex, toIndex, value); 49 | Arrays.binarySearch(array, key, comparator); // found ? index : -(insertPoint) - 1 50 | Arrays.equals(array, array2); 51 | Collection.toArray(arrayType[]); 52 | 53 | Collections.copy(dest, src); 54 | Collections.fill(collection, value); 55 | Collections.max(collection, comparator); 56 | Collections.replaceAll(list, oldValue, newValue); 57 | Collections.reverse(list); 58 | Collections.reverseOrder(); 59 | Collections.rotate(list, distance); // ---------> 60 | Collections.shuffle(list); // random_shuffle 61 | 62 | } 63 | 64 | public void run() { 65 | tokenizer = null; 66 | reader = new BufferedReader(new InputStreamReader(System.in)); 67 | out = new PrintWriter(System.out); 68 | 69 | solve(); 70 | 71 | out.close(); 72 | } 73 | 74 | public static void main(String[] args) { 75 | new Main().run(); 76 | } 77 | 78 | public StringTokenizer tokenizer; 79 | public BufferedReader reader; 80 | public PrintWriter out; 81 | 82 | public String next() { 83 | while (tokenizer == null || !tokenizer.hasMoreTokens()) { 84 | try { 85 | tokenizer = new StringTokenizer(reader.readLine()); 86 | } 87 | catch (IOException e) { 88 | throw new RuntimeException(e); 89 | } 90 | } 91 | return tokenizer.nextToken(); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/Templates/java_template.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.*; 3 | import java.math.*; 4 | 5 | public class Main { 6 | public void solve() {} 7 | public void run() { 8 | tokenizer = null; out = new PrintWriter(System.out); 9 | in = new BufferedReader(new InputStreamReader(System.in)); 10 | solve(); 11 | out.close(); 12 | } 13 | public static void main(String[] args) { 14 | new Main().run(); 15 | } 16 | public StringTokenizer tokenizer; 17 | public BufferedReader in; 18 | public PrintWriter out; 19 | public String next() { 20 | while (tokenizer == null || !tokenizer.hasMoreTokens()) { 21 | try { tokenizer = new StringTokenizer(in.readLine()); } 22 | catch (IOException e) { throw new RuntimeException(e); } 23 | } return tokenizer.nextToken(); 24 | } 25 | } -------------------------------------------------------------------------------- /src/Templates/pai.sh: -------------------------------------------------------------------------------- 1 | make gen 2 | make B_pai 3 | make B_re 4 | $i 5 | while [ true ] 6 | do 7 | echo $((i=i+1)) 8 | ./gen > B.in 9 | ./B_pai < B.in > B_pai.out 10 | ./B_re < B.in > B_re.out 11 | if ! diff B_pai.out B_re.out 12 | then 13 | echo Wrong 14 | break 15 | fi 16 | done 17 | -------------------------------------------------------------------------------- /src/Templates/vimrc.cpp: -------------------------------------------------------------------------------- 1 | set nu ru nobk cindent si 2 | set mouse=a sw=4 sts=4 ts=4 3 | set hlsearch incsearch 4 | set whichwrap=b,s,<,>,[,] 5 | syntax on 6 | 7 | nmap ggVG 8 | vmap "+y 9 | 10 | autocmd BufNewFile *.cpp 0r ~/Templates/cpp.cpp 11 | map :!g++ % -o %< -Wall -Wconversion -Wextra -g3 12 | map :!./%< 13 | map :!./%< < %<.in 14 | 15 | map :vnew %<.in 16 | map :!(gedit % &) 17 | --------------------------------------------------------------------------------