├── .gitignore └── src ├── Algebra ├── Complex.java ├── FastFourierTransform.java ├── GeneralFFT.java └── Karatsuba.java ├── Geometry ├── Circle.java ├── ClosestPair.java ├── ConvexHull.java ├── Line.java ├── Point.java ├── Segment.java └── Utils.java ├── Graph ├── Algorithms │ ├── LowestCommonAncestor.java │ ├── MaximumMatching.java │ ├── NetworkFlow │ │ ├── Dinic.java │ │ ├── FordFulkerson.java │ │ └── MinCostMaxFlow.java │ ├── ShortestPath │ │ ├── BellmanFord.java │ │ ├── Dijkstra.java │ │ └── FloydWarshall.java │ ├── SpanningTree.java │ ├── StronglyConnectedComponents.java │ ├── TopologicalSort.java │ └── TwoSat.java ├── Pair.java ├── Representation │ ├── AdjacencyMatrix.java │ ├── EdgeList.java │ ├── Graph.java │ └── LinkedList.java └── Triplet.java ├── LinearProgramming ├── LPSolver.java └── LinearProgramming.java ├── Matrix ├── Determinant.java ├── MatrixInverse.java ├── MatrixOperations.java └── RowReduce.java ├── Misc ├── FastIO.java └── InputReader.java ├── NumberTheory ├── DiscreteLog.java ├── PollardRho.java ├── PrimeSieve.java ├── SafeArithmetic.java ├── TotientSieve.java └── Utils.java ├── String ├── AhoCorasick.java ├── BWT.java ├── KnuthMorrisPratt.java ├── SuffixArray.java ├── SuffixTree.java └── ZAlgorithm.java ├── Trees ├── BinaryIndexedTrees.java ├── HeavyLightTree.java ├── KDTree.java ├── LazyIntervalTree.java ├── LazySegmentTree.java ├── LinkCutTree.java ├── QriorityPueue.java ├── RangeTree.java ├── SplayTree.java ├── SplayTree2.java └── Tree234.java └── out.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Package Files # 4 | *.jar 5 | *.war 6 | *.ear 7 | 8 | # Eclipse 9 | .classpath 10 | .project 11 | 12 | # swp 13 | .*.swp 14 | 15 | # except the jars (libraries) in lib 16 | !lib/*.jar 17 | 18 | # LaTeX Stuff 19 | *.aux 20 | *.log 21 | *.nav 22 | *.out 23 | *.snm 24 | *.synctex.gz 25 | *.toc 26 | *.vrb 27 | /bin 28 | -------------------------------------------------------------------------------- /src/Algebra/Complex.java: -------------------------------------------------------------------------------- 1 | package Algebra; 2 | 3 | public final class Complex { 4 | public static final Complex ZERO = new Complex(0, 0); 5 | public double real, imag; 6 | 7 | public Complex(double real, double imag) { 8 | this.real = real; 9 | this.imag = imag; 10 | } 11 | 12 | public Complex add(Complex other) { 13 | return new Complex(this.real + other.real, this.imag + other.imag); 14 | } 15 | 16 | public Complex negate(Complex other) { 17 | return new Complex(-this.real, -this.imag); 18 | } 19 | 20 | public Complex subtract(Complex other) { 21 | return new Complex(this.real - other.real, this.imag - other.imag); 22 | } 23 | 24 | public Complex inverse() { 25 | double div = len(); 26 | return new Complex(this.real / div, -this.imag / div); 27 | } 28 | 29 | public double len() { 30 | return real * real + imag * imag; 31 | } 32 | 33 | public Complex multiply(Complex other) { 34 | return new Complex(this.real * other.real - this.imag * other.imag, this.real * other.imag 35 | + other.real * this.imag); 36 | } 37 | 38 | public Complex multiply(double other) { 39 | return new Complex(this.real * other, this.imag * other); 40 | } 41 | 42 | public Complex divide(Complex other) { 43 | return this.multiply(other.inverse()); 44 | } 45 | 46 | public Complex conjugate() { 47 | return new Complex(this.real, -this.imag); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Algebra/FastFourierTransform.java: -------------------------------------------------------------------------------- 1 | package Algebra; 2 | 3 | public class FastFourierTransform { 4 | private Complex[] fft(Complex[] x) { 5 | int N = x.length; 6 | 7 | if (N == 1) 8 | return new Complex[] {x[0]}; 9 | Complex[] arr = new Complex[N >> 1]; 10 | for (int i = 0; i < N / 2; i++) 11 | arr[i] = x[2 * i]; 12 | Complex[] even = fft(arr); 13 | 14 | for (int i = 0; i < N / 2; i++) 15 | arr[i] = x[2 * i + 1]; 16 | Complex[] odd = fft(arr); 17 | 18 | Complex[] ret = new Complex[N]; 19 | for (int i = 0; i < N / 2; i++) { 20 | double ang = -2 * i * Math.PI / N; 21 | Complex ai = new Complex(Math.cos(ang), Math.sin(ang)).multiply(odd[i]); 22 | ret[i] = even[i].add(ai); 23 | ret[i + N / 2] = even[i].subtract(ai); 24 | } 25 | 26 | return ret; 27 | } 28 | 29 | public Complex[] ifft(Complex[] x) { 30 | int N = x.length; 31 | Complex[] ret = new Complex[N]; 32 | for (int i = 0; i < N; i++) 33 | ret[i] = x[i].conjugate(); 34 | ret = fft(ret); 35 | for (int i = 0; i < N; i++) 36 | ret[i] = ret[i].conjugate().multiply(1. / N); 37 | return ret; 38 | } 39 | 40 | // performs circular convolution 41 | public Complex[] circonv(Complex[] x, Complex[] y) { 42 | int N = x.length; 43 | Complex[] a = fft(x), b = fft(y); 44 | for (int i = 0; i < N; i++) 45 | a[i] = a[i].multiply(b[i]); 46 | return ifft(a); 47 | } 48 | 49 | // performs linear convolution of x,y 50 | public Complex[] conv(Complex[] x, Complex[] y) { 51 | int N = x.length; 52 | Complex[] a = new Complex[2 * N], b = new Complex[2 * N]; 53 | for (int i = 0; i < N; i++) { 54 | a[i] = x[i]; 55 | a[i + N] = Complex.ZERO; 56 | 57 | b[i] = y[i]; 58 | b[i + N] = Complex.ZERO; 59 | } 60 | return circonv(a, b); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Algebra/GeneralFFT.java: -------------------------------------------------------------------------------- 1 | package Algebra; 2 | 3 | public class GeneralFFT { 4 | // below FFT code very slightly modified from 5 | // http://nayuki.eigenstate.org/res/free-small-fft-in-multiple-languages/Fft.java 6 | /* 7 | * Computes the discrete Fourier transform (DFT) of the given complex vector, storing the result 8 | * back into the vector. The vector can have any length. This is a wrapper function. 9 | */ 10 | public static void transform(double[] real, double[] imag) { 11 | if (real.length != imag.length) 12 | throw new IllegalArgumentException("Mismatched lengths"); 13 | 14 | int n = real.length; 15 | if (n == 0) 16 | return; 17 | else if ((n & (n - 1)) == 0) // Is power of 2 18 | transformRadix2(real, imag); 19 | else 20 | // More complicated algorithm for aribtrary sizes 21 | transformBluestein(real, imag); 22 | } 23 | 24 | 25 | /* 26 | * Computes the inverse discrete Fourier transform (IDFT) of the given complex vector, storing the 27 | * result back into the vector. The vector can have any length. This is a wrapper function. This 28 | * transform does not perform scaling, so the inverse is not a true inverse. 29 | */ 30 | public static void inverseTransform(double[] real, double[] imag) { 31 | transform(imag, real); 32 | } 33 | 34 | /* 35 | * Computes the discrete Fourier transform (DFT) of the given complex vector, storing the result 36 | * back into the vector. The vector's length must be a power of 2. Uses the Cooley-Tukey 37 | * decimation-in-time radix-2 algorithm. 38 | */ 39 | public static void transformRadix2(double[] real, double[] imag) { 40 | // Initialization 41 | if (real.length != imag.length) 42 | throw new IllegalArgumentException("Mismatched lengths"); 43 | int n = real.length; 44 | if (n <= 1) 45 | return; 46 | int levels = -1; 47 | for (int i = 0; i < 32; i++) { 48 | if (1 << i == n) 49 | levels = i; // Equal to log2(n) 50 | } 51 | if (levels == -1) 52 | throw new IllegalArgumentException("Length is not a power of 2"); 53 | double[] cosTable = new double[n / 2]; 54 | double[] sinTable = new double[n / 2]; 55 | cosTable[0] = 1; 56 | sinTable[0] = 0; 57 | double qc = Math.cos(2 * Math.PI / n), qs = Math.sin(2 * Math.PI / n); 58 | for (int i = 1; i < n / 2; i++) { 59 | cosTable[i] = cosTable[i - 1] * qc - sinTable[i - 1] * qs; 60 | sinTable[i] = sinTable[i - 1] * qc + cosTable[i - 1] * qs; 61 | } 62 | 63 | // Bit-reversed addressing permutation 64 | for (int i = 0; i < n; i++) { 65 | int j = Integer.reverse(i) >>> (32 - levels); 66 | if (j > i) { 67 | double temp = real[i]; 68 | real[i] = real[j]; 69 | real[j] = temp; 70 | temp = imag[i]; 71 | imag[i] = imag[j]; 72 | imag[j] = temp; 73 | } 74 | } 75 | 76 | // Cooley-Tukey decimation-in-time radix-2 FFT 77 | for (int size = 2; size <= n; size *= 2) { 78 | int halfsize = size / 2; 79 | int tablestep = n / size; 80 | for (int i = 0; i < n; i += size) { 81 | for (int j = i, k = 0; j < i + halfsize; j++, k += tablestep) { 82 | double tpre = real[j + halfsize] * cosTable[k] + imag[j + halfsize] * sinTable[k]; 83 | double tpim = -real[j + halfsize] * sinTable[k] + imag[j + halfsize] * cosTable[k]; 84 | real[j + halfsize] = real[j] - tpre; 85 | imag[j + halfsize] = imag[j] - tpim; 86 | real[j] += tpre; 87 | imag[j] += tpim; 88 | } 89 | } 90 | } 91 | } 92 | 93 | 94 | /* 95 | * Computes the discrete Fourier transform (DFT) of the given complex vector, storing the result 96 | * back into the vector. The vector can have any length. This requires the convolution function, 97 | * which in turn requires the radix-2 FFT function. Uses Bluestein's chirp z-transform algorithm. 98 | */ 99 | public static void transformBluestein(double[] real, double[] imag) { 100 | // Find a power-of-2 convolution length m such that m >= n * 2 - 1 101 | int n = real.length; 102 | int m = 1; 103 | while (m < n * 2 - 1) 104 | m *= 2; 105 | 106 | // Trignometric tables 107 | double[] tc = new double[2 * n]; 108 | double[] ts = new double[2 * n]; 109 | tc[0] = 1; 110 | ts[0] = 0; 111 | double qc = Math.cos(Math.PI / n), qs = Math.sin(Math.PI / n); 112 | for (int i = 1; i < 2 * n; i++) { 113 | tc[i] = tc[i - 1] * qc - ts[i - 1] * qs; 114 | ts[i] = ts[i - 1] * qc + tc[i - 1] * qs; 115 | } 116 | double[] cosTable = new double[n]; 117 | double[] sinTable = new double[n]; 118 | for (int i = 0; i < n; i++) { 119 | int j = (int) ((long) i * i % (n * 2)); // This is more accurate than j = i * i 120 | cosTable[i] = tc[j]; 121 | sinTable[i] = ts[j]; 122 | } 123 | 124 | // Temporary vectors and preprocessing 125 | double[] areal = new double[m]; 126 | double[] aimag = new double[m]; 127 | for (int i = 0; i < n; i++) { 128 | areal[i] = real[i] * cosTable[i] + imag[i] * sinTable[i]; 129 | aimag[i] = -real[i] * sinTable[i] + imag[i] * cosTable[i]; 130 | } 131 | double[] breal = new double[m]; 132 | double[] bimag = new double[m]; 133 | breal[0] = cosTable[0]; 134 | bimag[0] = sinTable[0]; 135 | for (int i = 1; i < n; i++) { 136 | breal[i] = breal[m - i] = cosTable[i]; 137 | bimag[i] = bimag[m - i] = sinTable[i]; 138 | } 139 | 140 | // Convolution 141 | double[] creal = new double[m]; 142 | double[] cimag = new double[m]; 143 | convolve(areal, aimag, breal, bimag, creal, cimag); 144 | 145 | // Postprocessing 146 | for (int i = 0; i < n; i++) { 147 | real[i] = creal[i] * cosTable[i] + cimag[i] * sinTable[i]; 148 | imag[i] = -creal[i] * sinTable[i] + cimag[i] * cosTable[i]; 149 | } 150 | } 151 | 152 | /* 153 | * Computes the circular convolution of the given complex vectors. Each vector's length must be 154 | * the same. 155 | */ 156 | public static void convolve(double[] xreal, double[] ximag, double[] yreal, double[] yimag, 157 | double[] outreal, double[] outimag) { 158 | if (xreal.length != ximag.length || xreal.length != yreal.length 159 | || yreal.length != yimag.length || xreal.length != outreal.length 160 | || outreal.length != outimag.length) 161 | throw new IllegalArgumentException("Mismatched lengths"); 162 | 163 | int n = xreal.length; 164 | xreal = xreal.clone(); 165 | ximag = ximag.clone(); 166 | yreal = yreal.clone(); 167 | yimag = yimag.clone(); 168 | 169 | transform(xreal, ximag); 170 | transform(yreal, yimag); 171 | for (int i = 0; i < n; i++) { 172 | double temp = xreal[i] * yreal[i] - ximag[i] * yimag[i]; 173 | ximag[i] = ximag[i] * yreal[i] + xreal[i] * yimag[i]; 174 | xreal[i] = temp; 175 | } 176 | inverseTransform(xreal, ximag); 177 | for (int i = 0; i < n; i++) { // Scaling (because this FFT implementation omits it) 178 | outreal[i] = xreal[i] / n; 179 | outimag[i] = ximag[i] / n; 180 | } 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/Algebra/Karatsuba.java: -------------------------------------------------------------------------------- 1 | package Algebra; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Karatsuba { 6 | public static long mod; 7 | 8 | public static long[] multiply(long[] a, long[] b) { 9 | if (b.length <= 7) { 10 | long[] r = new long[a.length + b.length - 1]; 11 | for (int i = 0; i < r.length; i++) 12 | for (int j = Math.max(i - a.length + 1, 0); i - j >= 0 && j < b.length; j++) 13 | r[i] = (r[i] + a[i - j] * b[j]) % mod; 14 | return r; 15 | } 16 | if (a.length <= 7) { 17 | long[] r = new long[a.length + b.length - 1]; 18 | for (int i = 0; i < r.length; i++) 19 | for (int j = Math.max(i - b.length + 1, 0); i - j >= 0 && j < a.length; j++) 20 | r[i] = (r[i] + b[i - j] * a[j]) % mod; 21 | return r; 22 | } 23 | int K = a.length / 2; 24 | long[] a1 = Arrays.copyOfRange(a, 0, K); 25 | long[] a2 = Arrays.copyOfRange(a, K, a.length); 26 | long[] b1 = Arrays.copyOfRange(b, 0, K); 27 | long[] b2 = Arrays.copyOfRange(b, K, b.length); 28 | long[] c1 = multiply(a1, b1); 29 | long[] c2 = multiply(a2, b2); 30 | long[] c3 = sub(sub(multiply(add(a1, a2), add(b1, b2)), c1), c2); 31 | long[] ret = new long[a.length + b.length - 1]; 32 | System.arraycopy(c1, 0, ret, 0, c1.length); 33 | for (int i = 2 * K; i < 2 * K + c2.length; i++) { 34 | ret[i] = (ret[i] + c2[i - 2 * K]) % mod; 35 | } 36 | for (int i = K; i < K + c3.length; i++) { 37 | ret[i] = (ret[i] + c3[i - K]) % mod; 38 | } 39 | return ret; 40 | } 41 | 42 | public static long[] sub(long[] a, long[] b) { 43 | long[] r = new long[Math.max(a.length, b.length)]; 44 | System.arraycopy(a, 0, r, 0, a.length); 45 | for (int i = 0; i < b.length; i++) 46 | r[i] = (r[i] + mod - b[i]) % mod; 47 | return r; 48 | } 49 | 50 | public static long[] add(long[] a, long[] b) { 51 | long[] r = new long[Math.max(a.length, b.length)]; 52 | System.arraycopy(b, 0, r, 0, b.length); 53 | for (int i = 0; i < a.length; i++) 54 | r[i] = (r[i] + a[i]) % mod; 55 | return r; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Geometry/Circle.java: -------------------------------------------------------------------------------- 1 | package Geometry; 2 | 3 | 4 | /** 5 | * Representation of a circle 6 | * 7 | * @author Lewin 8 | * 9 | */ 10 | import static Geometry.Utils.*; 11 | 12 | public class Circle { 13 | // circle centered at p with radius r 14 | public Point p; 15 | public double r; 16 | 17 | public Circle(double x, double y, double r) { 18 | p = new Point(x, y); 19 | this.r = r; 20 | } 21 | 22 | // finds unique circle from 3 points 23 | public Circle(Point a, Point b, Point c) { 24 | double da1 = 2 * (c.x - a.x); 25 | double da2 = 2 * (c.x - b.x); 26 | double db1 = 2 * (c.y - a.y); 27 | double db2 = 2 * (c.y - b.y); 28 | double dc1 = c.x * c.x - a.x * a.x + c.y * c.y - a.y * a.y; 29 | double dc2 = c.x * c.x - b.x * b.x + c.y * c.y - b.y * b.y; 30 | 31 | double x = 0, y = 0; 32 | if (Math.abs(da1) <= EPS) { 33 | y = dc1 / db1; 34 | x = (dc2 - db2 * y) / da2; 35 | } else { 36 | db2 -= db1 * da2 / da1; 37 | dc2 -= dc1 * da2 / da1; 38 | y = dc2 / db2; 39 | x = (dc1 - db1 * y) / da1; 40 | } 41 | p = new Point(x, y); 42 | r = distance(p, a); 43 | } 44 | 45 | public boolean contains(Point other) { 46 | return distance(other, p) < r; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Geometry/ClosestPair.java: -------------------------------------------------------------------------------- 1 | package Geometry; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | import java.util.TreeSet; 6 | 7 | /** 8 | * O (n log n) for finding pair of closest points within a set 9 | * 10 | * @author Lewin 11 | * 12 | */ 13 | public class ClosestPair { 14 | private static State closestPair(Point[] points) { 15 | Arrays.sort(points); 16 | double min = 1e9; 17 | int p1 = -1, p2 = -1; 18 | int left = 0; 19 | 20 | TreeSet curset = new TreeSet(new Comparator() { 21 | public int compare(Point a, Point b) { 22 | return (int) (Math.signum(a.y == b.y ? a.x - b.x : a.y - b.y)); 23 | } 24 | }); 25 | 26 | for (Point p : points) { 27 | while (p.x - points[left].x > min) 28 | curset.remove(points[left++]); 29 | for (Point next : curset.subSet(new Point(p.x, (int) (p.y - min), 0), new Point(p.x, 30 | (int) (p.y + min), 0))) { 31 | double temp = dist(p, next); 32 | if (temp < min) { 33 | min = temp; 34 | p1 = p.idx; 35 | p2 = next.idx; 36 | } 37 | } 38 | curset.add(p); 39 | } 40 | 41 | return new State(p1, p2, min); 42 | } 43 | 44 | private static double dist(Point p1, Point p2) { 45 | return Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)); 46 | } 47 | 48 | static class State { 49 | public int p1, p2; 50 | public double dist; 51 | 52 | public State(int p1, int p2, double dist) { 53 | if (p2 < p1) { 54 | p2 ^= p1; 55 | p1 ^= p2; 56 | p2 ^= p1; 57 | } 58 | this.p1 = p1; 59 | this.p2 = p2; 60 | this.dist = dist; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Geometry/ConvexHull.java: -------------------------------------------------------------------------------- 1 | package Geometry; 2 | 3 | import java.util.Arrays; 4 | 5 | public class ConvexHull { 6 | public static Point[] convexHull(Point[] p) { 7 | int n = p.length; 8 | if (n <= 1) return p; 9 | Arrays.sort(p, (a, b) -> Integer.compare(a.x, b.x) != 0 ? Integer.compare(a.x, b.x) : Integer.compare(a.y, b.y)); 10 | Point[] q = new Point[n * 2]; 11 | int cnt = 0; 12 | for (int i = 0; i < n; q[cnt++] = p[i++]) 13 | for (; cnt > 1 && cross(q[cnt - 2], q[cnt - 1], p[i]) >= 0; --cnt); 14 | for (int i = n - 2, t = cnt; i >= 0; q[cnt++] = p[i--]) 15 | for (; cnt > t && cross(q[cnt - 2], q[cnt - 1], p[i]) >= 0; --cnt); 16 | return Arrays.copyOf(q, cnt - 1 - (q[0].x == q[1].x && q[0].y == q[1].y ? 1 : 0)); 17 | } 18 | 19 | public static class Point { 20 | final int x, y; 21 | 22 | public Point(int x, int y) { 23 | this.x = x; 24 | this.y = y; 25 | } 26 | } 27 | 28 | static long cross(Point a, Point b, Point c) { 29 | return (long) (b.x - a.x) * (c.y - a.y) - (long) (b.y - a.y) * (c.x - a.x); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Geometry/Line.java: -------------------------------------------------------------------------------- 1 | package Geometry; 2 | 3 | import static Geometry.Utils.*; 4 | 5 | /** 6 | * Representation of a Line 7 | * 8 | * @author Lewin 9 | * 10 | */ 11 | public class Line { 12 | public double a, b, c; 13 | 14 | // ax + by = c 15 | 16 | /** 17 | * Standard representation 18 | */ 19 | public Line(double a, double b, double c) { 20 | this.a = a; 21 | this.b = b; 22 | this.c = c; 23 | } 24 | 25 | /** 26 | * Unique line between two points 27 | */ 28 | public Line(Point p1, Point p2) { // two points 29 | if (p1.x == p2.x) { 30 | a = 1; 31 | b = 0; 32 | c = -p1.x; 33 | } else { 34 | b = 1; 35 | a = -(p1.y - p2.y) / (p1.x - p2.x); 36 | c = -(a * p1.x) - (b * p1.y); 37 | } 38 | } 39 | 40 | /** 41 | * Point-slope formula 42 | */ 43 | public Line(Point p, double m) { 44 | a = -m; 45 | b = 1; 46 | c = -((a * p.x) + (b * p.y)); 47 | } 48 | 49 | // returns true if line l is parallel to this 50 | public boolean parallel(Line l) { 51 | return (Math.abs(a - l.a) <= EPS && Math.abs(b - l.b) <= EPS); 52 | } 53 | 54 | // tests if two lines describe the same object 55 | public boolean same_line(Line l) { 56 | return (parallel(l) && Math.abs(c - l.c) <= EPS); 57 | } 58 | 59 | // finds intersection point between lines 60 | // if no intersection found, returns null; 61 | // if same line, returns INF, INF point 62 | public Point intersection_point(Line l) { 63 | Point p = new Point(INF, INF); 64 | if (same_line(l)) 65 | return p; 66 | if (parallel(l)) 67 | return null; 68 | 69 | p.x = (l.b * c - b * l.c) / (l.a * b - a * l.b); 70 | if (Math.abs(b) > EPS) 71 | p.y = -(a * p.x + c) / b; 72 | else 73 | p.y = -(l.a * p.x + l.c) / l.b; 74 | return p; 75 | } 76 | 77 | // Finds the point closest to p lying on this line 78 | public Point closest_Point(Point p) { 79 | Point p_c = new Point(INF, INF); 80 | if (Math.abs(b) <= EPS) { 81 | p_c.x = -c; 82 | p_c.y = p.y; 83 | return p_c; 84 | } 85 | if (Math.abs(a) <= EPS) { 86 | p_c.x = p.x; 87 | p_c.y = -c; 88 | return p_c; 89 | } 90 | Line perp = new Line(p, 1 / a); 91 | return intersection_point(perp); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/Geometry/Point.java: -------------------------------------------------------------------------------- 1 | package Geometry; 2 | 3 | import java.util.*; 4 | import static Geometry.Utils.*; 5 | 6 | /** 7 | * Representation of a Point 8 | * 9 | * @author Lewin 10 | * 11 | */ 12 | public class Point implements Comparable { 13 | public double x, y, angle; 14 | public int idx; 15 | 16 | public Point(double x, double y) { 17 | this.x = x; 18 | this.y = y; 19 | angle = 0; 20 | } 21 | 22 | public Point(double x, double y, int idx) { 23 | this.x = x; 24 | this.y = y; 25 | this.idx = idx; 26 | } 27 | 28 | public int compareTo(Point other) { 29 | return x == other.x ? (int) Math.signum(y - other.y) : (int) Math.signum(x - other.x); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Geometry/Segment.java: -------------------------------------------------------------------------------- 1 | package Geometry; 2 | 3 | import static Geometry.Utils.*; 4 | 5 | /** 6 | * Representation of a Segment 7 | * 8 | * @author Lewin 9 | * 10 | */ 11 | public class Segment { 12 | public Point a, b; 13 | public double length; 14 | 15 | public Segment(Point a, Point b) { 16 | this.a = a; 17 | this.b = b; 18 | length = distance(a, b); 19 | } 20 | 21 | /** 22 | * Returns shortest point distance 23 | * 24 | * @param c point we are considering 25 | * @return shortest length from c to this segment 26 | */ 27 | public double ptDist(Point c) { 28 | if (dot(a, b, c) > 0) 29 | return distance(b, c); 30 | if (dot(b, a, c) > 0) 31 | return distance(a, c); 32 | if (length == 0) 33 | return distance(a, c); 34 | return Math.abs(cross(a, b, c) / length); 35 | } 36 | 37 | /** 38 | * Returns a point that segment intersects with s 39 | * 40 | * @param s the segment that we are testing for intersection 41 | * @return A wrapper containting a boolean and a point if boolean is true and point is null this 42 | * and s have infinitely many intersections if boolean is true and point is not null this 43 | * and s intersect exactly once at point if boolean is false (implies point is null) this 44 | * and s do not intersect 45 | */ 46 | public Wrapper segments_intersect(Segment s) { 47 | Line l1 = new Line(a, b), l2 = new Line(s.a, s.b); 48 | Point p = new Point(0, 0); 49 | 50 | if (l1.same_line(l2)) 51 | return new Wrapper((point_in_box(a, s.a, s.b) || point_in_box(b, s.a, s.b) 52 | || point_in_box(s.a, a, b) || point_in_box(s.b, a, b)), null); 53 | 54 | if (l1.parallel(l2)) 55 | return new Wrapper(false, null); 56 | 57 | p = l1.intersection_point(l2); 58 | 59 | return new Wrapper((point_in_box(p, a, b) && point_in_box(p, s.a, s.b)), p); 60 | } 61 | 62 | static class Wrapper { 63 | public boolean state; 64 | public Point p; 65 | 66 | public Wrapper(boolean _state, Point _p) { 67 | state = _state; 68 | p = _p; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Geometry/Utils.java: -------------------------------------------------------------------------------- 1 | package Geometry; 2 | 3 | /** 4 | * Useful functions 5 | * 6 | * @author Lewin 7 | * 8 | */ 9 | public class Utils { 10 | public static final double EPS = 1e-9; 11 | public static final int INF = Integer.MAX_VALUE >> 2; 12 | 13 | // returns dot product of |a-b|*|b-c| 14 | public static double dot(Point a, Point b, Point c) { 15 | Point ab = new Point(b.x - a.x, b.y - a.y); 16 | Point bc = new Point(c.x - b.x, c.y - b.y); 17 | return ab.x * bc.x + ab.y * bc.y; 18 | } 19 | 20 | // return cross product of |b-a|x|c-a| 21 | public static double cross(Point a, Point b, Point c) { 22 | Point ab = new Point(b.x - a.x, b.y - a.y); 23 | Point ac = new Point(c.x - a.x, c.y - a.y); 24 | return ab.x * ac.y - ab.y * ac.x; 25 | } 26 | 27 | // returns if a,b,c are colinear 28 | public static boolean colinear(Point a, Point b, Point c) { 29 | return (a.x - b.x) * (a.y - c.y) == (a.x - c.x) * (a.y - b.y); 30 | } 31 | 32 | // returns distance between points a, and b 33 | public static double distance(Point a, Point b) { 34 | return Math.hypot(a.x - b.x, a.y - b.y); 35 | } 36 | 37 | // returns true iff p lies in box with opposite corners b1, b2 38 | public static boolean point_in_box(Point p, Point b1, Point b2) { 39 | return ((p.x >= Math.min(b1.x, b2.x)) && (p.x <= Math.max(b1.x, b2.x)) 40 | && (p.y >= Math.min(b1.y, b2.y)) && (p.y <= Math.max(b1.y, b2.y))); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Graph/Algorithms/LowestCommonAncestor.java: -------------------------------------------------------------------------------- 1 | package Graph.Algorithms; 2 | 3 | import java.util.Arrays; 4 | 5 | public class LowestCommonAncestor { 6 | public static int[] eadj, eprev, elast, ecost; 7 | public static int eidx; 8 | public static int N; 9 | private static int root; 10 | private static int[] depth, queue; 11 | private static int[][] anc; 12 | 13 | private static void init() { 14 | Arrays.fill(depth, 1 << 29); // INF 15 | 16 | int front = 0, back = 0; 17 | depth[root] = 0; 18 | queue[back++] = root; 19 | anc[0][root] = -1; 20 | 21 | while (front != back) { 22 | int node = queue[front++]; 23 | for (int e = elast[node]; e != -1; e = eprev[e]) 24 | if (depth[node] + ecost[e] < depth[eadj[e]]) { 25 | depth[eadj[e]] = depth[node] + ecost[e]; 26 | anc[0][eadj[e]] = node; 27 | queue[back++] = eadj[e]; 28 | }// depth [i] is distance from root to i 29 | // anc [0][i] is the first ancestor of i 30 | } 31 | 32 | for (int k = 1; 1 << k < N; k++) 33 | for (int i = 0; i < N; i++) 34 | anc[k][i] = anc[k - 1][i] == -1 ? -1 : anc[k - 1][anc[k - 1][i]]; 35 | } 36 | 37 | private static int lca(int a, int b) { 38 | if (depth[a] < depth[b]) { 39 | a ^= b; 40 | b ^= a; 41 | a ^= b; 42 | } 43 | 44 | // make depth [a] = depth [b] with binary search 45 | int diff = depth[a] - depth[b]; 46 | for (int i = 0; 1 << i <= diff; i++) 47 | if (((diff) & 1 << i) != 0) 48 | a = anc[i][a]; 49 | 50 | if (a == b) 51 | return a; 52 | 53 | int log = 0; 54 | while (1 << (log + 1) <= depth[a]) 55 | log++; 56 | 57 | // another binary search 58 | for (int i = log; i >= 0; i--) 59 | if (anc[i][a] != anc[i][b]) { 60 | a = anc[i][a]; 61 | b = anc[i][b]; 62 | } 63 | 64 | return anc[0][a]; 65 | } 66 | 67 | private static int dist(int a, int b) { 68 | return depth[a] + depth[b] - 2 * depth[lca(a, b)]; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Graph/Algorithms/MaximumMatching.java: -------------------------------------------------------------------------------- 1 | package Graph.Algorithms; 2 | 3 | import java.util.Arrays; 4 | 5 | public class MaximumMatching { 6 | private static int N; 7 | private static boolean[][] grid; 8 | 9 | private static void addEdge(int a, int b) { 10 | grid[a][b] = grid[b][a] = true; 11 | } 12 | 13 | private static int[] match, queue, pre, base; 14 | private static boolean[] hash, blossom; 15 | 16 | private static int maximum_matching() { 17 | pre = new int[N]; 18 | base = new int[N]; 19 | queue = new int[N]; 20 | hash = new boolean[N]; 21 | blossom = new boolean[N]; 22 | match = new int[N]; 23 | Arrays.fill(match, -1); 24 | int ans = 0; 25 | for (int i = 0; i < N; i++) 26 | if (match[i] == -1) 27 | ans += bfs(i); 28 | return ans; 29 | } 30 | 31 | private static int bfs(int p) { 32 | Arrays.fill(pre, -1); 33 | Arrays.fill(hash, false); 34 | for (int i = 0; i < N; i++) 35 | base[i] = i; 36 | int front = 0, back = 0; 37 | queue[back++] = p; 38 | while (front < back) { 39 | int u = queue[front++]; 40 | for (int v = 0; v < N; v++) { 41 | if (grid[u][v] && base[u] != base[v] && v != match[u]) { 42 | if (v == p || (match[v] != -1 && pre[match[v]] != -1)) { 43 | int b = contract(u, v); 44 | for (int i = 0; i < N; i++) { 45 | if (blossom[base[i]]) { 46 | base[i] = b; 47 | if (!hash[i]) { 48 | hash[i] = true; 49 | queue[back++] = i; 50 | } 51 | } 52 | } 53 | } else if (pre[v] == -1) { 54 | pre[v] = u; 55 | if (match[v] == -1) { 56 | augment(v); 57 | return 1; 58 | } else { 59 | queue[back++] = match[v]; 60 | hash[match[v]] = true; 61 | } 62 | } 63 | } 64 | } 65 | } 66 | return 0; 67 | } 68 | 69 | private static void augment(int u) { 70 | while (u != -1) { 71 | int v = pre[u], k = match[v]; 72 | match[u] = v; 73 | match[v] = u; 74 | u = k; 75 | } 76 | } 77 | 78 | private static int contract(int u, int v) { 79 | Arrays.fill(blossom, false); 80 | int b = find_base(base[u], base[v]); 81 | change_blossom(b, u); 82 | change_blossom(b, v); 83 | if (base[u] != b) 84 | pre[u] = v; 85 | if (base[v] != b) 86 | pre[v] = u; 87 | return b; 88 | } 89 | 90 | private static void change_blossom(int b, int u) { 91 | while (base[u] != b) { 92 | int v = match[u]; 93 | blossom[base[v]] = blossom[base[u]] = true; 94 | u = pre[v]; 95 | if (base[u] != b) 96 | pre[u] = v; 97 | } 98 | } 99 | 100 | private static int find_base(int u, int v) { 101 | boolean[] in_path = new boolean[N]; 102 | while (true) { 103 | in_path[u] = true; 104 | if (match[u] == -1) 105 | break; 106 | u = base[pre[match[u]]]; 107 | } 108 | while (!in_path[v]) 109 | v = base[pre[match[v]]]; 110 | return v; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/Graph/Algorithms/NetworkFlow/Dinic.java: -------------------------------------------------------------------------------- 1 | package Graph.Algorithms.NetworkFlow; 2 | 3 | import java.util.Arrays; 4 | 5 | public class Dinic { 6 | public static int N; 7 | public static int INF = 1 << 29; 8 | public static int[] eadj, eprev, elast; 9 | public static int eidx; 10 | private static int[] flow, capa, now; 11 | 12 | public static void init(int _N, int M) { 13 | N = _N; 14 | eadj = new int[M]; 15 | eprev = new int[M]; 16 | elast = new int[N]; 17 | flow = new int[M]; 18 | capa = new int[M]; 19 | now = new int[N]; 20 | level = new int[N]; 21 | eidx = 0; 22 | Arrays.fill(elast, -1); 23 | } 24 | 25 | private static void add_edge(int a, int b, int c) { 26 | eadj[eidx] = b; flow[eidx] = 0; capa[eidx] = c; eprev[eidx] = elast[a]; elast[a] = eidx++; 27 | eadj[eidx] = a; flow[eidx] = c; capa[eidx] = c; eprev[eidx] = elast[b]; elast[b] = eidx++; 28 | } 29 | 30 | private static int dinic(int source, int sink) { 31 | int res, flow = 0; 32 | while (bfs(source, sink)) { // see if there is an augmenting path 33 | System.arraycopy(elast, 0, now, 0, N); 34 | while ((res = dfs(source, INF, sink)) > 0) 35 | // push all possible flow through 36 | flow += res; 37 | } 38 | return flow; 39 | } 40 | 41 | private static int[] level; 42 | 43 | private static boolean bfs(int source, int sink) { 44 | Arrays.fill(level, -1); 45 | int front = 0, back = 0; 46 | int[] queue = new int[N]; 47 | level[source] = 0; 48 | queue[back++] = source; 49 | while (front < back && level[sink] == -1) { 50 | int node = queue[front++]; 51 | for (int e = elast[node]; e != -1; e = eprev[e]) { 52 | int to = eadj[e]; 53 | if (level[to] == -1 && flow[e] < capa[e]) { 54 | level[to] = level[node] + 1; 55 | queue[back++] = to; 56 | } 57 | } 58 | } 59 | 60 | return level[sink] != -1; 61 | } 62 | 63 | private static int dfs(int cur, int curflow, int goal) { 64 | if (cur == goal) 65 | return curflow; 66 | 67 | for (int e = now[cur]; e != -1; now[cur] = e = eprev[e]) { 68 | if (level[eadj[e]] > level[cur] && flow[e] < capa[e]) { 69 | int res = dfs(eadj[e], Math.min(curflow, capa[e] - flow[e]), goal); 70 | if (res > 0) { 71 | flow[e] += res; 72 | flow[e ^ 1] -= res; 73 | return res; 74 | } 75 | } 76 | } 77 | return 0; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Graph/Algorithms/NetworkFlow/FordFulkerson.java: -------------------------------------------------------------------------------- 1 | package Graph.Algorithms.NetworkFlow; 2 | 3 | import static Graph.Representation.AdjacencyMatrix.*; 4 | 5 | public class FordFulkerson { 6 | private static int networkFlow(int source, int sink) { 7 | if (source == sink) 8 | return INF; 9 | 10 | int totalFlow = 0; 11 | int[][] cap = new int[N][N]; // don't want to alter original array 12 | for (int i = 0; i < N; i++) 13 | // if you do want to alter it, change input from grid to cap 14 | System.arraycopy(grid[i], 0, cap[i], 0, N); // get rid of these three 15 | // lines 16 | 17 | while (true) { // while there exists an augmenting path 18 | int[] prev = new int[N], flow = new int[N]; 19 | boolean[] visited = new boolean[N]; 20 | int[] queue = new int[N]; 21 | int front = 0, back = 0; 22 | 23 | queue[back++] = source; 24 | visited[source] = true; 25 | flow[source] = INF; 26 | boolean success = false; 27 | 28 | // find the path 29 | outer: while (front != back) { 30 | int node = queue[front++]; 31 | 32 | for (int i = 0; i < N; i++) 33 | if (!visited[i] && cap[node][i] > 0) { 34 | prev[i] = node; 35 | flow[i] = Math.min(flow[node], cap[node][i]); 36 | visited[i] = true; 37 | 38 | if (i == sink) { 39 | success = true; 40 | break outer; 41 | } 42 | 43 | queue[back++] = i; 44 | } 45 | } 46 | if (!success) 47 | break; 48 | 49 | // push flow through 50 | int pathCap = flow[sink]; 51 | totalFlow += pathCap; 52 | 53 | for (int x = sink; x != source; x = prev[x]) { 54 | cap[prev[x]][x] -= pathCap; 55 | cap[x][prev[x]] += pathCap; 56 | } 57 | } 58 | 59 | return totalFlow; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Graph/Algorithms/NetworkFlow/MinCostMaxFlow.java: -------------------------------------------------------------------------------- 1 | package Graph.Algorithms.NetworkFlow; 2 | 3 | import java.util.Arrays; 4 | 5 | public class MinCostMaxFlow { 6 | public static int N; 7 | public static int INF = 1 << 29; 8 | private static int[][] cap, cost; 9 | private static int[] pot; 10 | 11 | // add an edge from x to y with capacity w and cost c 12 | private static void addEdge(int x, int y, int w, int c) { 13 | cap[x][y] = w; 14 | cost[x][y] = c; 15 | cost[y][x] = -c; 16 | } 17 | 18 | // if we want max cost, take replace c with Q - c, (Q > all c) 19 | // then take Q * flow [0] - flow [1] 20 | private static int[] flow(int source, int sink) { 21 | int ans_flow = 0, ans_cost = 0; 22 | pot = new int[N]; // potential of the node 23 | 24 | while (true) { 25 | boolean[] used = new boolean[N]; 26 | int[] dist = new int[N], prev = new int[N]; 27 | Arrays.fill(dist, INF); 28 | dist[source] = 0; 29 | 30 | while (true) { 31 | int x = -1; 32 | for (int i = 0; i < N; i++) 33 | if (dist[i] != INF && !used[i] && (x == -1 || dist[i] < dist[x])) 34 | x = i; 35 | 36 | if (x == -1) 37 | break; 38 | 39 | used[x] = true; 40 | for (int i = 0; i < N; i++) 41 | if (cap[x][i] > 0 && dist[x] + cost[x][i] + pot[x] - pot[i] < dist[i]) { 42 | dist[i] = dist[x] + cost[x][i] + pot[x] - pot[i]; 43 | prev[i] = x; 44 | } 45 | } 46 | 47 | if (!used[sink]) 48 | break; 49 | 50 | int ansf = INF, ansc = 0; 51 | for (int x = sink; x != source; x = prev[x]) 52 | ansf = Math.min(ansf, cap[prev[x]][x]); 53 | 54 | ans_flow += ansf; 55 | for (int x = sink; x != source; x = prev[x]) { 56 | ansc += cost[prev[x]][x] * ansf; 57 | cap[prev[x]][x] -= ansf; 58 | cap[x][prev[x]] += ansf; 59 | } 60 | 61 | for (int i = 0; i < N; i++) 62 | pot[i] += dist[i]; 63 | 64 | ans_flow += ansf; 65 | ans_cost += ansc; 66 | } 67 | 68 | return new int[] {ans_flow, ans_cost}; 69 | // returns both flow and cost 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Graph/Algorithms/ShortestPath/BellmanFord.java: -------------------------------------------------------------------------------- 1 | package Graph.Algorithms.ShortestPath; 2 | 3 | public class BellmanFord { 4 | public static int INF = 1 << 29; 5 | static class Edge { 6 | public int from, to, weight; 7 | public Edge(int from, int to, int weight) { 8 | this.from = from; 9 | this.to = to; 10 | this.weight = weight; 11 | } 12 | } 13 | 14 | private static int[] bellman_ford(Edge[] edges, int[] dist, int start) { 15 | int N = dist.length; 16 | int M = edges.length; 17 | 18 | int[] prev = new int[N]; 19 | for (int i = 0; i < N; i++) { 20 | dist[i] = INF; 21 | prev[i] = -1; 22 | } 23 | 24 | dist[start] = 0; 25 | for (int i = 0; i < N; i++) { 26 | boolean changed = false; 27 | 28 | for (int j = 0; j < M; j++) 29 | if (dist[edges[j].from] + edges[j].weight < dist[edges[j].to]) { 30 | dist[edges[j].to] = dist[edges[j].from] + edges[j].weight; 31 | prev[edges[j].to] = edges[j].from; 32 | changed = true; 33 | } 34 | 35 | if (!changed) 36 | break; 37 | } 38 | 39 | for (int i = 0; i < M; i++) 40 | if (dist[edges[i].to] > dist[edges[i].from] + edges[i].weight) 41 | return null; 42 | 43 | return prev; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Graph/Algorithms/ShortestPath/Dijkstra.java: -------------------------------------------------------------------------------- 1 | package Graph.Algorithms.ShortestPath; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.PriorityQueue; 6 | 7 | public class Dijkstra { 8 | public static int INF = 1 << 29; 9 | 10 | static class Edge implements Comparable{ 11 | public int to, weight; 12 | public Edge(int to, int weight) { 13 | this.to = to; 14 | this.weight = weight; 15 | } 16 | 17 | public int compareTo(Edge other) { 18 | return weight - other.weight; 19 | } 20 | } 21 | private static void dijkstra(ArrayList[] graph, int[] dist, int start) { 22 | int N = dist.length; 23 | Arrays.fill(dist, INF); 24 | PriorityQueue pq = new PriorityQueue(); 25 | pq.add(new Edge(start, 0)); 26 | 27 | while (pq.size() > 0) { 28 | int node = pq.peek().to, weight = pq.peek().weight; pq.poll(); 29 | if (dist[node] != weight) continue; 30 | 31 | for (Edge e : graph[node]) { 32 | if (dist[e.to] < dist[node] + e.weight) 33 | pq.add(new Edge(e.to, dist[e.to] = dist[node] + e.weight)); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Graph/Algorithms/ShortestPath/FloydWarshall.java: -------------------------------------------------------------------------------- 1 | package Graph.Algorithms.ShortestPath; 2 | 3 | public class FloydWarshall { 4 | private static void floyd_warshall(int[][] dist) { 5 | int N = dist.length; 6 | for (int k = 0; k < N; k++) 7 | for (int i = 0; i < N; i++) 8 | for (int j = 0; j < N; j++) 9 | dist[i][j] = Math.min(dist[i][j], dist[i][k] + dist[k][j]); 10 | // dist [i][j] is the shortest distance from node i to node j 11 | // if dist [i][j] == INF, then they are not connected 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Graph/Algorithms/SpanningTree.java: -------------------------------------------------------------------------------- 1 | package Graph.Algorithms; 2 | 3 | import java.util.PriorityQueue; 4 | import static Graph.Representation.LinkedList.*; 5 | import Graph.Pair; 6 | 7 | public class SpanningTree { 8 | 9 | // for max spanning tree, add -weight and return -treeCost 10 | // for product trees, take the log of each weight (log (ab) = log (a) + log (b)) 11 | private static int minSpanningTree() { // Prim's algorithm 12 | boolean[] visited = new boolean[N]; 13 | PriorityQueue pq = new PriorityQueue(); 14 | int treeCost = 0, treeSize = 0; 15 | pq.add(new Pair(0, 0)); 16 | 17 | while (treeSize < N) { 18 | int node = pq.peek().a, weight = pq.peek().b; 19 | pq.poll(); 20 | if (visited[node]) 21 | continue; 22 | treeSize++; 23 | treeCost += weight; 24 | visited[node] = true; 25 | 26 | for (int e = elast[node]; e != -1; e = eprev[e]) 27 | if (!visited[eadj[e]]) 28 | pq.add(new Pair(eadj[e], ecost[e])); 29 | } 30 | 31 | return treeCost; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Graph/Algorithms/StronglyConnectedComponents.java: -------------------------------------------------------------------------------- 1 | package Graph.Algorithms; 2 | 3 | import java.util.Arrays; 4 | import static Graph.Representation.LinkedList.*; 5 | 6 | public class StronglyConnectedComponents { 7 | private static int[] part, index, lowlink, stack, size; 8 | private static int pidx, sidx, ssize; 9 | private static boolean[] instack; 10 | 11 | private static void tarjan() { 12 | stack = new int[N]; 13 | index = new int[N]; 14 | part = new int[N]; 15 | lowlink = new int[N]; 16 | instack = new boolean[N]; 17 | size = new int[N]; 18 | Arrays.fill(index, -1); 19 | 20 | pidx = 0; 21 | sidx = 0; 22 | ssize = 0; 23 | for (int i = 0; i < N; i++) 24 | if (index[i] == -1) 25 | strongconnect(i); 26 | } 27 | 28 | private static void strongconnect(int node) { 29 | index[node] = pidx; 30 | lowlink[node] = pidx; 31 | pidx++; 32 | stack[sidx++] = node; 33 | instack[node] = true; 34 | 35 | for (int e = elast[node]; e != -1; e = eprev[e]) { 36 | if (index[eadj[e]] == -1) { 37 | strongconnect(eadj[e]); 38 | if (lowlink[eadj[e]] < lowlink[node]) 39 | lowlink[node] = lowlink[eadj[e]]; 40 | } else if (instack[eadj[e]]) { 41 | if (index[eadj[e]] < lowlink[node]) 42 | lowlink[node] = index[eadj[e]]; 43 | } 44 | } 45 | 46 | if (lowlink[node] == index[node]) { 47 | int cur, csize = 0; 48 | do { 49 | cur = stack[--sidx]; 50 | csize++; 51 | part[cur] = ssize; 52 | instack[cur] = false; 53 | } while (cur != node); 54 | size[ssize++] = csize; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Graph/Algorithms/TopologicalSort.java: -------------------------------------------------------------------------------- 1 | package Graph.Algorithms; 2 | 3 | import static Graph.Representation.LinkedList.*; 4 | 5 | public class TopologicalSort { 6 | private static int[] indeg; 7 | 8 | // note new addEdge method 9 | private static void d_addEdge(int a, int b, int c) { // directed + indegrees 10 | indeg[b]++; 11 | eadj[eidx] = b; 12 | eprev[eidx] = elast[a]; 13 | ecost[eidx] = c; 14 | elast[a] = eidx++; 15 | } 16 | 17 | private static boolean toposort(int[] topo) { 18 | int[] queue = new int[N]; 19 | int front = 0, back = 0, idx = 0; 20 | 21 | // add all nodes with no incoming edges 22 | for (int i = 0; i < indeg.length; i++) 23 | if (indeg[i] == 0) 24 | queue[back++] = i; 25 | 26 | while (front != back) { 27 | int node = queue[front++]; 28 | topo[idx++] = node; 29 | 30 | // expand current node, removing all of its edges 31 | for (int e = elast[node]; e != -1; e = eprev[e]) 32 | if (--indeg[eadj[e]] == 0) 33 | queue[back++] = eadj[e]; 34 | } 35 | 36 | return idx != topo.length; // true if successful, false if not a DAG 37 | // topo will contain topologically sorted list of nodes 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Graph/Algorithms/TwoSat.java: -------------------------------------------------------------------------------- 1 | package Graph.Algorithms; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | public class TwoSat { 8 | static void dfs1(List[] graph, boolean[] used, List order, int u) { 9 | used[u] = true; 10 | for (int v : graph[u]) 11 | if (!used[v]) 12 | dfs1(graph, used, order, v); 13 | order.add(u); 14 | } 15 | 16 | static void dfs2(List[] reverseGraph, int[] comp, int u, int color) { 17 | comp[u] = color; 18 | for (int v : reverseGraph[u]) 19 | if (comp[v] == -1) 20 | dfs2(reverseGraph, comp, v, color); 21 | } 22 | 23 | public static boolean[] solve2Sat(List[] graph) { 24 | int n = graph.length; 25 | boolean[] used = new boolean[n]; 26 | List order = new ArrayList<>(); 27 | for (int i = 0; i < n; ++i) 28 | if (!used[i]) 29 | dfs1(graph, used, order, i); 30 | 31 | List[] reverseGraph = new List[n]; 32 | for (int i = 0; i < n; i++) 33 | reverseGraph[i] = new ArrayList<>(); 34 | for (int i = 0; i < n; i++) 35 | for (int j : graph[i]) 36 | reverseGraph[j].add(i); 37 | 38 | int[] comp = new int[n]; 39 | Arrays.fill(comp, -1); 40 | for (int i = 0, color = 0; i < n; ++i) { 41 | int u = order.get(n - i - 1); 42 | if (comp[u] == -1) 43 | dfs2(reverseGraph, comp, u, color++); 44 | } 45 | 46 | for (int i = 0; i < n; ++i) 47 | if (comp[i] == comp[i ^ 1]) 48 | return null; 49 | 50 | boolean[] res = new boolean[n / 2]; 51 | for (int i = 0; i < n; i += 2) 52 | res[i / 2] = comp[i] > comp[i ^ 1]; 53 | return res; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Graph/Pair.java: -------------------------------------------------------------------------------- 1 | package Graph; 2 | 3 | public class Pair implements Comparable { 4 | public int a, b; 5 | 6 | public Pair(int a, int b) { 7 | this.a = a; 8 | this.b = b; 9 | } 10 | 11 | public int compareTo(Pair other) { 12 | return b == other.b ? a - other.a : b - other.b; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Graph/Representation/AdjacencyMatrix.java: -------------------------------------------------------------------------------- 1 | package Graph.Representation; 2 | 3 | /** 4 | * 5 | * @author Lewin 6 | * 7 | */ 8 | public class AdjacencyMatrix implements Graph { 9 | public static int N; 10 | public static int[][] grid; 11 | 12 | @Override 13 | public void init(int N, int M) { 14 | this.N = N; 15 | grid = new int[N][N]; 16 | } 17 | 18 | @Override 19 | public void addEdge(int a, int b, int weight) { 20 | grid[a][b] = weight; 21 | // if don't want bidirectional, comment out next line 22 | grid[b][a] = weight; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/Graph/Representation/EdgeList.java: -------------------------------------------------------------------------------- 1 | package Graph.Representation; 2 | 3 | public class EdgeList implements Graph { 4 | static class Edge { 5 | public int from, to, weight; 6 | 7 | public Edge(int from, int to, int weight) { 8 | this.from = from; 9 | this.to = to; 10 | this.weight = weight; 11 | } 12 | } 13 | 14 | public static int N, M, idx; 15 | public static Edge[] edges; 16 | 17 | @Override 18 | public void init(int N, int M) { 19 | this.N = N; 20 | this.M = M; 21 | edges = new Edge[M]; 22 | idx = 0; 23 | } 24 | 25 | @Override 26 | public void addEdge(int a, int b, int weight) { 27 | edges[idx++] = new Edge(a, b, weight); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/Graph/Representation/Graph.java: -------------------------------------------------------------------------------- 1 | package Graph.Representation; 2 | 3 | public interface Graph { 4 | // N number of nodes 5 | // nodes labeled 0...N-1 6 | // M number of edges 7 | public static final int INF = 1 << 29; 8 | 9 | public void init(int N, int M); 10 | 11 | public void addEdge(int a, int b, int weight); 12 | } 13 | -------------------------------------------------------------------------------- /src/Graph/Representation/LinkedList.java: -------------------------------------------------------------------------------- 1 | package Graph.Representation; 2 | 3 | /** 4 | * 5 | * @author Lewin 6 | * 7 | */ 8 | public class LinkedList implements Graph { 9 | public static int[] eadj, elast, eprev, ecost; 10 | public static int eidx; 11 | public static int N, M; 12 | 13 | @Override 14 | public void init(int N, int M) { 15 | this.N = N; 16 | this.M = M; 17 | 18 | eadj = new int[2 * M]; 19 | eprev = new int[2 * M]; 20 | ecost = new int[2 * M]; 21 | elast = new int[N]; 22 | eidx = 0; 23 | } 24 | 25 | @Override 26 | public void addEdge(int a, int b, int weight) { 27 | eadj[eidx] = b; 28 | ecost[eidx] = weight; 29 | eprev[eidx] = elast[a]; 30 | elast[a] = eidx++; 31 | // if don't want bidirectional, comment out below line 32 | eadj[eidx] = a; 33 | ecost[eidx] = weight; 34 | eprev[eidx] = elast[b]; 35 | elast[b] = eidx++; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Graph/Triplet.java: -------------------------------------------------------------------------------- 1 | package Graph; 2 | 3 | public class Triplet implements Comparable { 4 | public int a, b, c; 5 | 6 | public Triplet(int a, int b, int c) { 7 | this.a = a; 8 | this.b = b; 9 | this.c = c; 10 | } 11 | 12 | public int compareTo(Triplet other) { 13 | return c == other.c ? b == other.b ? a - other.a : b - other.b : c - other.c; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/LinearProgramming/LPSolver.java: -------------------------------------------------------------------------------- 1 | package LinearProgramming; 2 | 3 | public class LPSolver { 4 | public static double EPS = 1e-9; 5 | public int m, n; 6 | public int[] B, N; 7 | public double[][] D; 8 | public double[] x; 9 | 10 | public LPSolver(double[][] A, double[] b, double[] c) { 11 | n = c.length; 12 | m = b.length; 13 | N = new int[n + 1]; 14 | B = new int[m]; 15 | D = new double[m + 2][n + 2]; 16 | for (int i = 0; i < m; i++) 17 | for (int j = 0; j < n; j++) 18 | D[i][j] = A[i][j]; 19 | for (int i = 0; i < m; i++) { 20 | B[i] = n + i; 21 | D[i][n] = -1; 22 | D[i][n + 1] = b[i]; 23 | } 24 | for (int j = 0; j < n; j++) { 25 | N[j] = j; 26 | D[m][j] = -c[j]; 27 | } 28 | N[n] = -1; 29 | D[m + 1][n] = 1; 30 | } 31 | 32 | public void pivot(int r, int s) { 33 | for (int i = 0; i < m + 2; i++) 34 | if (i != r) 35 | for (int j = 0; j < n + 2; j++) 36 | if (j != s) 37 | D[i][j] -= D[r][j] * D[i][s] / D[r][s]; 38 | for (int j = 0; j < n + 2; j++) 39 | if (j != s) 40 | D[r][j] /= D[r][s]; 41 | for (int i = 0; i < m + 2; i++) 42 | if (i != r) 43 | D[i][s] /= -D[r][s]; 44 | D[r][s] = 1.0 / D[r][s]; 45 | int t = B[r]; 46 | B[r] = N[s]; 47 | N[s] = t; 48 | } 49 | 50 | public boolean simplex(int phase) { 51 | int x = phase == 1 ? m + 1 : m; 52 | while (true) { 53 | int s = -1; 54 | for (int j = 0; j <= n; j++) { 55 | if (phase == 2 && N[j] == -1) 56 | continue; 57 | if (s == -1 || D[x][j] < D[x][s] || (Math.abs(D[x][j] - D[x][s]) < EPS && N[j] < N[s])) 58 | s = j; 59 | } 60 | if (D[x][s] >= -EPS) 61 | return true; 62 | int r = -1; 63 | for (int i = 0; i < m; i++) { 64 | if (D[i][s] <= 0) 65 | continue; 66 | if (r == -1 || D[i][n + 1] * D[r][s] < D[r][n + 1] * D[i][s] 67 | || (Math.abs(D[i][n + 1] * D[r][s] - D[r][n + 1] * D[i][s]) < EPS && B[i] < B[r])) 68 | r = i; 69 | } 70 | if (r == -1) 71 | return false; 72 | pivot(r, s); 73 | } 74 | } 75 | 76 | public double solve() { 77 | int r = 0; 78 | for (int i = 1; i < m; i++) 79 | if (D[i][n + 1] < D[r][n + 1]) 80 | r = i; 81 | if (D[r][n + 1] <= -EPS) { 82 | pivot(r, n); 83 | if (!simplex(1) || D[m + 1][n + 1] < -EPS) 84 | return Double.NEGATIVE_INFINITY; 85 | for (int i = 0; i < m; i++) 86 | if (B[i] == -1) { 87 | int s = -1; 88 | for (int j = 0; j <= n; j++) 89 | if (s == -1 || D[i][j] < D[i][s] || (Math.abs(D[i][j] - D[i][s]) < EPS && N[j] < N[s])) 90 | s = j; 91 | pivot(i, s); 92 | } 93 | } 94 | if (!simplex(2)) 95 | return Double.POSITIVE_INFINITY; 96 | x = new double[n]; 97 | for (int i = 0; i < m; i++) 98 | if (B[i] < n) 99 | x[B[i]] = D[i][n + 1]; 100 | return D[m][n + 1]; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/LinearProgramming/LinearProgramming.java: -------------------------------------------------------------------------------- 1 | package LinearProgramming; 2 | 3 | import java.util.Arrays; 4 | 5 | public class LinearProgramming { 6 | public static final double EPS = 1e-9; 7 | /** 8 | * Maximizes CX subject to AX <= B with X >= 0 X will be set as a result, but method returns value 9 | */ 10 | public static double[] X; 11 | 12 | public static double simplex(double[][] A, double[] B, double[] C) { 13 | // peturbations to avoid cycling 14 | for (int i = 0; i < B.length; i++) 15 | B[i] += Math.random() * 1e-300; 16 | 17 | int vars = C.length; 18 | int cons = B.length; 19 | int rows = cons, cols = vars + cons + 1; 20 | double[][] a = new double[cons + 1][vars + cons + 2]; 21 | for (int i = 0; i < cons; i++) { 22 | for (int j = 0; j < vars; j++) 23 | a[i][j] = A[i][j]; 24 | for (int j = 0; j < cons; j++) 25 | a[i][j + vars] = i == j ? 1 : 0; 26 | a[i][vars + cons] = 0; 27 | a[i][vars + cons + 1] = B[i]; 28 | } 29 | 30 | for (int j = 0; j < vars; j++) { 31 | a[cons][j] = C[j] == 0 ? 0 : -C[j]; 32 | a[cons][j + vars] = 0; 33 | } 34 | 35 | a[cons][vars + cons] = 1; 36 | a[cons][vars + cons + 1] = 0; 37 | 38 | while (true) { 39 | int pc = 0; 40 | for (int i = 1; i < cols; i++) 41 | if (a[rows][i] < a[rows][pc]) 42 | pc = i; 43 | 44 | if (a[rows][pc] >= 0) 45 | break; 46 | 47 | int pr = -1; 48 | for (int i = 0; i < rows; i++) 49 | if (a[i][pc] >= EPS) 50 | if (pr == -1 || a[i][cols] / a[i][pc] < a[pr][cols] / a[pr][pc]) 51 | pr = i; 52 | if (pr == -1) { 53 | System.out.println("Unbounded"); 54 | return Double.MAX_VALUE; 55 | } 56 | 57 | for (int i = 0; i <= rows; i++) { 58 | if (i == pr) 59 | continue; 60 | double ratio = a[i][pc] / a[pr][pc]; 61 | for (int j = 0; j <= cols; j++) 62 | a[i][j] -= ratio * a[pr][j]; 63 | a[i][pc] = 0; 64 | } 65 | 66 | // normalize 67 | for (int i = 0; i <= rows; i++) { 68 | double max = 0; 69 | for (int j = 0; j <= cols; j++) 70 | max = Math.max(max, Math.abs(a[i][j])); 71 | for (int j = 0; j <= cols; j++) 72 | a[i][j] /= max; 73 | } 74 | } 75 | 76 | // get X vector 77 | X = new double[vars]; 78 | for (int i = 0; i < vars; i++) { 79 | boolean found = false; 80 | for (int j = 0; j < cons; j++) { 81 | if (a[j][i] != 0) { 82 | if (!found) { 83 | X[i] = a[j][cols] / a[j][i]; 84 | found = true; 85 | } else { 86 | X[i] = 0; 87 | break; 88 | } 89 | } 90 | } 91 | } 92 | return a[rows][cols] / a[rows][cols - 1]; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/Matrix/Determinant.java: -------------------------------------------------------------------------------- 1 | package Matrix; 2 | 3 | public class Determinant { 4 | 5 | // square matrix 6 | private static double det(double[][] arr) { 7 | int N = arr.length; 8 | double[][] M = new double[N][N]; 9 | for (int i = 0; i < arr.length; i++) 10 | System.arraycopy(arr[i], 0, M[i], 0, N); 11 | 12 | double mult = 1; 13 | for (int r = 0; r < N; r++) { 14 | int k = r; 15 | while (M[k][r] == 0) { 16 | k++; 17 | if (k == N) 18 | return 0; 19 | } 20 | double[] temp = M[r]; 21 | M[r] = M[k]; 22 | M[k] = temp; 23 | if (r != k) { 24 | mult *= -1; 25 | } 26 | 27 | double lv = M[r][r]; 28 | for (int j = 0; j < N; j++) 29 | M[r][j] /= lv; 30 | mult *= lv; 31 | 32 | for (int i = r; i < N; i++) { 33 | if (i != r) { 34 | lv = M[i][r]; 35 | for (int j = r; j < N; j++) 36 | M[i][j] -= lv * M[r][j]; 37 | } 38 | } 39 | } 40 | return mult; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Matrix/MatrixInverse.java: -------------------------------------------------------------------------------- 1 | package Matrix; 2 | 3 | public class MatrixInverse { 4 | 5 | // square matrix 6 | // returns null if no inverse 7 | private static double[][] inv(double[][] arr) { 8 | int N = arr.length; 9 | double[][] M = new double[N][2 * N]; 10 | for (int i = 0; i < arr.length; i++) { 11 | System.arraycopy(arr[i], 0, M[i], 0, N); 12 | M[i][i + N] = 1; 13 | } 14 | 15 | for (int r = 0; r < N; r++) { 16 | int k = r; 17 | while (M[k][r] == 0) { 18 | k++; 19 | if (k == N) 20 | return null; // no inverse 21 | } 22 | double[] temp = M[r]; 23 | M[r] = M[k]; 24 | M[k] = temp; 25 | 26 | double lv = M[r][r]; 27 | for (int j = 0; j < 2 * N; j++) 28 | M[r][j] /= lv; 29 | 30 | for (int i = 0; i < N; i++) { 31 | if (i != r) { 32 | lv = M[i][r]; 33 | for (int j = 0; j < 2 * N; j++) 34 | M[i][j] -= lv * M[r][j]; 35 | } 36 | } 37 | } 38 | 39 | double[][] ret = new double[N][N]; 40 | for (int i = 0; i < N; i++) 41 | System.arraycopy(M[i], N, ret[i], 0, N); 42 | return ret; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Matrix/MatrixOperations.java: -------------------------------------------------------------------------------- 1 | package Matrix; 2 | 3 | /** 4 | * Operations on matrices 5 | * 6 | * @author Lewin 7 | * 8 | */ 9 | public class MatrixOperations { 10 | private static int mod; 11 | 12 | private static int[][] mat_exp(int[][] A, int e) { 13 | if (e == 1) 14 | return A; 15 | else if (e % 2 == 0) { 16 | int[][] A1 = mat_exp(A, e / 2); 17 | return matrix_mult(A1, A1); 18 | } else 19 | return matrix_mult(A, mat_exp(A, e - 1)); 20 | } 21 | 22 | private static int[][] matrix_mult(int[][] A, int[][] B) { 23 | int[][] C = new int[A.length][A.length]; 24 | for (int i = 0; i < A.length; i++) 25 | for (int j = 0; j < A.length; j++) 26 | for (int k = 0; k < A.length; k++) 27 | C[i][k] = (C[i][k] + A[i][j] * B[j][k]) % mod; 28 | return C; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Matrix/RowReduce.java: -------------------------------------------------------------------------------- 1 | package Matrix; 2 | 3 | /** 4 | * Row reduce function 5 | * 6 | * @author Lewin 7 | * 8 | */ 9 | public class RowReduce { 10 | private static void rref(double[][] M) { 11 | int row = M.length; 12 | if (row == 0) 13 | return; 14 | 15 | int col = M[0].length; 16 | 17 | int lead = 0; 18 | for (int r = 0; r < row; r++) { 19 | if (lead >= col) 20 | return; 21 | 22 | int k = r; 23 | while (M[k][lead] == 0) { 24 | k++; 25 | if (k == row) { 26 | k = r; 27 | lead++; 28 | if (lead == col) 29 | return; 30 | } 31 | } 32 | double[] temp = M[r]; 33 | M[r] = M[k]; 34 | M[k] = temp; 35 | 36 | double lv = M[r][lead]; 37 | for (int j = 0; j < col; j++) 38 | M[r][j] /= lv; 39 | 40 | for (int i = 0; i < row; i++) { 41 | if (i != r) { 42 | lv = M[i][lead]; 43 | for (int j = 0; j < col; j++) 44 | M[i][j] -= lv * M[r][j]; 45 | } 46 | } 47 | lead++; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Misc/FastIO.java: -------------------------------------------------------------------------------- 1 | package Misc; 2 | 3 | import java.io.DataInputStream; 4 | import java.io.FileInputStream; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | 8 | public class FastIO { 9 | static class Reader { 10 | final private int BUFFER_SIZE = 1 << 16; 11 | private DataInputStream din; 12 | private byte[] buffer; 13 | private int bufferPointer, bytesRead; 14 | 15 | 16 | public Reader() { 17 | din = new DataInputStream(System.in); 18 | buffer = new byte[BUFFER_SIZE]; 19 | bufferPointer = bytesRead = 0; 20 | } 21 | 22 | public Reader(String file_name) throws IOException { 23 | din = new DataInputStream(new FileInputStream(file_name)); 24 | buffer = new byte[BUFFER_SIZE]; 25 | bufferPointer = bytesRead = 0; 26 | } 27 | 28 | public Reader(InputStream in) throws IOException { 29 | din = new DataInputStream(in); 30 | buffer = new byte[BUFFER_SIZE]; 31 | bufferPointer = bytesRead = 0; 32 | } 33 | 34 | public String readLine() throws IOException { 35 | byte[] buf = new byte[1 << 20]; 36 | int cnt = 0; 37 | byte c = read(); 38 | while (c <= ' ') 39 | c = read(); 40 | do { 41 | buf[cnt++] = c; 42 | } while ((c = read()) != '\n'); 43 | return new String(buf, 0, cnt); 44 | } 45 | 46 | public String next() throws IOException { 47 | byte[] buf = new byte[1 << 20]; 48 | int cnt = 0; 49 | byte c = read(); 50 | while (c <= ' ') 51 | c = read(); 52 | do { 53 | buf[cnt++] = c; 54 | } while ((c = read()) > ' '); 55 | return new String(buf, 0, cnt); 56 | } 57 | 58 | public int nextInt() throws IOException { 59 | int ret = 0; 60 | byte c = read(); 61 | while (c <= ' ') 62 | c = read(); 63 | boolean neg = (c == '-'); 64 | if (neg) 65 | c = read(); 66 | do { 67 | ret = ret * 10 + c - '0'; 68 | } while ((c = read()) >= '0' && c <= '9'); 69 | if (neg) 70 | return -ret; 71 | return ret; 72 | } 73 | 74 | public long nextLong() throws IOException { 75 | long ret = 0; 76 | byte c = read(); 77 | while (c <= ' ') 78 | c = read(); 79 | boolean neg = (c == '-'); 80 | if (neg) 81 | c = read(); 82 | do { 83 | ret = ret * 10 + c - '0'; 84 | } while ((c = read()) >= '0' && c <= '9'); 85 | if (neg) 86 | return -ret; 87 | return ret; 88 | } 89 | 90 | public double nextDouble() throws IOException { 91 | double ret = 0, div = 1; 92 | byte c = read(); 93 | while (c <= ' ') 94 | c = read(); 95 | boolean neg = (c == '-'); 96 | if (neg) 97 | c = read(); 98 | do { 99 | ret = ret * 10 + c - '0'; 100 | } while ((c = read()) >= '0' && c <= '9'); 101 | if (c == '.') 102 | while ((c = read()) >= '0' && c <= '9') 103 | ret += (c - '0') / (div *= 10); 104 | if (neg) 105 | return -ret; 106 | return ret; 107 | } 108 | 109 | private void fillBuffer() throws IOException { 110 | bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE); 111 | if (bytesRead == -1) 112 | buffer[0] = -1; 113 | } 114 | 115 | private byte read() throws IOException { 116 | if (bufferPointer == bytesRead) 117 | fillBuffer(); 118 | return buffer[bufferPointer++]; 119 | } 120 | 121 | public void close() throws IOException { 122 | if (din == null) 123 | return; 124 | din.close(); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/Misc/InputReader.java: -------------------------------------------------------------------------------- 1 | package Misc; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.util.StringTokenizer; 8 | 9 | class InputReader { 10 | public BufferedReader reader; 11 | public StringTokenizer tokenizer; 12 | 13 | public InputReader(InputStream stream) { 14 | reader = new BufferedReader(new InputStreamReader(stream), 32768); 15 | tokenizer = null; 16 | } 17 | 18 | public String next() { 19 | while (tokenizer == null || !tokenizer.hasMoreTokens()) { 20 | try { 21 | tokenizer = new StringTokenizer(reader.readLine()); 22 | } catch (IOException e) { 23 | throw new RuntimeException(e); 24 | } 25 | } 26 | return tokenizer.nextToken(); 27 | } 28 | 29 | public int nextInt() { 30 | return Integer.parseInt(next()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/NumberTheory/DiscreteLog.java: -------------------------------------------------------------------------------- 1 | package NumberTheory; 2 | 3 | import java.util.HashMap; 4 | import static NumberTheory.Utils.inv; 5 | import static NumberTheory.SafeArithmetic.mod_exp; 6 | 7 | 8 | public class DiscreteLog { 9 | // gcd (g, mod) = 1 10 | public static long discreteLog(long g, long gn, long mod) { 11 | long m = (long) Math.ceil(Math.sqrt(mod)); 12 | HashMap mp = new HashMap(); 13 | long cur = 1; 14 | for (int i = 0; i < m; i++) { 15 | mp.put(cur, (long) i); 16 | cur = (cur * g) % mod; 17 | } 18 | long st2 = mod_exp(inv(g, mod), m, mod); 19 | long y = gn; 20 | for (int i = 0; i < m; i++) { 21 | if (mp.containsKey(y)) 22 | return i * m + mp.get(y); 23 | y = (y * st2) % mod; 24 | } 25 | return -1; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/NumberTheory/PollardRho.java: -------------------------------------------------------------------------------- 1 | package NumberTheory; 2 | 3 | import java.math.BigInteger; 4 | import java.security.SecureRandom; 5 | 6 | /** 7 | * Implementation of Pollard Rho's factoring algorithm 8 | * 9 | * @author Lewin http://en.wikipedia.org/wiki/Pollard's_rho_algorithm 10 | */ 11 | 12 | public class PollardRho { 13 | private final static BigInteger ZERO = new BigInteger("0"); 14 | private final static BigInteger ONE = new BigInteger("1"); 15 | private final static BigInteger TWO = new BigInteger("2"); 16 | private final static SecureRandom random = new SecureRandom(); 17 | 18 | // cycle detection 19 | public static BigInteger rho(BigInteger N) { 20 | BigInteger divisor; 21 | BigInteger c = new BigInteger(N.bitLength(), random); 22 | BigInteger x = new BigInteger(N.bitLength(), random); 23 | BigInteger xx = x; 24 | 25 | // check divisibility by 2 26 | if (N.mod(TWO).compareTo(ZERO) == 0) 27 | return TWO; 28 | 29 | do { 30 | x = x.multiply(x).mod(N).add(c).mod(N); 31 | xx = xx.multiply(xx).mod(N).add(c).mod(N); 32 | xx = xx.multiply(xx).mod(N).add(c).mod(N); 33 | divisor = x.subtract(xx).gcd(N); 34 | } while ((divisor.compareTo(ONE)) == 0); 35 | 36 | return divisor; 37 | } 38 | 39 | // prints out all factors 40 | // can modify to store these factors into some data structure 41 | public static void factor(BigInteger N) { 42 | if (N.compareTo(ONE) == 0) 43 | return; 44 | if (N.isProbablePrime(20)) { 45 | System.out.println(N); 46 | return; 47 | } 48 | BigInteger divisor = rho(N); 49 | factor(divisor); 50 | factor(N.divide(divisor)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/NumberTheory/PrimeSieve.java: -------------------------------------------------------------------------------- 1 | package NumberTheory; 2 | 3 | /** 4 | * Prime Siever 5 | * 6 | * @author Lewin 7 | * 8 | */ 9 | public class PrimeSieve { 10 | public static boolean[] isPrime; 11 | public static int[] prime; 12 | public static int idx, len; 13 | 14 | private static void generatePrimes() { 15 | isPrime = new boolean[len + 1]; 16 | prime = new int[len / 2]; 17 | isPrime[2] = true; 18 | prime[idx++] = 2; 19 | int i; 20 | for (i = 3; i <= len; i += 2) 21 | isPrime[i] = true; 22 | for (i = 3; i * i <= len; i += 2) { 23 | if (isPrime[i]) { 24 | prime[idx++] = i; 25 | for (int j = i * i; j <= len; j += 2 * i) 26 | isPrime[j] = false; 27 | } 28 | } 29 | for (; i <= len; i += 2) 30 | if (isPrime[i]) 31 | prime[idx++] = i; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/NumberTheory/SafeArithmetic.java: -------------------------------------------------------------------------------- 1 | package NumberTheory; 2 | 3 | /** 4 | * Safely multiplies and adds number under a modulus to prevent overflow Operations may still 5 | * overflow if modulus is greater than Long.MAX_VALUE / 2 6 | * 7 | * @author Lewin 8 | * 9 | */ 10 | public class SafeArithmetic { 11 | public static long mod_mult(long x, long y, long p) { 12 | if (x == 0 || y == 0) 13 | return 0; 14 | long a = x, b = y, c = 0; 15 | while (a > 0) { 16 | if ((a & 1) == 1) 17 | c = (c + b) % p; 18 | a >>= 1; 19 | b = (b * 2) % p; 20 | } 21 | return c; 22 | } 23 | 24 | public static long mod_exp(long b, long e, long mod) { 25 | if (b == 0 || b == 1) 26 | return b; 27 | long res = 1; 28 | while (e > 0) { 29 | if ((e & 1) == 1) 30 | res = mod_mult(res, b, mod); 31 | e >>= 1; 32 | b = mod_mult(b, b, mod); 33 | } 34 | return res; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/NumberTheory/TotientSieve.java: -------------------------------------------------------------------------------- 1 | package NumberTheory; 2 | 3 | /** 4 | * Euler's Totient Function Siever 5 | * 6 | * @author Lewin http://en.wikipedia.org/wiki/Euler's_totient_function 7 | */ 8 | public class TotientSieve { 9 | private static boolean[] isPrime; 10 | private static int[] prime; 11 | private static int idx, len; 12 | private static int[] phi; 13 | 14 | private static void phi_prime_sieve() { 15 | isPrime = new boolean[len + 1]; 16 | prime = new int[len / 2]; 17 | phi = new int[len + 1]; 18 | phi[0] = 0; 19 | phi[1] = 1; 20 | for (int i = 2; i <= len; i++) { 21 | isPrime[i] = true; 22 | phi[i] = i; 23 | } 24 | for (int i = 2; i <= len; i++) { 25 | if (isPrime[i]) { 26 | prime[idx++] = i; 27 | phi[i] = i - 1; 28 | for (int j = i + i; j <= len; j += i) { 29 | isPrime[j] = false; 30 | phi[j] /= i; 31 | phi[j] *= i - 1; 32 | } 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/NumberTheory/Utils.java: -------------------------------------------------------------------------------- 1 | package NumberTheory; 2 | 3 | import static NumberTheory.PrimeSieve.idx; 4 | import static NumberTheory.PrimeSieve.prime; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * Collection of common operations 11 | * 12 | * @author Lewin 13 | * 14 | */ 15 | 16 | public class Utils { 17 | // Euler's Totient Function 18 | public static long phi(long n) {// make sure to generate primes 19 | long temp = n; 20 | for (int i = 0; prime[i] * prime[i] <= temp && i < idx; i++) 21 | if (temp % prime[i] == 0) { 22 | n -= n / prime[i]; 23 | while (temp % prime[i] == 0) 24 | temp /= prime[i]; 25 | } 26 | return temp == 1 ? n : n / temp * (temp - 1); 27 | } 28 | 29 | // N choose K 30 | public static long comb(int n, int k) { 31 | int a = Math.min(k, n - k); 32 | long res = 1; 33 | for (int i = 1; i <= a; i++) { 34 | res *= n--; 35 | res /= i; 36 | } 37 | return res; 38 | } 39 | 40 | // Greatest Common Divisor 41 | public static long gcd(long x, long y) { 42 | for (; x != 0; x ^= y, y ^= x, x ^= y, x %= y); 43 | return y; 44 | } 45 | 46 | // Inverse of N mod M; 47 | public static long inv(long N, long M) { 48 | long x = 0, lastx = 1, y = 1, lasty = 0, q, t, a = N, b = M; 49 | while (b != 0) { 50 | q = a / b; t = a % b; a = b; b = t; 51 | t = x; x = lastx - q * x; lastx = t; 52 | t = y; y = lasty - q * y; lasty = t; 53 | } 54 | return (lastx + M) % M; 55 | } 56 | 57 | // Chinese Remainder Theorem 58 | // all mods are pairwise coprime 59 | public static long CRT(long[] vals, long[] mods) { 60 | long prodall = 1; 61 | for (long j : mods) 62 | prodall *= j; 63 | 64 | long ret = 0; 65 | for (int i = 0; i < vals.length; i++) { 66 | long ni = mods[i], ai = vals[i]; 67 | ret = (ret + ai * prodall / ni % prodall * inv(prodall / ni % ni, ni)) % prodall; 68 | } 69 | return ret; 70 | } 71 | 72 | public static int generator(int p) { 73 | ArrayList fact = new ArrayList<>(); 74 | int phi = p - 1; 75 | int n = phi; 76 | for (int i = 2; i * i <= n; ++i) 77 | if (n % i == 0) { 78 | fact.add(i); 79 | while (n % i == 0) 80 | n /= i; 81 | } 82 | if (n > 1) fact.add(n); 83 | 84 | for (int res = 2; res <= p; ++res) { 85 | int i; 86 | for (i = 0; i < fact.size() && mod_exp(res, phi / fact.get(i), p) != 1; ++i) ; 87 | if (i == fact.size()) 88 | return res; 89 | } 90 | 91 | return -1; 92 | } 93 | 94 | public static long mod_exp(long b, long e, long mod) { 95 | long res = 1; 96 | while (e > 0) { 97 | if ((e & 1) == 1) 98 | res = (res * b) % mod; 99 | b = (b * b) % mod; 100 | e >>= 1; 101 | } 102 | return res; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/String/AhoCorasick.java: -------------------------------------------------------------------------------- 1 | package String; 2 | 3 | import java.util.Arrays; 4 | 5 | // taken from here: https://sites.google.com/site/indy256/algo/aho_corasick 6 | public class AhoCorasick { 7 | static final int ALPHABET_SIZE = 26; 8 | 9 | Node[] nodes; 10 | int nodeCount; 11 | 12 | static class Node { 13 | int parent; 14 | int depth; 15 | char charFromParent; 16 | int suffLink = -1; 17 | int[] children = new int[ALPHABET_SIZE]; 18 | int[] transitions = new int[ALPHABET_SIZE]; 19 | boolean leaf; 20 | 21 | { 22 | Arrays.fill(children, -1); 23 | Arrays.fill(transitions, -1); 24 | } 25 | } 26 | 27 | public AhoCorasick(int maxNodes) { 28 | nodes = new Node[maxNodes]; 29 | // create root 30 | nodes[0] = new Node(); 31 | nodes[0].suffLink = 0; 32 | nodes[0].parent = -1; 33 | nodeCount = 1; 34 | } 35 | 36 | public void addString(String s) { 37 | int cur = 0; 38 | for (char ch : s.toCharArray()) { 39 | int c = ch - 'a'; 40 | if (nodes[cur].children[c] == -1) { 41 | nodes[nodeCount] = new Node(); 42 | nodes[nodeCount].parent = cur; 43 | nodes[nodeCount].charFromParent = ch; 44 | nodes[cur].children[c] = nodeCount++; 45 | } 46 | cur = nodes[cur].children[c]; 47 | } 48 | nodes[cur].leaf = true; 49 | nodes[cur].depth = s.length(); 50 | } 51 | 52 | public int suffLink(int nodeIndex) { 53 | Node node = nodes[nodeIndex]; 54 | if (node.suffLink == -1) 55 | node.suffLink = node.parent == 0 ? 0 : transition(suffLink(node.parent), node.charFromParent); 56 | return node.suffLink; 57 | } 58 | 59 | public int transition(int nodeIndex, char ch) { 60 | int c = ch - 'a'; 61 | Node node = nodes[nodeIndex]; 62 | if (node.transitions[c] == -1) 63 | node.transitions[c] = 64 | node.children[c] != -1 ? node.children[c] : (nodeIndex == 0 ? 0 : transition( 65 | suffLink(nodeIndex), ch)); 66 | return node.transitions[c]; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/String/BWT.java: -------------------------------------------------------------------------------- 1 | package String; 2 | 3 | /** 4 | * @author: Lewin A linear time BWT encoder/decoder also computes suffix arrays in linear time 5 | */ 6 | import java.io.BufferedReader; 7 | import java.io.FileReader; 8 | import java.io.IOException; 9 | import java.io.PrintWriter; 10 | 11 | public class BWT { 12 | // number of letters in our alphabet 13 | private static final int K = 53; 14 | 15 | private static int toInt(char c) { 16 | if (c == '$') 17 | return 0; 18 | if (c >= 'A' && c <= 'Z') 19 | return c - 'A' + 1; 20 | else 21 | return c - 'a' + ('Z' - 'A' + 1) + 1; 22 | } 23 | 24 | private static char toChar(int i) { 25 | if (i == 0) 26 | return '$'; 27 | if (i > 0 && i <= 26) 28 | return (char) (i + 'A' - 1); 29 | else 30 | return (char) (i - 27 + 'a'); 31 | } 32 | 33 | private static int[] radix_sort(int[] s, int[] pos) { 34 | int N = pos.length; 35 | int[] count = new int[s.length]; 36 | for (int i = 0; i < N; i++) 37 | count[s[pos[i]]]++; 38 | 39 | for (int j = 1; j < count.length; j++) 40 | count[j] += count[j - 1]; 41 | for (int j = count.length - 1; j > 0; j--) 42 | count[j] = count[j - 1]; 43 | count[0] = 0; 44 | 45 | // get new positions 46 | int[] nord = new int[N]; 47 | for (int i = 0; i < N; i++) 48 | nord[count[s[pos[i]]]++] = pos[i]; 49 | 50 | return nord; 51 | } 52 | 53 | private static int[] suffix_array(int[] s) { 54 | int N = s.length; 55 | 56 | int n1 = (N + 1) / 3, n2 = N / 3, n0 = (N + 2) / 3; 57 | 58 | if (N % 3 == 1) 59 | n1++; 60 | // pad S 61 | int[] ns = new int[N + 3]; 62 | System.arraycopy(s, 0, ns, 0, s.length); 63 | 64 | int[] pos = new int[n1 + n2]; 65 | int idx = 0; 66 | for (int i = 1; i < N; i += 3) 67 | pos[idx++] = i; 68 | if (N % 3 == 1) 69 | pos[idx++] = N; 70 | for (int i = 2; i < N; i += 3) 71 | pos[idx++] = i; 72 | 73 | int[] bmap = new int[N + 1]; 74 | for (int i = 0; i < pos.length; i++) 75 | bmap[pos[i]] = i; 76 | 77 | int[] fmap = new int[n1 + n2]; 78 | System.arraycopy(pos, 0, fmap, 0, n1 + n2); 79 | 80 | for (int i = 0; i < pos.length; pos[i++] += 2); 81 | pos = radix_sort(ns, pos); 82 | for (int i = 0; i < pos.length; pos[i++]--); 83 | pos = radix_sort(ns, pos); 84 | for (int i = 0; i < pos.length; pos[i++]--); 85 | pos = radix_sort(ns, pos); 86 | 87 | // now relabel strings 88 | int p0 = -1, p1 = -1, p2 = -1, cidx = 0; 89 | int[] rs = new int[n1 + n2]; 90 | for (int i = 0; i < pos.length; i++) { 91 | if (ns[pos[i]] != p0 || ns[pos[i] + 1] != p1 || ns[pos[i] + 2] != p2) { 92 | p0 = ns[pos[i]]; 93 | p1 = ns[pos[i] + 1]; 94 | p2 = ns[pos[i] + 2]; 95 | rs[bmap[pos[i]]] = cidx++; 96 | } else { 97 | rs[bmap[pos[i]]] = cidx - 1; 98 | } 99 | } 100 | 101 | int[] rSA = new int[n1 + n2]; 102 | if (cidx == n1 + n2) { 103 | System.arraycopy(pos, 0, rSA, 0, n1 + n2); 104 | } else { 105 | int[] r = suffix_array(rs); 106 | for (int i = 0; i < rSA.length; i++) 107 | rSA[i] = fmap[r[i]]; 108 | } 109 | 110 | int[] rank = new int[N + 3]; 111 | for (int i = 0; i < rSA.length; i++) 112 | rank[rSA[i]] = i + 1; 113 | 114 | int[] pos0 = new int[n0]; 115 | int qidx = 0; 116 | for (int i = 0; i < rSA.length; i++) 117 | if (rSA[i] % 3 == 1) 118 | pos0[qidx++] = rSA[i] - 1; 119 | pos0 = radix_sort(s, pos0); 120 | 121 | int[] ret = new int[N]; 122 | int fidx = 0; 123 | for (int i = 0, j = 0; fidx < N;) { 124 | if (j == n1 + n2) 125 | ret[fidx++] = pos0[i++]; 126 | else if (rSA[j] == N) 127 | j++; 128 | else if (i == n0) 129 | ret[fidx++] = rSA[j++]; 130 | else { 131 | if (rSA[j] % 3 == 1) { 132 | if (ns[pos0[i]] < ns[rSA[j]] 133 | || (ns[pos0[i]] == ns[rSA[j]] && rank[pos0[i] + 1] < rank[rSA[j] + 1])) 134 | ret[fidx++] = pos0[i++]; 135 | else 136 | ret[fidx++] = rSA[j++]; 137 | } else { 138 | if (ns[pos0[i]] < ns[rSA[j]] 139 | || (ns[pos0[i]] == ns[rSA[j]] && ns[pos0[i] + 1] < ns[rSA[j] + 1]) 140 | || (ns[pos0[i]] == ns[rSA[j]] && ns[pos0[i] + 1] == ns[rSA[j] + 1] && rank[pos0[i] + 2] < rank[rSA[j] + 2])) 141 | ret[fidx++] = pos0[i++]; 142 | else 143 | ret[fidx++] = rSA[j++]; 144 | } 145 | } 146 | } 147 | 148 | return ret; 149 | } 150 | 151 | private static int[][] createMaps(String s) { 152 | int N = s.length(); 153 | char[] c = s.toCharArray(); 154 | 155 | int[] fmap = new int[K], bmap = new int[K]; 156 | for (int i = 0; i < N; i++) 157 | fmap[toInt(c[i])]++; 158 | 159 | for (int i = 0, idx = 0; i < K; i++) 160 | if (fmap[i] > 0) { 161 | fmap[i] = idx; 162 | bmap[idx++] = i; 163 | } 164 | 165 | int[] arr = new int[N]; 166 | for (int i = 0; i < N; i++) 167 | arr[i] = fmap[toInt(s.charAt(i))]; 168 | 169 | return new int[][] {arr, bmap}; 170 | } 171 | 172 | private static int[] inverse_BWT(int[] s) { 173 | int N = s.length; 174 | int[] pos = new int[N]; 175 | for (int i = 0; i < N; i++) 176 | pos[i] = i; 177 | 178 | pos = radix_sort(s, pos); 179 | 180 | int[] res = new int[N]; 181 | for (int i = 0, cur = pos[pos[0]]; i < N; res[i] = s[cur], cur = pos[cur], i++); 182 | 183 | return res; 184 | } 185 | 186 | public static String inverse_BWT(String s) { 187 | int N = s.length(); 188 | int[][] c = createMaps(s); 189 | int[] b = inverse_BWT(c[0]); 190 | 191 | char[] ret = new char[N]; 192 | for (int i = 0; i < N; i++) 193 | ret[i] = toChar(c[1][b[i]]); 194 | return new String(ret); 195 | } 196 | 197 | public static String BWT(String s) { 198 | int N = s.length(); 199 | int[] pos = suffix_array(createMaps(s)[0]); 200 | char[] ret = new char[N]; 201 | for (int i = 0; i < N; i++) 202 | ret[i] = s.charAt(pos[i] == 0 ? N - 1 : pos[i] - 1); 203 | return new String(ret); 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /src/String/KnuthMorrisPratt.java: -------------------------------------------------------------------------------- 1 | package String; 2 | 3 | /** 4 | * Implementation of Knuth-Morris-Pratt 5 | * 6 | * See http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm 7 | * 8 | * @author Lewin 9 | * 10 | */ 11 | public class KnuthMorrisPratt { 12 | private static int KMP(String text, String word) { 13 | char[] a = text.toCharArray(), b = word.toCharArray(); 14 | int[] T = new int[a.length + b.length]; 15 | 16 | int pos = 2, cnd = 0; 17 | T[0] = -1; 18 | T[1] = 0; 19 | while (pos < b.length) { 20 | if (b[pos - 1] == b[cnd]) { 21 | cnd++; 22 | T[pos] = cnd; 23 | pos++; 24 | } else if (cnd > 0) 25 | cnd = T[cnd]; 26 | else { 27 | T[pos] = 0; 28 | pos++; 29 | } 30 | } 31 | 32 | int m = 0, i = 0; 33 | while (m + i < a.length) { 34 | if (b[i] == a[m + i]) { 35 | if (i == b.length - 1) 36 | return m; 37 | i++; 38 | } else { 39 | m += i - T[i]; 40 | if (T[i] > -1) 41 | i = T[i]; 42 | else 43 | i = 0; 44 | } 45 | } 46 | return a.length; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/String/SuffixArray.java: -------------------------------------------------------------------------------- 1 | package String; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * O(n log n) suffix array O(n) longest common prefix 7 | * 8 | * @author Lewin 9 | * 10 | */ 11 | public class SuffixArray { 12 | 13 | private static int[] suffix_array(char[] s) { 14 | int n = s.length; 15 | int[] id = new int[n]; 16 | for (int i = 0; i < n; i++) 17 | id[i] = s[i] - 'a'; 18 | 19 | for (int k = 1; k <= n; k <<= 1) { 20 | Triplet[] elem = new Triplet[n]; 21 | for (int i = 0; i < n; i++) 22 | elem[i] = new Triplet(id[i], (i + k < n) ? id[i + k] : -1, i); 23 | Arrays.sort(elem); 24 | int cur = -1; 25 | for (int i = 0; i < n; i++) { 26 | if (i == 0 || !(elem[i].a == elem[i - 1].a && elem[i].b == elem[i - 1].b)) 27 | cur++; 28 | id[elem[i].c] = cur; 29 | } 30 | } 31 | 32 | return id; 33 | } 34 | 35 | private static int[] lcp(char[] A, int[] order, int[] rank) { 36 | int n = order.length; 37 | int[] height = new int[n]; 38 | 39 | int h = 0; 40 | for (int i = 0; i < n; i++) { 41 | if (order[i] > 0) { 42 | int j = rank[order[i] - 1]; 43 | while (i + h < n && j + h < n && A[i + h] == A[j + h]) 44 | h++; 45 | height[order[i]] = h; 46 | if (h > 0) 47 | h--; 48 | } 49 | } 50 | 51 | return height; 52 | } 53 | 54 | static class Triplet implements Comparable { 55 | public int a, b, c; 56 | 57 | public Triplet(int _a, int _b, int _c) { 58 | a = _a; 59 | b = _b; 60 | c = _c; 61 | } 62 | 63 | public int compareTo(Triplet other) { 64 | return (a == other.a) ? b - other.b : a - other.a; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/String/SuffixTree.java: -------------------------------------------------------------------------------- 1 | package String; 2 | 3 | public class SuffixTree { 4 | static String alphabet = "abcdefghijklmnopqrstuvwxyz12"; 5 | static int alphabetSize = alphabet.length(); 6 | 7 | static class Node { 8 | int depth; // from start of suffix 9 | int begin; 10 | int end; 11 | Node[] children; 12 | Node parent; 13 | Node suffixLink; 14 | int mask; 15 | boolean mark; 16 | 17 | Node(int begin, int end, int depth, Node parent) { 18 | children = new Node[alphabetSize]; 19 | this.begin = begin; 20 | this.end = end; 21 | this.parent = parent; 22 | this.depth = depth; 23 | mask = 0; 24 | mark = false; 25 | } 26 | 27 | boolean contains(int d) { 28 | return depth <= d && d < depth + (end - begin); 29 | } 30 | } 31 | 32 | public static Node buildSuffixTree(String s) { 33 | int n = s.length(); 34 | byte[] a = new byte[n]; 35 | for (int i = 0; i < n; i++) { 36 | a[i] = (byte) alphabet.indexOf(s.charAt(i)); 37 | } 38 | Node root = new Node(0, 0, 0, null); 39 | Node cn = root; 40 | // root.suffixLink must be null, but that way it gets more convenient 41 | // processing 42 | root.suffixLink = root; 43 | Node needsSuffixLink = null; 44 | int lastRule = 0; 45 | int j = 0; 46 | for (int i = -1; i < n - 1; i++) {// strings s[j..i] already in tree, 47 | // add s[i+l] to it. 48 | int cur = a[i + 1]; // last char of current string 49 | for (; j <= i + 1; j++) { 50 | int curDepth = i + 1 - j; 51 | if (lastRule != 3) { 52 | cn = cn.suffixLink != null ? cn.suffixLink : cn.parent.suffixLink; 53 | int k = j + cn.depth; 54 | while (curDepth > 0 && !cn.contains(curDepth - 1)) { 55 | k += cn.end - cn.begin; 56 | cn = cn.children[a[k]]; 57 | } 58 | } 59 | if (!cn.contains(curDepth)) { // explicit node 60 | if (needsSuffixLink != null) { 61 | needsSuffixLink.suffixLink = cn; 62 | needsSuffixLink = null; 63 | } 64 | if (cn.children[cur] == null) { 65 | // no extension - add leaf 66 | cn.children[cur] = new Node(i + 1, n, curDepth, cn); 67 | lastRule = 2; 68 | } else { 69 | cn = cn.children[cur]; 70 | lastRule = 3; // already exists 71 | break; 72 | } 73 | } else { // implicit node 74 | int end = cn.begin + curDepth - cn.depth; 75 | if (a[end] != cur) { // split implicit node here 76 | Node newn = new Node(cn.begin, end, cn.depth, cn.parent); 77 | newn.children[cur] = new Node(i + 1, n, curDepth, newn); 78 | newn.children[a[end]] = cn; 79 | cn.parent.children[a[cn.begin]] = newn; 80 | if (needsSuffixLink != null) { 81 | needsSuffixLink.suffixLink = newn; 82 | } 83 | cn.begin = end; 84 | cn.depth = curDepth; 85 | cn.parent = newn; 86 | cn = needsSuffixLink = newn; 87 | lastRule = 2; 88 | } else if (cn.end != n || cn.begin - cn.depth < j) { 89 | lastRule = 3; 90 | break; 91 | } else { 92 | lastRule = 1; 93 | } 94 | } 95 | } 96 | } 97 | root.suffixLink = null; 98 | return root; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /src/String/ZAlgorithm.java: -------------------------------------------------------------------------------- 1 | package String; 2 | 3 | public class ZAlgorithm { 4 | public int[] zAlgorithm(char[] let) { 5 | int N = let.length; 6 | int[] z = new int[N]; 7 | int L = 0, R = 0; 8 | for (int i = 1; i < N; i++) { 9 | if (i > R) { 10 | L = R = i; 11 | while (R < N && let[R - L] == let[R]) 12 | R++; 13 | z[i] = R - L; 14 | R--; 15 | } else { 16 | int k = i - L; 17 | if (z[k] < R - i + 1) 18 | z[i] = z[k]; 19 | else { 20 | L = i; 21 | while (R < N && let[R - L] == let[R]) 22 | R++; 23 | z[i] = R - L; 24 | R--; 25 | } 26 | } 27 | } 28 | z[0] = N; 29 | return z; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Trees/BinaryIndexedTrees.java: -------------------------------------------------------------------------------- 1 | package Trees; 2 | 3 | /** 4 | * Given a list of N numbers in a row, we can use this structure for exactly 1 of 2 uses: a) range 5 | * query, point update b) range update, point query 6 | * 7 | * For more info, see: 8 | * http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=binaryIndexedTrees 9 | * 10 | * @author Lewin 11 | */ 12 | public class BinaryIndexedTrees { 13 | private static int[] tree; 14 | private static int N; 15 | 16 | private static int query(int K) { 17 | int sum = 0; 18 | for (int i = K; i > 0; i -= (i & -i)) 19 | sum += tree[i]; 20 | return sum; 21 | } 22 | 23 | private static void update(int K, int val) { 24 | for (int i = K; i <= N; i += (i & -i)) 25 | tree[i] += val; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Trees/HeavyLightTree.java: -------------------------------------------------------------------------------- 1 | package Trees; 2 | 3 | import java.util.Arrays; 4 | 5 | public class HeavyLightTree { 6 | public static int MAXN = 10000; 7 | static { 8 | size = new int[MAXN]; 9 | cp = new int[MAXN]; 10 | depth = new int[MAXN]; 11 | anc = new int[15][MAXN]; 12 | bestchild = new int[MAXN]; 13 | whchain = new int[MAXN]; 14 | chainhead = new int[MAXN]; 15 | index = new int[MAXN]; 16 | chains = new int[MAXN]; 17 | emp = new Edge[MAXN]; 18 | g = new Graph(MAXN, MAXN - 1); 19 | } 20 | 21 | static class Graph { 22 | public int[] eadj, eprev, elast, ecost; 23 | public int eidx; 24 | 25 | public Graph(int N, int M) { 26 | eadj = new int[2 * M]; 27 | eprev = new int[2 * M]; 28 | ecost = new int[2 * M]; 29 | elast = new int[N]; 30 | reset(); 31 | } 32 | 33 | public void reset() { 34 | Arrays.fill(elast, -1); 35 | eidx = 0; 36 | } 37 | 38 | public void addEdge(int a, int b, int c) { 39 | eadj[eidx] = b; 40 | ecost[eidx] = c; 41 | eprev[eidx] = elast[a]; 42 | elast[a] = eidx++; 43 | eadj[eidx] = a; 44 | ecost[eidx] = c; 45 | eprev[eidx] = elast[b]; 46 | elast[b] = eidx++; 47 | } 48 | } 49 | 50 | static class Edge { 51 | public int a, b; 52 | 53 | public Edge(int a, int b) { 54 | this.a = a; 55 | this.b = b; 56 | } 57 | 58 | @Override 59 | public int hashCode() { 60 | return a * 10000 + b; 61 | } 62 | 63 | @Override 64 | public boolean equals(Object other) { 65 | if (!(other instanceof Edge)) 66 | return false; 67 | return ((Edge) other).a == a && ((Edge) other).b == b; 68 | } 69 | } 70 | 71 | public static int[] arr; 72 | 73 | static class SegmentTree { 74 | public int start, end, max; 75 | public SegmentTree left, right; 76 | 77 | public SegmentTree(int start, int end) { 78 | this.start = start; 79 | this.end = end; 80 | if (start == end) { 81 | max = arr[start]; 82 | } else { 83 | int mid = (start + end) >> 1; 84 | left = new SegmentTree(start, mid); 85 | right = new SegmentTree(mid + 1, end); 86 | max = Math.max(left.max, right.max); 87 | } 88 | } 89 | 90 | public void update(int pos, int val) { 91 | if (start == pos && end == pos) { 92 | max = val; 93 | return; 94 | } 95 | int mid = (start + end) >> 1; 96 | if (mid >= pos) 97 | left.update(pos, val); 98 | else 99 | right.update(pos, val); 100 | max = Math.max(left.max, right.max); 101 | } 102 | 103 | public int query(int s, int e) { 104 | if (start == s && end == e) { 105 | return max; 106 | } 107 | int mid = (start + end) >> 1; 108 | if (mid >= e) 109 | return left.query(s, e); 110 | else if (mid < s) 111 | return right.query(s, e); 112 | else 113 | return Math.max(left.query(s, mid), right.query(mid + 1, e)); 114 | } 115 | } 116 | 117 | public static int N; 118 | public static Graph g; 119 | public static Edge[] emp; 120 | 121 | public static int[] size, cp, depth; 122 | public static int[][] anc; 123 | public static int[] bestchild; 124 | 125 | public static int dfs0(int node, int par) { 126 | anc[0][node] = par; 127 | depth[node] = par == -1 ? 0 : depth[par] + 1; 128 | size[node] = 1; 129 | bestchild[node] = -1; 130 | int max = 0; 131 | for (int e = g.elast[node]; e != -1; e = g.eprev[e]) { 132 | int next = g.eadj[e]; 133 | if (next == par) 134 | continue; 135 | cp[next] = g.ecost[e]; 136 | int sizen = dfs0(next, node); 137 | if (sizen > max) { 138 | max = sizen; 139 | bestchild[node] = next; 140 | } 141 | size[node] += sizen; 142 | } 143 | return size[node]; 144 | } 145 | 146 | public static int[] whchain, chainhead, index, chains; 147 | public static int cidx, widx; 148 | 149 | public static void dfs1(int node, int par) { 150 | whchain[node] = widx; 151 | index[node] = cidx; 152 | chains[cidx++] = node; 153 | 154 | if (bestchild[node] == -1) 155 | return; 156 | dfs1(bestchild[node], node); 157 | for (int e = g.elast[node]; e != -1; e = g.eprev[e]) { 158 | int next = g.eadj[e]; 159 | if (next == par || next == bestchild[node]) 160 | continue; 161 | widx++; 162 | chainhead[widx] = next; 163 | dfs1(next, node); 164 | } 165 | } 166 | 167 | public static SegmentTree root; 168 | 169 | public static void init() { 170 | dfs0(0, -1); 171 | for (int i = 1; i < 15; i++) { 172 | for (int j = 0; j < N; j++) { 173 | anc[i][j] = anc[i - 1][j] == -1 ? -1 : anc[i - 1][anc[i - 1][j]]; 174 | } 175 | } 176 | chainhead[0] = 0; 177 | widx = 0; 178 | cidx = 0; 179 | dfs1(0, -1); 180 | arr = new int[cidx]; 181 | for (int i = 0; i < cidx; i++) 182 | arr[i] = cp[chains[i]]; 183 | root = new SegmentTree(0, cidx - 1); 184 | } 185 | 186 | public static int lca(int a, int b) { 187 | if (depth[a] < depth[b]) { 188 | a ^= b; 189 | b ^= a; 190 | a ^= b; 191 | } 192 | 193 | int diff = depth[a] - depth[b]; 194 | for (int i = 0; i < anc.length && diff > 0; i++, diff >>= 1) 195 | if ((diff & 1) != 0) 196 | a = anc[i][a]; 197 | 198 | if (a == b) 199 | return a; 200 | 201 | for (int i = anc.length - 1; i >= 0; i--) 202 | if (anc[i][a] != anc[i][b]) { 203 | a = anc[i][a]; 204 | b = anc[i][b]; 205 | } 206 | 207 | return anc[0][a]; 208 | } 209 | 210 | public static int query_up(int a, int b) { 211 | // a is an ancestor of b 212 | int achain = whchain[a], bchain = whchain[b]; 213 | int ans = 0; 214 | while (achain != bchain) { // try to get them on the same chain 215 | if (b != chainhead[bchain]) 216 | ans = Math.max(ans, root.query(index[chainhead[bchain]], index[b])); 217 | b = anc[0][chainhead[bchain]]; 218 | bchain = whchain[b]; 219 | } 220 | if (a != b) 221 | ans = Math.max(ans, root.query(index[a] + 1, index[b])); 222 | return ans; 223 | } 224 | 225 | public static int query(int a, int b) { 226 | int lca = lca(a, b); 227 | return Math.max(query_up(lca, a), query_up(lca, b)); 228 | } 229 | 230 | public static void update(int x, int c) { 231 | Edge e = emp[x]; 232 | int a = e.a, b = e.b; 233 | if (depth[a] < depth[b]) { 234 | int t = a; 235 | a = b; 236 | b = t; 237 | } 238 | root.update(index[b], c); 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /src/Trees/KDTree.java: -------------------------------------------------------------------------------- 1 | package Trees; 2 | 3 | public class KDTree { 4 | // don't know if this works 5 | static class kd_tree { 6 | public kd_tree Lchild = null, Rchild = null; 7 | public Point[] points; 8 | public int d; 9 | 10 | public kd_tree(Point[] points, int depth) { 11 | this.points = points; 12 | int k = points[0].coord.length; 13 | int N = points.length; 14 | d = depth % k; 15 | 16 | if (N == 1) 17 | return; 18 | 19 | Point[] temp; 20 | int lo = 0, hi = N - 1, comp; 21 | while (true) { 22 | temp = new Point[N]; 23 | comp = points[lo].coord[d]; 24 | int f1 = 0, f2 = N - 1; 25 | for (int i = lo; i <= hi; i++) { 26 | if (points[i].coord[d] < comp) 27 | temp[f1++] = points[i]; 28 | else 29 | temp[f2--] = points[i]; 30 | } 31 | points = temp; 32 | if (f1 == N / 2) 33 | break; 34 | if (f1 < N / 2) 35 | lo = f1; 36 | else 37 | hi = f2; 38 | } 39 | 40 | Point[] first = new Point[N / 2], second = new Point[N - N / 2]; 41 | System.arraycopy(points, 0, first, 0, N / 2); 42 | System.arraycopy(points, N / 2, second, 0, N - N / 2); 43 | Lchild = new kd_tree(first, depth + 1); 44 | Rchild = new kd_tree(second, depth + 1); 45 | } 46 | 47 | } 48 | 49 | static class Point { 50 | public int[] coord; 51 | 52 | public Point(int[] coord) { 53 | this.coord = coord; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Trees/LazyIntervalTree.java: -------------------------------------------------------------------------------- 1 | package Trees; 2 | 3 | public class LazyIntervalTree { 4 | public int min, max, lazy, start, end; 5 | public LazyIntervalTree child1 = null, child2 = null; 6 | 7 | public LazyIntervalTree(int start, int end) { 8 | this.start = start; 9 | this.end = end; 10 | if (start != end) { 11 | int mid = (start + end) >> 1; 12 | child1 = new LazyIntervalTree(start, mid); 13 | child2 = new LazyIntervalTree(mid + 1, end); 14 | } 15 | } 16 | 17 | public void modify(int val) { 18 | min += val; 19 | max += val; 20 | lazy += val; 21 | } 22 | 23 | public void push() { 24 | if (child1 == null) 25 | return; 26 | child1.modify(lazy); 27 | child2.modify(lazy); 28 | lazy = 0; 29 | } 30 | 31 | public void join() { 32 | if (child1 == null) 33 | return; 34 | min = Math.min(child1.min, child2.min); 35 | max = Math.max(child1.max, child2.max); 36 | } 37 | 38 | public int minQuery(int a, int b) { 39 | if (a <= start && end <= b) 40 | return min; 41 | if (start > b || a > end) 42 | return Integer.MAX_VALUE; 43 | if (child1 == null) 44 | return min; 45 | 46 | push(); 47 | return Math.min(child1.minQuery(a, b), child2.minQuery(a, b)); 48 | } 49 | 50 | public int maxQuery(int a, int b) { 51 | if (a <= start && end <= b) 52 | return max; 53 | if (start > b || a > end) 54 | return -Integer.MAX_VALUE; 55 | if (child1 == null) 56 | return max; 57 | 58 | push(); 59 | return Math.max(child1.maxQuery(a, b), child2.maxQuery(a, b)); 60 | } 61 | 62 | public void updateRange(int a, int b, int val) { 63 | if (a <= start && end <= b) { 64 | modify(val); 65 | return; 66 | } 67 | if (start > b || a > end) 68 | return; 69 | if (child1 == null) 70 | return; 71 | 72 | push(); 73 | child1.updateRange(a, b, val); 74 | child2.updateRange(a, b, val); 75 | join(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/Trees/LazySegmentTree.java: -------------------------------------------------------------------------------- 1 | package Trees; 2 | 3 | public class LazySegmentTree { 4 | public static int[] tree, lazy; 5 | public static final int INF = 1 << 29; 6 | public static int PN, N; 7 | 8 | // PN = 1<<(f(N)) 9 | // f(N): for(i = 0; N>>i > 0; i++) 10 | 11 | private static void modify(int pos, int val) { 12 | tree[pos] += val; 13 | lazy[pos] += val; 14 | } 15 | 16 | private static void push(int pos) { 17 | modify(2 * pos, lazy[pos]); 18 | modify(2 * pos + 1, lazy[pos]); 19 | lazy[pos] = 0; 20 | } 21 | 22 | private static void join(int pos) { 23 | tree[pos] = Math.min(tree[2 * pos], tree[2 * pos + 1]); 24 | } 25 | 26 | private static int query(int pos, int start, int end, int a, int b) { 27 | if (a <= start && end <= b) 28 | return tree[pos]; 29 | if (pos >= PN || start >= b || a >= end) 30 | return INF; 31 | push(pos); 32 | int mid = (start + end) >> 1; 33 | return Math.min(query(2 * pos, start, mid, a, b), query(2 * pos + 1, mid + 1, end, a, b)); 34 | } 35 | 36 | private static void update(int pos, int start, int end, int a, int b, int val) { 37 | if (a <= start && end <= b) { 38 | modify(pos, val); 39 | return; 40 | } 41 | if (pos >= PN || start >= b || a >= end) 42 | return; 43 | push(pos); 44 | int mid = (start + end) >> 1; 45 | update(2 * pos, start, mid, a, b, val); 46 | update(2 * pos + 1, mid + 1, end, a, b, val); 47 | join(pos); 48 | } 49 | 50 | private static void build(int pos, int start, int end) { 51 | if (pos >= PN || start >= N) 52 | return; 53 | int mid = (start + end) >> 1; 54 | build(2 * pos, start, mid); 55 | build(2 * pos + 1, mid + 1, end); 56 | tree[pos] = tree[2 * pos]; 57 | lazy[pos] = 0; 58 | if (mid < N) 59 | tree[pos] = Math.min(tree[pos], tree[2 * pos + 1]); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Trees/LinkCutTree.java: -------------------------------------------------------------------------------- 1 | package Trees; 2 | 3 | public class LinkCutTree { 4 | private static final int INF = 1000000000; 5 | private static final TEdge NULL = new TEdge(null, INF); 6 | 7 | static class TEdge { 8 | public Node n; 9 | public int weight; 10 | 11 | public TEdge(Node n, int weight) { 12 | this.n = n; 13 | this.weight = n == null ? INF : weight; 14 | } 15 | 16 | public String toString() { 17 | return (n == null ? null : n.id) + " " + weight; 18 | } 19 | } 20 | 21 | static class Node { 22 | int id, min; 23 | TEdge left; 24 | TEdge right; 25 | TEdge parent; 26 | boolean flip; 27 | 28 | public Node(int id) { 29 | this.id = id; 30 | this.min = INF; 31 | left = NULL; 32 | right = NULL; 33 | parent = NULL; 34 | } 35 | 36 | public String toString() { 37 | return id + " " + "|L: " + left + " |R: " + right + " |P: " + parent; 38 | } 39 | } 40 | 41 | static void push(Node x) { 42 | if (!x.flip) 43 | return; 44 | x.flip = false; 45 | TEdge t = x.left; 46 | x.left = x.right; 47 | x.right = t; 48 | if (x.left.n != null) 49 | x.left.n.flip = !x.left.n.flip; 50 | if (x.right.n != null) 51 | x.right.n.flip = !x.right.n.flip; 52 | } 53 | 54 | // Whether x is a root of a splay tree 55 | static boolean isRoot(Node x) { 56 | return x.parent.n == null || (x.parent.n.left.n != x && x.parent.n.right.n != x); 57 | } 58 | 59 | static void connect(Node ch, Node p, int weight, boolean leftChild) { 60 | if (leftChild) 61 | p.left = new TEdge(ch, weight); 62 | else 63 | p.right = new TEdge(ch, weight); 64 | 65 | p.min = 66 | Math.min(p.right.n == null ? INF : Math.min(p.right.n.min, p.right.weight), 67 | p.left.n == null ? INF : Math.min(p.left.n.min, p.left.weight)); 68 | 69 | if (ch != null) { 70 | ch.parent = new TEdge(p, weight); 71 | } 72 | } 73 | 74 | // rotate edge (x, x.parent) 75 | static void rotate(Node x) { 76 | Node p = x.parent.n; 77 | Node g = p.parent.n; 78 | boolean isRootP = isRoot(p); 79 | boolean leftChildX = (x == p.left.n); 80 | 81 | TEdge next = leftChildX ? x.right : x.left; 82 | int w1 = p.parent.weight; 83 | int w2 = x.parent.weight; 84 | int w3 = next.n == null ? w2 : next.weight; 85 | connect(next.n, p, w2, leftChildX); 86 | connect(p, x, w3, !leftChildX); 87 | 88 | if (!isRootP) 89 | connect(x, g, w1, p == g.left.n); 90 | else 91 | x.parent = new TEdge(g, w1); 92 | } 93 | 94 | static void splay(Node x) { 95 | while (!isRoot(x)) { 96 | Node p = x.parent.n; 97 | Node g = p.parent.n; 98 | if (!isRoot(p)) 99 | push(g); 100 | push(p); 101 | push(x); 102 | if (!isRoot(p)) 103 | rotate((x == p.left.n) == (p == g.left.n) ? p : x); 104 | rotate(x); 105 | } 106 | push(x); 107 | } 108 | 109 | // Makes node x the root of the virtual tree, and also x is the leftmost 110 | // node in its splay tree 111 | static Node expose(Node x) { 112 | Node last = null; 113 | int lw = INF; 114 | for (Node y = x; y != null; y = y.parent.n) { 115 | splay(y); 116 | y.left = new TEdge(last, lw); 117 | y.min = 118 | Math.min(last == null ? INF : Math.min(last.min, lw), 119 | y.right.n == null ? INF : Math.min(y.right.n.min, y.right.weight)); 120 | last = y; 121 | lw = y.parent.weight; 122 | } 123 | splay(x); 124 | return last; 125 | } 126 | 127 | public static Node findRoot(Node x) { 128 | expose(x); 129 | while (x.right.n != null) { 130 | x = x.right.n; 131 | push(x); 132 | } 133 | return x; 134 | } 135 | 136 | // prerequisite: x and y are in distinct trees 137 | public static void link(Node x, Node y, int idx) { 138 | if (findRoot(x) == findRoot(y)) 139 | throw new RuntimeException("error: x and y are connected"); 140 | expose(x); 141 | x.flip = !x.flip; // evert 142 | x.parent = new TEdge(y, idx); 143 | expose(x); 144 | } 145 | 146 | public static boolean connected(Node x, Node y) { 147 | if (x == y) 148 | return true; 149 | return findRoot(x) == findRoot(y); 150 | } 151 | 152 | public static void cut(Node x, Node y) { 153 | expose(x); 154 | x.flip = !x.flip; // evert 155 | expose(y); 156 | if (y.right.n != x || x.left.n != null || x.right.n != null) 157 | throw new RuntimeException("error: no edge (x,y)"); 158 | y.right.n.parent = NULL; 159 | y.right = NULL; 160 | y.min = y.left.n == null ? INF : Math.min(y.left.weight, y.left.n.min); 161 | } 162 | 163 | static int find(Node x, Node y) { 164 | expose(x); 165 | x.flip = !x.flip; 166 | expose(y); 167 | int res = INF; 168 | Node last = null; 169 | for (Node z = x; z != y; z = z.parent.n) { 170 | if (z.left.n != null && z != last) 171 | res = Math.min(res, Math.min(z.left.weight, z.left.n.min)); 172 | res = Math.min(res, z.parent.weight); 173 | last = z.left.n; 174 | } 175 | return res; 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/Trees/QriorityPueue.java: -------------------------------------------------------------------------------- 1 | package Trees; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Comparator; 5 | import java.util.HashMap; 6 | import java.util.Iterator; 7 | 8 | // A custom heap that is backed by a hashmap and arraylist 9 | public class QriorityPueue { 10 | private int size; 11 | private ArrayList list; 12 | private HashMap pos; 13 | private Comparator comp; 14 | 15 | public QriorityPueue(Comparator comp) { 16 | size = 0; 17 | list = new ArrayList(); 18 | pos = new HashMap(); 19 | this.comp = comp; 20 | } 21 | 22 | public boolean add(E e) { 23 | if (e == null) 24 | throw new NullPointerException(); 25 | list.add(e); 26 | pos.put(e, size); 27 | bubbleUp(size, e); 28 | size++; 29 | return true; 30 | } 31 | 32 | public E poll() { 33 | if (size == 0) 34 | return null; 35 | size--; 36 | E ret = list.get(0); 37 | pos.remove(ret); 38 | E last = list.get(size); 39 | list.remove(size); 40 | if (size != 0) 41 | bubbleDown(0, last); 42 | return ret; 43 | } 44 | 45 | public E peek() { 46 | if (size == 0) 47 | return null; 48 | return list.get(0); 49 | } 50 | 51 | public boolean updateKey(E e) { 52 | Integer ps = pos.get(e); 53 | if (ps == null) 54 | return false; 55 | 56 | // try moving it up and down 57 | bubbleUp(ps, e); 58 | ps = pos.get(e); 59 | bubbleDown(ps, e); 60 | 61 | return true; 62 | } 63 | 64 | public int size() { 65 | return size; 66 | } 67 | 68 | public boolean isEmpty() { 69 | return size == 0; 70 | } 71 | 72 | public boolean remove(E e) { 73 | Integer ps = pos.get(e); 74 | if (ps == null) 75 | return false; 76 | pos.remove(e); 77 | size--; 78 | E last = list.get(size); 79 | if (size != 0) 80 | bubbleDown(ps, last); 81 | return true; 82 | } 83 | 84 | public boolean contains(E e) { 85 | return pos.containsKey(e); 86 | } 87 | 88 | public Iterator iterator() { 89 | return list.iterator(); 90 | } 91 | 92 | private void bubbleUp(int idx, E e) { 93 | while (idx > 0) { 94 | int par = (idx - 1) >> 1; 95 | E toComp = list.get(par); 96 | if (comp.compare(e, toComp) >= 0) // greater than parent 97 | break; 98 | list.set(idx, toComp); 99 | pos.put(toComp, idx); 100 | idx = par; 101 | } 102 | list.set(idx, e); 103 | pos.put(e, idx); 104 | } 105 | 106 | private void bubbleDown(int idx, E e) { 107 | int half = size >> 1; 108 | while (idx < half) { 109 | int next = (idx << 1) + 1, test = next + 1; 110 | E toComp = list.get(next); 111 | // get biggest child 112 | if (test < size && comp.compare(toComp, list.get(test)) > 0) 113 | toComp = list.get(next = test); 114 | if (comp.compare(e, toComp) <= 0) // less than biggest child 115 | break; 116 | list.set(idx, toComp); 117 | pos.put(toComp, idx); 118 | idx = next; 119 | } 120 | list.set(idx, e); 121 | pos.put(e, idx); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/Trees/RangeTree.java: -------------------------------------------------------------------------------- 1 | package Trees; 2 | 3 | public class RangeTree { 4 | public int start, end, num; 5 | public RangeTree child1 = null, child2 = null; 6 | 7 | public RangeTree(int start, int end) { 8 | this.start = start; 9 | this.end = end; 10 | if (start != end) { 11 | child1 = new RangeTree(start, (start + end) / 2); 12 | child2 = new RangeTree((start + end) / 2 + 1, end); 13 | } 14 | } 15 | 16 | public void insert(int ind) { 17 | num++; 18 | if (child1 == null) 19 | return; 20 | if (child1.end >= ind) 21 | child1.insert(ind); 22 | else 23 | child2.insert(ind); 24 | } 25 | 26 | public void delete(int ind) { 27 | num--; 28 | if (child1 == null) 29 | return; 30 | if (child1.end >= ind) 31 | child1.delete(ind); 32 | else 33 | child2.delete(ind); 34 | } 35 | 36 | public int query(int st, int en) { 37 | if (start == st && end == en) 38 | return num; 39 | if (st > child1.end) 40 | return child2.query(st, en); 41 | if (en < child2.start) 42 | return child1.query(st, en); 43 | return child1.query(st, child1.end) + child2.query(child2.start, en); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/Trees/SplayTree.java: -------------------------------------------------------------------------------- 1 | package Trees; 2 | 3 | // from Sedgewick 4 | public class SplayTree, Value> { 5 | 6 | private Node root; 7 | 8 | private class Node { 9 | private Key key; 10 | private Value value; 11 | private Node left, right; 12 | 13 | public Node(Key key, Value value) { 14 | this.key = key; 15 | this.value = value; 16 | } 17 | } 18 | 19 | public boolean contains(Key key) { 20 | return (get(key) != null); 21 | } 22 | 23 | // return value associated with the given key 24 | // if no such value, return null 25 | public Value get(Key key) { 26 | root = splay(root, key); 27 | int cmp = key.compareTo(root.key); 28 | if (cmp == 0) 29 | return root.value; 30 | else 31 | return null; 32 | } 33 | 34 | public void put(Key key, Value value) { 35 | // splay key to root 36 | if (root == null) { 37 | root = new Node(key, value); 38 | return; 39 | } 40 | 41 | root = splay(root, key); 42 | 43 | int cmp = key.compareTo(root.key); 44 | 45 | // Insert new node at root 46 | if (cmp < 0) { 47 | Node n = new Node(key, value); 48 | n.left = root.left; 49 | n.right = root; 50 | root.left = null; 51 | root = n; 52 | } 53 | 54 | // Insert new node at root 55 | else if (cmp > 0) { 56 | Node n = new Node(key, value); 57 | n.right = root.right; 58 | n.left = root; 59 | root.right = null; 60 | root = n; 61 | } 62 | 63 | // It was a duplicate key. Simply replace the value 64 | else if (cmp == 0) { 65 | root.value = value; 66 | } 67 | 68 | } 69 | 70 | public void remove(Key key) { 71 | if (root == null) 72 | return; // empty tree 73 | 74 | root = splay(root, key); 75 | 76 | int cmp = key.compareTo(root.key); 77 | 78 | if (cmp == 0) { 79 | if (root.left == null) { 80 | root = root.right; 81 | } else { 82 | Node x = root.right; 83 | root = root.left; 84 | splay(root, key); 85 | root.right = x; 86 | } 87 | } 88 | 89 | // else: it wasn't in the tree to remove 90 | } 91 | 92 | private Node splay(Node h, Key key) { 93 | if (h == null) 94 | return null; 95 | 96 | int cmp1 = key.compareTo(h.key); 97 | 98 | if (cmp1 < 0) { 99 | if (h.left == null) { 100 | return h; 101 | } 102 | int cmp2 = key.compareTo(h.left.key); 103 | if (cmp2 < 0) { 104 | h.left.left = splay(h.left.left, key); 105 | h = rotateRight(h); 106 | } else if (cmp2 > 0) { 107 | h.left.right = splay(h.left.right, key); 108 | if (h.left.right != null) 109 | h.left = rotateLeft(h.left); 110 | } 111 | 112 | if (h.left == null) 113 | return h; 114 | else 115 | return rotateRight(h); 116 | } 117 | 118 | else if (cmp1 > 0) { 119 | if (h.right == null) { 120 | return h; 121 | } 122 | 123 | int cmp2 = key.compareTo(h.right.key); 124 | if (cmp2 < 0) { 125 | h.right.left = splay(h.right.left, key); 126 | if (h.right.left != null) 127 | h.right = rotateRight(h.right); 128 | } else if (cmp2 > 0) { 129 | h.right.right = splay(h.right.right, key); 130 | h = rotateLeft(h); 131 | } 132 | 133 | if (h.right == null) 134 | return h; 135 | else 136 | return rotateLeft(h); 137 | } 138 | 139 | else 140 | return h; 141 | } 142 | 143 | // height of tree (1-node tree has height 0) 144 | public int height() { 145 | return height(root); 146 | } 147 | 148 | private int height(Node x) { 149 | if (x == null) 150 | return -1; 151 | return 1 + Math.max(height(x.left), height(x.right)); 152 | } 153 | 154 | 155 | public int size() { 156 | return size(root); 157 | } 158 | 159 | private int size(Node x) { 160 | if (x == null) 161 | return 0; 162 | else 163 | return (1 + size(x.left) + size(x.right)); 164 | } 165 | 166 | // right rotate 167 | private Node rotateRight(Node h) { 168 | Node x = h.left; 169 | h.left = x.right; 170 | x.right = h; 171 | return x; 172 | } 173 | 174 | // left rotate 175 | private Node rotateLeft(Node h) { 176 | Node x = h.right; 177 | h.right = x.left; 178 | x.left = h; 179 | return x; 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/Trees/SplayTree2.java: -------------------------------------------------------------------------------- 1 | package Trees; 2 | 3 | public class SplayTree2 { 4 | static class Node { 5 | int size; 6 | Node left; 7 | Node right; 8 | Node parent; 9 | boolean flip; 10 | char id; 11 | 12 | public Node(char id) { 13 | this.id = id; 14 | this.size = 1; 15 | left = null; 16 | right = null; 17 | parent = null; 18 | } 19 | 20 | public String toString() { 21 | return id + " " + size; 22 | } 23 | } 24 | 25 | static void push(Node x) { 26 | if (!x.flip) 27 | return; 28 | x.flip = false; 29 | Node t = x.left; 30 | x.left = x.right; 31 | x.right = t; 32 | if (x.left != null) 33 | x.left.flip = !x.left.flip; 34 | if (x.right != null) 35 | x.right.flip = !x.right.flip; 36 | join(x); 37 | } 38 | 39 | // Whether x is a root of a splay tree 40 | static boolean isRoot(Node x) { 41 | return x.parent == null; 42 | } 43 | 44 | static void connect(Node ch, Node p, boolean leftChild) { 45 | if (leftChild) 46 | p.left = ch; 47 | else 48 | p.right = ch; 49 | join(p); 50 | if (ch != null) { 51 | ch.parent = p; 52 | } 53 | } 54 | 55 | // rotate edge (x, x.parent) 56 | static void rotate(Node x) { 57 | Node p = x.parent; 58 | Node g = p.parent; 59 | boolean isRootP = isRoot(p); 60 | boolean leftChildX = (x == p.left); 61 | 62 | Node next = leftChildX ? x.right : x.left; 63 | connect(next, p, leftChildX); 64 | connect(p, x, !leftChildX); 65 | 66 | if (!isRootP) 67 | connect(x, g, p == g.left); 68 | else 69 | x.parent = g; 70 | } 71 | 72 | static void splay(Node x) { 73 | while (!isRoot(x)) { 74 | Node p = x.parent; 75 | Node g = p.parent; 76 | if (!isRoot(p)) 77 | push(g); 78 | push(p); 79 | push(x); 80 | if (!isRoot(p)) 81 | rotate((x == p.left) == (p == g.left) ? p : x); 82 | rotate(x); 83 | } 84 | push(x); 85 | root = x; 86 | } 87 | 88 | static Node cutLeft(Node x) { 89 | Node ret = x.left; 90 | if (ret != null) { 91 | x.left.parent = null; 92 | x.left = null; 93 | join(x); 94 | } 95 | return ret; 96 | } 97 | 98 | static Node cutRight(Node x) { 99 | Node ret = x.right; 100 | if (ret != null) { 101 | x.right.parent = null; 102 | x.right = null; 103 | join(x); 104 | } 105 | return ret; 106 | } 107 | 108 | static void join(Node x) { 109 | x.size = (x.left == null ? 0 : x.left.size) + (x.right == null ? 0 : x.right.size) + 1; 110 | } 111 | 112 | private static Node getElementAtPosition(Node start, int a) { 113 | Node cur = start; 114 | while (a > 0) { 115 | push(cur); 116 | int sz = (cur.left == null ? 0 : cur.left.size); 117 | if (a <= sz) { 118 | cur = cur.left; 119 | continue; 120 | } 121 | a -= sz + 1; 122 | if (a == 0) 123 | break; 124 | cur = cur.right; 125 | } 126 | splay(cur); 127 | return cur; 128 | } 129 | 130 | private static char getElement(int a) { 131 | return getElementAtPosition(root, a).id; 132 | } 133 | 134 | private static void flip(int a, int b) { 135 | if (a == b) 136 | return; 137 | Node right = getElementAtPosition(root, b); 138 | Node ra = cutRight(right); 139 | Node left = getElementAtPosition(root, a); 140 | Node la = cutLeft(left); 141 | splay(left); 142 | left.flip = !left.flip; 143 | push(left); 144 | connect(ra, left, false); 145 | splay(right); 146 | connect(la, right, true); 147 | } 148 | 149 | private static String s; 150 | 151 | private static Node initRec(int start, int end) { 152 | if (start == end) { 153 | return new Node(s.charAt(start - 1)); 154 | } 155 | int mid = (start + end) >> 1; 156 | Node x = new Node(s.charAt(mid - 1)); 157 | if (start <= mid - 1) 158 | connect(initRec(start, mid - 1), x, true); 159 | if (mid + 1 <= end) 160 | connect(initRec(mid + 1, end), x, false); 161 | return x; 162 | } 163 | 164 | private static Node root; 165 | } 166 | -------------------------------------------------------------------------------- /src/Trees/Tree234.java: -------------------------------------------------------------------------------- 1 | /* Tree234.java */ 2 | 3 | package Trees; 4 | 5 | public class Tree234 { 6 | static class Tree234Node { 7 | int keys, key1, key2, key3; 8 | Tree234Node parent, child1, child2, child3, child4; 9 | 10 | Tree234Node() { 11 | keys = 0; 12 | parent = child1 = child2 = child3 = child4 = null; 13 | } 14 | 15 | Tree234Node(Tree234Node p, int key) { 16 | this(); 17 | keys = 1; 18 | key1 = key; 19 | parent = p; 20 | } 21 | 22 | // returns final position of the key 23 | protected int addKey(int key) { 24 | assert keys < 3; 25 | 26 | switch (keys++) { 27 | case 2: 28 | key3 = key; 29 | if (key3 > key2) 30 | return 3; 31 | key3 = key2; 32 | case 1: 33 | key2 = key; 34 | if (key2 > key1) 35 | return 2; 36 | key2 = key1; 37 | case 0: 38 | key1 = key; 39 | return 1; 40 | } 41 | 42 | throw new RuntimeException(); 43 | } 44 | 45 | // returns the new parent. 46 | protected Tree234Node ejectMiddle() { 47 | assert keys == 3 && (parent == null || parent.keys < 3); 48 | 49 | if (parent == null) 50 | parent = new Tree234Node(); 51 | Tree234Node c1 = new Tree234Node(parent, key1); 52 | c1.updateChild(1, child1); 53 | c1.updateChild(2, child2); 54 | Tree234Node c2 = new Tree234Node(parent, key3); 55 | c2.updateChild(1, child3); 56 | c2.updateChild(2, child4); 57 | 58 | int pos = parent.addKey(key2); 59 | if (pos <= 2) 60 | parent.updateChild(4, parent.child3); 61 | if (pos <= 1) 62 | parent.updateChild(3, parent.child2); 63 | parent.updateChild(pos, c1); 64 | parent.updateChild(pos + 1, c2); 65 | 66 | return parent; 67 | } 68 | 69 | // update this child(num) with child 70 | private void updateChild(int num, Tree234Node child) { 71 | if (child != null) 72 | child.parent = this; 73 | switch (num) { 74 | case 1: 75 | child1 = child; 76 | break; 77 | case 2: 78 | child2 = child; 79 | break; 80 | case 3: 81 | child3 = child; 82 | break; 83 | case 4: 84 | child4 = child; 85 | break; 86 | } 87 | } 88 | 89 | // returns true if this node has the key 90 | public boolean containsKey(int key) { 91 | return key == key1 || (keys > 1 && key == key2) || (keys > 2 && key == key3); 92 | } 93 | 94 | // returns next child according to key 95 | protected Tree234Node next(int key) { 96 | return key < key1 ? child1 : keys == 1 || key < key2 ? child2 97 | : keys == 2 || key < key3 ? child3 : child4; 98 | } 99 | } 100 | 101 | // END Tree234Node 102 | 103 | Tree234Node root; 104 | int size = 0; 105 | 106 | public Tree234() { 107 | root = null; 108 | size = 0; 109 | } 110 | 111 | public boolean find(int key) { 112 | for (Tree234Node cur = root; cur != null; cur = cur.next(key)) 113 | if (cur.containsKey(key)) 114 | return true; 115 | return false; 116 | } 117 | 118 | public void insert(int key) { 119 | if (find(key)) 120 | return; 121 | if (root == null) 122 | root = new Tree234Node(); 123 | 124 | Tree234Node cur; 125 | for (cur = root; cur.keys == 3 || cur.child1 != null; cur = 126 | (cur.keys == 3 ? cur.ejectMiddle() : cur).next(key)); 127 | cur.addKey(key); 128 | 129 | size++; 130 | if (root.parent != null) 131 | root = root.parent; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/out.txt: -------------------------------------------------------------------------------- 1 | package Algebra; 2 | 3 | public class FastFourierTransform { 4 | private Complex [] fft(Complex [] x) { 5 | int N = x.length; 6 | 7 | if (N == 1) return new Complex [] {x[0]}; 8 | Complex [] arr = new Complex [N >> 1]; 9 | for (int i = 0; i < N / 2; i++) 10 | arr [i] = x [2 * i]; 11 | Complex [] even = fft (arr); 12 | 13 | for (int i = 0; i < N / 2; i++) 14 | arr [i] = x [2 * i + 1]; 15 | Complex [] odd = fft(arr); 16 | 17 | Complex [] ret = new Complex [N]; 18 | for (int i = 0; i < N / 2; i++) { 19 | double ang = -2 * i * Math.PI / N; 20 | Complex ai = new Complex(Math.cos(ang), Math.sin(ang)).multiply(odd[i]); 21 | ret[i] = even[i].add(ai); 22 | ret[i + N / 2] = even[i].subtract(ai); 23 | } 24 | 25 | return ret; 26 | } 27 | 28 | public Complex [] ifft (Complex [] x) { 29 | int N = x.length; 30 | Complex [] ret = new Complex [N]; 31 | for (int i = 0; i < N; i++) 32 | ret [i] = x[i].conjugate(); 33 | ret = fft(ret); 34 | for (int i = 0; i < N; i++) 35 | ret [i] = ret[i].conjugate().multiply(1. / N); 36 | return ret; 37 | } 38 | 39 | // performs circular convolution 40 | public Complex[] circonv (Complex [] x, Complex [] y) { 41 | int N = x.length; 42 | Complex [] a = fft(x), b = fft(y); 43 | for (int i = 0; i < N; i++) 44 | a[i] = a[i].multiply(b[i]); 45 | return ifft(a); 46 | } 47 | 48 | // performs linear convolution of x,y 49 | public Complex[] conv (Complex [] x, Complex [] y) { 50 | int N = x.length; 51 | Complex [] a = new Complex [2 * N], 52 | b = new Complex [2 * N]; 53 | for (int i = 0; i < N; i++) { 54 | a[i] = x[i]; 55 | a[i + N] = Complex.ZERO; 56 | 57 | b[i] = y[i]; 58 | b[i + N] = Complex.ZERO; 59 | } 60 | return circonv (a, b); 61 | } 62 | } 63 | package Algebra; 64 | 65 | public class GeneralFFT { 66 | // below FFT code very slightly modified from 67 | // http://nayuki.eigenstate.org/res/free-small-fft-in-multiple-languages/Fft.java 68 | /* 69 | * Computes the discrete Fourier transform (DFT) of the given complex vector, storing the result 70 | * back into the vector. The vector can have any length. This is a wrapper function. 71 | */ 72 | public static void transform(double[] real, double[] imag) { 73 | if (real.length != imag.length) 74 | throw new IllegalArgumentException("Mismatched lengths"); 75 | 76 | int n = real.length; 77 | if (n == 0) 78 | return; 79 | else if ((n & (n - 1)) == 0) // Is power of 2 80 | transformRadix2(real, imag); 81 | else 82 | // More complicated algorithm for aribtrary sizes 83 | transformBluestein(real, imag); 84 | } 85 | 86 | 87 | /* 88 | * Computes the inverse discrete Fourier transform (IDFT) of the given complex vector, storing the 89 | * result back into the vector. The vector can have any length. This is a wrapper function. This 90 | * transform does not perform scaling, so the inverse is not a true inverse. 91 | */ 92 | public static void inverseTransform(double[] real, double[] imag) { 93 | transform(imag, real); 94 | } 95 | 96 | /* 97 | * Computes the discrete Fourier transform (DFT) of the given complex vector, storing the result 98 | * back into the vector. The vector's length must be a power of 2. Uses the Cooley-Tukey 99 | * decimation-in-time radix-2 algorithm. 100 | */ 101 | public static void transformRadix2(double[] real, double[] imag) { 102 | // Initialization 103 | if (real.length != imag.length) 104 | throw new IllegalArgumentException("Mismatched lengths"); 105 | int n = real.length; 106 | if (n <= 1) 107 | return; 108 | int levels = -1; 109 | for (int i = 0; i < 32; i++) { 110 | if (1 << i == n) 111 | levels = i; // Equal to log2(n) 112 | } 113 | if (levels == -1) 114 | throw new IllegalArgumentException("Length is not a power of 2"); 115 | double[] cosTable = new double[n / 2]; 116 | double[] sinTable = new double[n / 2]; 117 | cosTable[0] = 1; 118 | sinTable[0] = 0; 119 | double qc = Math.cos(2 * Math.PI / n), qs = Math.sin(2 * Math.PI / n); 120 | for (int i = 1; i < n / 2; i++) { 121 | cosTable[i] = cosTable[i - 1] * qc - sinTable[i - 1] * qs; 122 | sinTable[i] = sinTable[i - 1] * qc + cosTable[i - 1] * qs; 123 | } 124 | 125 | // Bit-reversed addressing permutation 126 | for (int i = 0; i < n; i++) { 127 | int j = Integer.reverse(i) >>> (32 - levels); 128 | if (j > i) { 129 | double temp = real[i]; 130 | real[i] = real[j]; 131 | real[j] = temp; 132 | temp = imag[i]; 133 | imag[i] = imag[j]; 134 | imag[j] = temp; 135 | } 136 | } 137 | 138 | // Cooley-Tukey decimation-in-time radix-2 FFT 139 | for (int size = 2; size <= n; size *= 2) { 140 | int halfsize = size / 2; 141 | int tablestep = n / size; 142 | for (int i = 0; i < n; i += size) { 143 | for (int j = i, k = 0; j < i + halfsize; j++, k += tablestep) { 144 | double tpre = real[j + halfsize] * cosTable[k] + imag[j + halfsize] * sinTable[k]; 145 | double tpim = -real[j + halfsize] * sinTable[k] + imag[j + halfsize] * cosTable[k]; 146 | real[j + halfsize] = real[j] - tpre; 147 | imag[j + halfsize] = imag[j] - tpim; 148 | real[j] += tpre; 149 | imag[j] += tpim; 150 | } 151 | } 152 | } 153 | } 154 | 155 | 156 | /* 157 | * Computes the discrete Fourier transform (DFT) of the given complex vector, storing the result 158 | * back into the vector. The vector can have any length. This requires the convolution function, 159 | * which in turn requires the radix-2 FFT function. Uses Bluestein's chirp z-transform algorithm. 160 | */ 161 | public static void transformBluestein(double[] real, double[] imag) { 162 | // Find a power-of-2 convolution length m such that m >= n * 2 - 1 163 | int n = real.length; 164 | int m = 1; 165 | while (m < n * 2 - 1) 166 | m *= 2; 167 | 168 | // Trignometric tables 169 | double[] tc = new double[2 * n]; 170 | double[] ts = new double[2 * n]; 171 | tc[0] = 1; 172 | ts[0] = 0; 173 | double qc = Math.cos(Math.PI / n), qs = Math.sin(Math.PI / n); 174 | for (int i = 1; i < 2 * n; i++) { 175 | tc[i] = tc[i - 1] * qc - ts[i - 1] * qs; 176 | ts[i] = ts[i - 1] * qc + tc[i - 1] * qs; 177 | } 178 | double[] cosTable = new double[n]; 179 | double[] sinTable = new double[n]; 180 | for (int i = 0; i < n; i++) { 181 | int j = (int) ((long) i * i % (n * 2)); // This is more accurate than j = i * i 182 | cosTable[i] = tc[j]; 183 | sinTable[i] = ts[j]; 184 | } 185 | 186 | // Temporary vectors and preprocessing 187 | double[] areal = new double[m]; 188 | double[] aimag = new double[m]; 189 | for (int i = 0; i < n; i++) { 190 | areal[i] = real[i] * cosTable[i] + imag[i] * sinTable[i]; 191 | aimag[i] = -real[i] * sinTable[i] + imag[i] * cosTable[i]; 192 | } 193 | double[] breal = new double[m]; 194 | double[] bimag = new double[m]; 195 | breal[0] = cosTable[0]; 196 | bimag[0] = sinTable[0]; 197 | for (int i = 1; i < n; i++) { 198 | breal[i] = breal[m - i] = cosTable[i]; 199 | bimag[i] = bimag[m - i] = sinTable[i]; 200 | } 201 | 202 | // Convolution 203 | double[] creal = new double[m]; 204 | double[] cimag = new double[m]; 205 | convolve(areal, aimag, breal, bimag, creal, cimag); 206 | 207 | // Postprocessing 208 | for (int i = 0; i < n; i++) { 209 | real[i] = creal[i] * cosTable[i] + cimag[i] * sinTable[i]; 210 | imag[i] = -creal[i] * sinTable[i] + cimag[i] * cosTable[i]; 211 | } 212 | } 213 | 214 | /* 215 | * Computes the circular convolution of the given complex vectors. Each vector's length must be 216 | * the same. 217 | */ 218 | public static void convolve(double[] xreal, double[] ximag, double[] yreal, double[] yimag, 219 | double[] outreal, double[] outimag) { 220 | if (xreal.length != ximag.length || xreal.length != yreal.length 221 | || yreal.length != yimag.length || xreal.length != outreal.length 222 | || outreal.length != outimag.length) 223 | throw new IllegalArgumentException("Mismatched lengths"); 224 | 225 | int n = xreal.length; 226 | xreal = xreal.clone(); 227 | ximag = ximag.clone(); 228 | yreal = yreal.clone(); 229 | yimag = yimag.clone(); 230 | 231 | transform(xreal, ximag); 232 | transform(yreal, yimag); 233 | for (int i = 0; i < n; i++) { 234 | double temp = xreal[i] * yreal[i] - ximag[i] * yimag[i]; 235 | ximag[i] = ximag[i] * yreal[i] + xreal[i] * yimag[i]; 236 | xreal[i] = temp; 237 | } 238 | inverseTransform(xreal, ximag); 239 | for (int i = 0; i < n; i++) { // Scaling (because this FFT implementation omits it) 240 | outreal[i] = xreal[i] / n; 241 | outimag[i] = ximag[i] / n; 242 | } 243 | } 244 | } 245 | package Geometry; 246 | 247 | 248 | /** 249 | * Representation of a circle 250 | * @author Lewin 251 | * 252 | */ 253 | import static Geometry.Utils.*; 254 | 255 | public class Circle { 256 | // circle centered at p with radius r 257 | public Point p; 258 | public double r; 259 | 260 | public Circle (double x, double y, double r) { 261 | p = new Point (x, y); 262 | this.r = r; 263 | } 264 | 265 | // finds unique circle from 3 points 266 | public Circle (Point a, Point b, Point c) { 267 | double da1 = 2 * (c.x - a.x); 268 | double da2 = 2 * (c.x - b.x); 269 | double db1 = 2 * (c.y - a.y); 270 | double db2 = 2 * (c.y - b.y); 271 | double dc1 = c.x * c.x - a.x * a.x + c.y * c.y - a.y * a.y; 272 | double dc2 = c.x * c.x - b.x * b.x + c.y * c.y - b.y * b.y; 273 | 274 | double x = 0, y = 0; 275 | if (Math.abs (da1) <= EPS) { 276 | y = dc1 / db1; 277 | x = (dc2 - db2 * y) / da2; 278 | } else { 279 | db2 -= db1 * da2 / da1; 280 | dc2 -= dc1 * da2 / da1; 281 | y = dc2 / db2; 282 | x = (dc1 - db1 * y) / da1; 283 | } 284 | p = new Point (x, y); 285 | r = distance (p, a); 286 | } 287 | 288 | public boolean contains (Point other) { 289 | return distance (other, p) < r; 290 | } 291 | } 292 | package Geometry; 293 | 294 | import java.util.Arrays; 295 | import java.util.Comparator; 296 | import java.util.TreeSet; 297 | /** 298 | * O (n log n) for finding pair of closest points within a set 299 | * @author Lewin 300 | * 301 | */ 302 | public class ClosestPair { 303 | private static State closestPair(Point[] points) { 304 | Arrays.sort (points); 305 | double min = 1e9; 306 | int p1 = -1, p2 = -1; 307 | int left = 0; 308 | 309 | TreeSet curset = new TreeSet ( 310 | new Comparator () { 311 | public int compare (Point a, Point b) { 312 | return (int)(Math.signum (a.y == b.y ? a.x - b.x : a.y - b.y)); 313 | } 314 | }); 315 | 316 | for (Point p : points) { 317 | while (p.x - points [left].x > min) 318 | curset.remove (points [left++]); 319 | for (Point next : curset.subSet ( 320 | new Point (p.x, (int)(p.y - min), 0), 321 | new Point (p.x, (int)(p.y + min), 0))) { 322 | double temp = dist (p, next); 323 | if (temp < min) { 324 | min = temp; 325 | p1 = p.idx; p2 = next.idx; 326 | } 327 | } 328 | curset.add (p); 329 | } 330 | 331 | return new State (p1, p2, min); 332 | } 333 | 334 | private static double dist (Point p1, Point p2) { 335 | return Math.sqrt ((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)); 336 | } 337 | 338 | static class State { 339 | public int p1, p2; 340 | public double dist; 341 | 342 | public State (int p1, int p2, double dist) { 343 | if (p2 < p1) {p2 ^= p1; p1 ^= p2; p2 ^= p1;} 344 | this.p1 = p1; 345 | this.p2 = p2; 346 | this.dist = dist; 347 | } 348 | } 349 | } 350 | package Geometry; 351 | 352 | import static Geometry.Utils.EPS; 353 | import static Geometry.Utils.cross; 354 | 355 | import java.util.Arrays; 356 | import java.util.Comparator; 357 | 358 | 359 | /** 360 | * Convex hull made easy 361 | * 362 | * Adapted from USACO training pages 363 | * 364 | * @author Lewin 365 | */ 366 | public class ConvexHull { 367 | /** 368 | * Given an array of N unsorted points, returns an array of points that make up the convex hull of 369 | * the points in clockwise order 370 | * 371 | * The points are the same objects (NOT copies) 372 | * 373 | * Uses the gift-wrapping algorithm. Runs in O(N log N) time 374 | * 375 | * @param p array of points 376 | * @return array of points in convex hull in order 377 | */ 378 | private static Point[] convexHull(Point[] p) { 379 | int numPoints = p.length; 380 | Point m = new Point(0, 0); 381 | for (int i = 0; i < numPoints; i++) { 382 | m.x += p[i].x / numPoints; 383 | m.y += p[i].y / numPoints; 384 | } 385 | 386 | for (int i = 0; i < numPoints; i++) 387 | p[i].angle = Math.atan2(p[i].y - m.y, p[i].x - m.x); 388 | 389 | Arrays.sort(p, new Comparator() { 390 | public int compare(Point a, Point b) { 391 | return (int) Math.signum(a.angle - b.angle); 392 | } 393 | }); 394 | 395 | Point[] hull = new Point[numPoints]; 396 | hull[0] = p[0]; 397 | hull[1] = p[1]; 398 | 399 | int hullPos = 2; 400 | for (int i = 2; i < numPoints - 1; i++) { 401 | while (hullPos > 1 && cross(hull[hullPos - 2], hull[hullPos - 1], p[i]) < EPS) 402 | hullPos--; 403 | hull[hullPos++] = p[i]; 404 | } 405 | 406 | // add last point 407 | Point p2 = p[numPoints - 1]; 408 | while (hullPos > 1 && cross(hull[hullPos - 2], hull[hullPos - 1], p2) < EPS) 409 | hullPos--; 410 | 411 | int hullStart = 0; 412 | boolean flag = false; 413 | do { 414 | flag = false; 415 | if (hullPos - hullStart >= 2 && cross(hull[hullPos - 1], p2, hull[hullStart]) < EPS) { 416 | p2 = hull[--hullPos]; 417 | flag = true; 418 | } 419 | if (hullPos - hullStart >= 2 && cross(p2, hull[hullStart], hull[hullStart + 1]) < EPS) { 420 | hullStart++; 421 | flag = true; 422 | } 423 | } while (flag); 424 | hull[hullPos++] = p2; 425 | 426 | return Arrays.copyOfRange(hull, hullStart, hullPos); 427 | } 428 | } 429 | package Geometry; 430 | 431 | import static Geometry.Utils.*; 432 | /** 433 | * Representation of a Line 434 | * @author Lewin 435 | * 436 | */ 437 | public class Line { 438 | public double a, b, c; 439 | 440 | // ax + by = c 441 | 442 | /** 443 | * Standard representation 444 | */ 445 | public Line (double a, double b, double c) { 446 | this.a = a; 447 | this.b = b; 448 | this.c = c; 449 | } 450 | 451 | /** 452 | * Unique line between two points 453 | */ 454 | public Line (Point p1, Point p2) { // two points 455 | if (p1.x == p2.x) { 456 | a = 1; 457 | b = 0; 458 | c = -p1.x; 459 | } else { 460 | b = 1; 461 | a = -(p1.y - p2.y) / (p1.x - p2.x); 462 | c = -(a * p1.x) - (b * p1.y); 463 | } 464 | } 465 | 466 | /** 467 | * Point-slope formula 468 | */ 469 | public Line (Point p, double m) { 470 | a = -m; 471 | b = 1; 472 | c = -((a * p.x) + (b * p.y)); 473 | } 474 | 475 | // returns true if line l is parallel to this 476 | public boolean parallel (Line l) { 477 | return (Math.abs (a - l.a) <= EPS && Math.abs (b - l.b) <= EPS); 478 | } 479 | 480 | // tests if two lines describe the same object 481 | public boolean same_line (Line l) { 482 | return (parallel (l) && Math.abs (c - l.c) <= EPS); 483 | } 484 | 485 | // finds intersection point between lines 486 | // if no intersection found, returns null; 487 | // if same line, returns INF, INF point 488 | public Point intersection_point (Line l) { 489 | Point p = new Point (INF, INF); 490 | if (same_line (l)) 491 | return p; 492 | if (parallel (l)) 493 | return null; 494 | 495 | p.x = (l.b * c - b * l.c) / (l.a * b - a * l.b); 496 | if (Math.abs (b) > EPS) 497 | p.y = -(a * p.x + c) / b; 498 | else 499 | p.y = -(l.a * p.x + l.c) / l.b; 500 | return p; 501 | } 502 | 503 | // Finds the point closest to p lying on this line 504 | public Point closest_Point (Point p) { 505 | Point p_c = new Point (INF, INF); 506 | if (Math.abs (b) <= EPS) { 507 | p_c.x = -c; 508 | p_c.y = p.y; 509 | return p_c; 510 | } 511 | if (Math.abs (a) <= EPS) { 512 | p_c.x = p.x; 513 | p_c.y = -c; 514 | return p_c; 515 | } 516 | Line perp = new Line (p, 1 / a); 517 | return intersection_point (perp); 518 | } 519 | } 520 | package Geometry; 521 | 522 | import java.util.*; 523 | import static Geometry.Utils.*; 524 | 525 | /** 526 | * Representation of a Point 527 | * @author Lewin 528 | * 529 | */ 530 | public class Point implements Comparable { 531 | public double x, y, angle; 532 | public int idx; 533 | 534 | public Point (double x, double y) { 535 | this.x = x; 536 | this.y = y; 537 | angle = 0; 538 | } 539 | 540 | public Point (double x, double y, int idx) { 541 | this.x = x; 542 | this.y = y; 543 | this.idx = idx; 544 | } 545 | 546 | public int compareTo (Point other) { 547 | return x == other.x ? (int)Math.signum (y - other.y) : (int)Math.signum (x - other.x); 548 | } 549 | } 550 | package Geometry; 551 | 552 | import static Geometry.Utils.*; 553 | 554 | /** 555 | * Representation of a Segment 556 | * @author Lewin 557 | * 558 | */ 559 | public class Segment { 560 | public Point a, b; 561 | public double length; 562 | 563 | public Segment (Point a, Point b) { 564 | this.a = a; 565 | this.b = b; 566 | length = distance (a, b); 567 | } 568 | 569 | /** 570 | * Returns shortest point distance 571 | * @param c point we are considering 572 | * @return shortest length from c to this segment 573 | */ 574 | public double ptDist (Point c) { 575 | if (dot (a, b, c) > 0) 576 | return distance (b, c); 577 | if (dot (b, a, c) > 0) 578 | return distance (a, c); 579 | if (length == 0) 580 | return distance (a, c); 581 | return Math.abs (cross (a, b, c) / length); 582 | } 583 | 584 | /** 585 | * Returns a point that segment intersects with s 586 | * @param s the segment that we are testing for intersection 587 | * @return A wrapper containting a boolean and a point 588 | * if boolean is true and point is null 589 | * this and s have infinitely many intersections 590 | * if boolean is true and point is not null 591 | * this and s intersect exactly once at point 592 | * if boolean is false (implies point is null) 593 | * this and s do not intersect 594 | */ 595 | public Wrapper segments_intersect (Segment s) { 596 | Line l1 = new Line (a, b), l2 = new Line (s.a, s.b); 597 | Point p = new Point (0, 0); 598 | 599 | if (l1.same_line (l2)) 600 | return new Wrapper ( 601 | (point_in_box (a, s.a, s.b) || point_in_box (b, s.a, s.b) 602 | || point_in_box (s.a, a, b) || point_in_box (s.b, a, b)), 603 | null); 604 | 605 | if (l1.parallel (l2)) 606 | return new Wrapper (false, null); 607 | 608 | p = l1.intersection_point (l2); 609 | 610 | return new Wrapper ((point_in_box (p, a, b) && point_in_box (p, s.a, 611 | s.b)), p); 612 | } 613 | 614 | static class Wrapper { 615 | public boolean state; 616 | public Point p; 617 | 618 | public Wrapper (boolean _state, Point _p) { 619 | state = _state; 620 | p = _p; 621 | } 622 | } 623 | } 624 | package Geometry; 625 | 626 | /** 627 | * Useful functions 628 | * @author Lewin 629 | * 630 | */ 631 | public class Utils { 632 | public static final double EPS = 1e-9; 633 | public static final int INF = Integer.MAX_VALUE >> 2; 634 | 635 | // returns dot product of |a-b|*|b-c| 636 | public static double dot (Point a, Point b, Point c) { 637 | Point ab = new Point (b.x - a.x, b.y - a.y); 638 | Point bc = new Point (c.x - b.x, c.y - b.y); 639 | return ab.x * bc.x + ab.y * bc.y; 640 | } 641 | 642 | // return cross product of |b-a|x|c-a| 643 | public static double cross (Point a, Point b, Point c) { 644 | Point ab = new Point (b.x - a.x, b.y - a.y); 645 | Point ac = new Point (c.x - a.x, c.y - a.y); 646 | return ab.x * ac.y - ab.y * ac.x; 647 | } 648 | 649 | // returns if a,b,c are colinear 650 | public static boolean colinear (Point a, Point b, Point c) { 651 | return (a.x - b.x) * (a.y - c.y) == (a.x - c.x) * (a.y - b.y); 652 | } 653 | 654 | // returns distance between points a, and b 655 | public static double distance (Point a, Point b) { 656 | return Math.hypot(a.x - b.x, a.y - b.y); 657 | } 658 | 659 | // returns true iff p lies in box with opposite corners b1, b2 660 | public static boolean point_in_box (Point p, Point b1, Point b2) { 661 | return ((p.x >= Math.min (b1.x, b2.x)) && (p.x <= Math.max (b1.x, b2.x)) 662 | && (p.y >= Math.min (b1.y, b2.y)) && (p.y <= Math.max (b1.y, b2.y))); 663 | } 664 | } 665 | package Graph.Algorithms; 666 | import static Graph.Representation.LinkedList.N; 667 | import static Graph.Representation.LinkedList.eadj; 668 | import static Graph.Representation.LinkedList.ecost; 669 | import static Graph.Representation.LinkedList.elast; 670 | import static Graph.Representation.LinkedList.eprev; 671 | import java.util.Arrays; 672 | 673 | public class LowestCommonAncestor { 674 | private static int root; 675 | private static int [] depth, queue; 676 | private static int [][] anc; 677 | 678 | private static void init () { 679 | Arrays.fill (depth, 1 << 29); // INF 680 | 681 | int front = 0, back = 0; 682 | depth[root] = 0; 683 | queue[back++] = root; 684 | anc[0][root] = -1; 685 | 686 | while (front != back) { 687 | int node = queue[front++]; 688 | for (int e = elast[node]; e != -1; e = eprev[e]) 689 | if (depth[node] + ecost[e] < depth[eadj[e]]) { 690 | depth[eadj[e]] = depth[node] + ecost[e]; 691 | anc[0][eadj[e]] = node; 692 | queue[back++] = eadj[e]; 693 | }// depth [i] is distance from root to i 694 | // anc [0][i] is the first ancestor of i 695 | } 696 | 697 | for (int k = 1; 1 << k < N; k++) 698 | for (int i = 0; i < N; i++) 699 | anc[k][i] = anc[k - 1][i] == -1 ? -1 : anc[k - 1][anc[k - 1][i]]; 700 | } 701 | 702 | private static int lca (int a, int b) { 703 | if (depth[a] < depth[b]) { 704 | a ^= b; 705 | b ^= a; 706 | a ^= b; 707 | } 708 | 709 | // make depth [a] = depth [b] with binary search 710 | int diff = depth[a] - depth[b]; 711 | for (int i = 0; 1 << i <= diff; i++) 712 | if (((diff) & 1 << i) != 0) 713 | a = anc[i][a]; 714 | 715 | if (a == b) 716 | return a; 717 | 718 | int log = 0; 719 | while (1 << (log + 1) <= depth[a]) 720 | log++; 721 | 722 | // another binary search 723 | for (int i = log; i >= 0; i--) 724 | if (anc[i][a] != anc[i][b]) { 725 | a = anc[i][a]; 726 | b = anc[i][b]; 727 | } 728 | 729 | return anc[0][a]; 730 | } 731 | 732 | private static int dist (int a, int b) { 733 | return depth[a] + depth[b] - 2 * depth[lca (a, b)]; 734 | } 735 | } 736 | package Graph.Algorithms; 737 | 738 | import java.util.Arrays; 739 | 740 | public class MaximumMatching { 741 | private static int N; 742 | private static boolean [][] grid; 743 | 744 | private static void addEdge (int a, int b) { 745 | grid[a][b] = grid[b][a] = true; 746 | } 747 | 748 | private static int [] match, queue, pre, base; 749 | private static boolean [] hash, blossom; 750 | 751 | private static int maximum_matching () { 752 | pre = new int [N]; 753 | base = new int [N]; 754 | queue = new int [N]; 755 | hash = new boolean [N]; 756 | blossom = new boolean [N]; 757 | match = new int [N]; 758 | Arrays.fill (match, -1); 759 | int ans = 0; 760 | for (int i = 0; i < N; i++) 761 | if (match[i] == -1) 762 | ans += bfs (i); 763 | return ans; 764 | } 765 | 766 | private static int bfs (int p) { 767 | Arrays.fill (pre, -1); 768 | Arrays.fill (hash, false); 769 | for (int i = 0; i < N; i++) 770 | base[i] = i; 771 | int front = 0, back = 0; 772 | queue[back++] = p; 773 | while (front < back) { 774 | int u = queue[front++]; 775 | for (int v = 0; v < N; v++) { 776 | if (grid[u][v] && base[u] != base[v] && v != match[u]) { 777 | if (v == p || (match[v] != -1 && pre[match[v]] != -1)) { 778 | int b = contract (u, v); 779 | for (int i = 0; i < N; i++) { 780 | if (blossom[base[i]]) { 781 | base[i] = b; 782 | if (!hash[i]) { 783 | hash[i] = true; 784 | queue[back++] = i; 785 | } 786 | } 787 | } 788 | } else if (pre[v] == -1) { 789 | pre[v] = u; 790 | if (match[v] == -1) { 791 | augment (v); 792 | return 1; 793 | } else { 794 | queue[back++] = match[v]; 795 | hash[match[v]] = true; 796 | } 797 | } 798 | } 799 | } 800 | } 801 | return 0; 802 | } 803 | 804 | private static void augment (int u) { 805 | while (u != -1) { 806 | int v = pre[u], k = match[v]; 807 | match[u] = v; 808 | match[v] = u; 809 | u = k; 810 | } 811 | } 812 | 813 | private static int contract (int u, int v) { 814 | Arrays.fill (blossom, false); 815 | int b = find_base (base[u], base[v]); 816 | change_blossom (b, u); 817 | change_blossom (b, v); 818 | if (base[u] != b) 819 | pre[u] = v; 820 | if (base[v] != b) 821 | pre[v] = u; 822 | return b; 823 | } 824 | 825 | private static void change_blossom (int b, int u) { 826 | while (base[u] != b) { 827 | int v = match[u]; 828 | blossom[base[v]] = blossom[base[u]] = true; 829 | u = pre[v]; 830 | if (base[u] != b) 831 | pre[u] = v; 832 | } 833 | } 834 | 835 | private static int find_base (int u, int v) { 836 | boolean [] in_path = new boolean [N]; 837 | while (true) { 838 | in_path[u] = true; 839 | if (match[u] == -1) 840 | break; 841 | u = base[pre[match[u]]]; 842 | } 843 | while (!in_path[v]) 844 | v = base[pre[match[v]]]; 845 | return v; 846 | } 847 | } 848 | package Graph.Algorithms.NetworkFlow; 849 | 850 | import java.util.Arrays; 851 | import static Graph.Representation.LinkedList.*; 852 | public class Dinic { 853 | private static int [] flow, capa, now; 854 | 855 | // notice new addEdge method 856 | // directed flow (even though we add two edges) 857 | private static void add_edge (int a, int b, int c) { 858 | eadj[eidx] = b; flow[eidx] = 0; capa[eidx] = c; eprev[eidx] = elast[a]; elast[a] = eidx++; 859 | eadj[eidx] = a; flow[eidx] = c; capa[eidx] = c; eprev[eidx] = elast[b]; elast[b] = eidx++; 860 | } 861 | 862 | private static int dinic (int source, int sink) { 863 | int res, flow = 0; 864 | while (bfs (source, sink)) { // see if there is an augmenting path 865 | System.arraycopy (elast, 0, now, 0, N); 866 | while ((res = dfs (source, INF, sink)) > 0) // push all possible flow through 867 | flow += res; 868 | } 869 | return flow; 870 | } 871 | 872 | private static int [] level; 873 | 874 | private static boolean bfs (int source, int sink) { 875 | Arrays.fill (level, -1); 876 | int front = 0, back = 0; 877 | int [] queue = new int [N]; 878 | 879 | level[source] = 0; 880 | queue[back++] = source; 881 | 882 | while (front < back && level[sink] == -1) { 883 | int node = queue[front++]; 884 | for (int e = elast[node]; e != -1; e = eprev[e]) { 885 | int to = eadj[e]; 886 | if (level[to] == -1 && flow[e] < capa[e]) { 887 | level[to] = level[node] + 1; 888 | queue[back++] = to; 889 | } 890 | } 891 | } 892 | 893 | return level[sink] != -1; 894 | } 895 | 896 | private static int dfs (int cur, int curflow, int goal) { 897 | if (cur == goal) 898 | return curflow; 899 | 900 | for (int e = now[cur]; e != -1; now[cur] = e = eprev[e]) { 901 | if (level[eadj[e]] > level[cur] && flow[e] < capa[e]) { 902 | int res = dfs (eadj[e], Math.min (curflow, capa[e] - flow[e]), goal); 903 | if (res > 0) { 904 | flow[e] += res; 905 | flow[e ^ 1] -= res; 906 | return res; 907 | } 908 | } 909 | } 910 | return 0; 911 | } 912 | } 913 | package Graph.Algorithms.NetworkFlow; 914 | import static Graph.Representation.AdjacencyMatrix.*; 915 | public class FordFulkerson { 916 | private static int networkFlow (int source, int sink) { 917 | if (source == sink) 918 | return INF; 919 | 920 | int totalFlow = 0; 921 | int [][] cap = new int [N][N]; // don't want to alter original array 922 | for (int i = 0; i < N; i++) 923 | // if you do want to alter it, change input from grid to cap 924 | System.arraycopy (grid[i], 0, cap[i], 0, N); // get rid of these three 925 | // lines 926 | 927 | while (true) { // while there exists an augmenting path 928 | int [] prev = new int [N], flow = new int [N]; 929 | boolean [] visited = new boolean [N]; 930 | int [] queue = new int [N]; 931 | int front = 0, back = 0; 932 | 933 | queue[back++] = source; 934 | visited[source] = true; 935 | flow[source] = INF; 936 | boolean success = false; 937 | 938 | // find the path 939 | outer : while (front != back) { 940 | int node = queue[front++]; 941 | 942 | for (int i = 0; i < N; i++) 943 | if (!visited[i] && cap[node][i] > 0) { 944 | prev[i] = node; 945 | flow[i] = Math.min (flow[node], cap[node][i]); 946 | visited[i] = true; 947 | 948 | if (i == sink) { 949 | success = true; 950 | break outer; 951 | } 952 | 953 | queue[back++] = i; 954 | } 955 | } 956 | if (!success) 957 | break; 958 | 959 | // push flow through 960 | int pathCap = flow[sink]; 961 | totalFlow += pathCap; 962 | 963 | for (int x = sink; x != source; x = prev[x]) { 964 | cap[prev[x]][x] -= pathCap; 965 | cap[x][prev[x]] += pathCap; 966 | } 967 | } 968 | 969 | return totalFlow; 970 | } 971 | } 972 | package Graph.Algorithms.NetworkFlow; 973 | 974 | import java.util.Arrays; 975 | import static Graph.Representation.AdjacencyMatrix.*; 976 | public class MinCostMaxFlow { 977 | private static int [][] cap, cost; 978 | private static int [] pot; 979 | 980 | // add an edge from x to y with capacity w and cost c 981 | private static void addEdge (int x, int y, int w, int c) { 982 | cap[x][y] = w; 983 | cost[x][y] = c; 984 | cost[y][x] = -c; 985 | } 986 | 987 | // if we want max cost, take replace c with Q - c, (Q > all c) 988 | // then take Q * flow [0] - flow [1] 989 | private static int [] flow (int source, int sink) { 990 | int ans_flow = 0, ans_cost = 0; 991 | pot = new int [N]; // potential of the node 992 | 993 | while (true) { 994 | boolean [] used = new boolean [N]; 995 | int [] dist = new int [N], prev = new int [N]; 996 | Arrays.fill (dist, INF); 997 | dist[source] = 0; 998 | 999 | while (true) { 1000 | int x = -1; 1001 | for (int i = 0; i < N; i++) 1002 | if (dist[i] != INF && !used[i] && (x == -1 || dist[i] < dist[x])) 1003 | x = i; 1004 | 1005 | if (x == -1) 1006 | break; 1007 | 1008 | used[x] = true; 1009 | for (int i = 0; i < N; i++) 1010 | if (cap[x][i] > 0 1011 | && dist[x] + cost[x][i] + pot[x] - pot[i] < dist[i]) { 1012 | dist[i] = dist[x] + cost[x][i] + pot[x] - pot[i]; 1013 | prev[i] = x; 1014 | } 1015 | } 1016 | 1017 | if (!used[sink]) 1018 | break; 1019 | 1020 | int ansf = INF, ansc = 0; 1021 | for (int x = sink; x != source; x = prev[x]) 1022 | ansf = Math.min (ansf, cap[prev[x]][x]); 1023 | 1024 | ans_flow += ansf; 1025 | for (int x = sink; x != source; x = prev[x]) { 1026 | ansc += cost[prev[x]][x] * ansf; 1027 | cap[prev[x]][x] -= ansf; 1028 | cap[x][prev[x]] += ansf; 1029 | } 1030 | 1031 | for (int i = 0; i < N; i++) 1032 | pot[i] += dist[i]; 1033 | 1034 | ans_flow += ansf; 1035 | ans_cost += ansc; 1036 | } 1037 | 1038 | return new int [] { ans_flow, ans_cost }; 1039 | // returns both flow and cost 1040 | } 1041 | } 1042 | package Graph.Algorithms.ShortestPath; 1043 | 1044 | import static Graph.Representation.EdgeList.*; 1045 | import Graph.Triplet; 1046 | 1047 | public class BellmanFord { 1048 | private static Triplet [] edges; 1049 | 1050 | private static int [] bellman_ford (int [] dist, int start) { 1051 | // IMPORTANT: use this if and only if there are negative path values 1052 | // this is the only way to process them 1053 | int [] prev = new int [N]; 1054 | for (int i = 0; i < N; i++) { 1055 | dist[i] = INF; 1056 | prev[i] = -1; 1057 | } 1058 | 1059 | dist[start] = 0; 1060 | // shortest non-cyclic path is at most length N 1061 | for (int i = 0; i < N; i++) { 1062 | boolean changed = false; 1063 | 1064 | for (int j = 0; j < M; j++) 1065 | if (dist[edges[j].a] + edges[j].c < dist[edges[j].b]) { 1066 | dist[edges[j].b] = dist[edges[j].a] + edges[j].c; 1067 | prev[edges[j].b] = edges[j].a; 1068 | changed = true; 1069 | } 1070 | 1071 | if (!changed) 1072 | break; 1073 | } 1074 | 1075 | // if we can make a path shorter, there exists a negative cycle 1076 | for (int i = 0; i < M; i++) 1077 | if (dist[edges[i].b] > dist[edges[i].a] + edges[i].c) 1078 | return null; // negative cycle 1079 | 1080 | return prev; // no cycles, parent pointers to recreate path 1081 | // replace this with true/false if you don't care about parent pointers 1082 | } 1083 | } 1084 | package Graph.Algorithms.ShortestPath; 1085 | 1086 | import java.util.Arrays; 1087 | import java.util.PriorityQueue; 1088 | import Graph.Triplet; 1089 | import static Graph.Representation.LinkedList.*; 1090 | 1091 | public class Dijkstra { 1092 | private static int [] dijkstra_prev (int [] dist, int start) { 1093 | Arrays.fill (dist, INF); 1094 | int [] prev = new int [N]; 1095 | boolean [] visited = new boolean [N]; 1096 | PriorityQueue pq = new PriorityQueue (); 1097 | pq.add (new Triplet (start, -1, 0)); 1098 | 1099 | while (pq.size () > 0) { 1100 | int node = pq.peek ().a, pre = pq.peek ().b, weight = pq.peek ().c; 1101 | pq.poll (); 1102 | if (visited[node]) 1103 | continue; 1104 | visited[node] = true; 1105 | dist[node] = weight; 1106 | prev[node] = pre; 1107 | 1108 | for (int e = elast[node]; e != -1; e = eprev[e]) 1109 | if (!visited[eadj[e]]) 1110 | pq.add (new Triplet (eadj[e], node, ecost[e] + weight)); 1111 | } 1112 | 1113 | return prev; // parent pointers (in case you want to recreate the path) 1114 | } 1115 | } 1116 | package Graph.Algorithms.ShortestPath; 1117 | public class FloydWarshall { 1118 | private static void floyd_warshall (int [][] dist) { 1119 | int N = dist.length; 1120 | for (int k = 0; k < N; k++) 1121 | for (int i = 0; i < N; i++) 1122 | for (int j = 0; j < N; j++) 1123 | dist[i][j] = Math.min (dist[i][j], dist[i][k] + dist[k][j]); 1124 | // dist [i][j] is the shortest distance from node i to node j 1125 | // if dist [i][j] == INF, then they are not connected 1126 | } 1127 | } 1128 | package Graph.Algorithms; 1129 | 1130 | import java.util.PriorityQueue; 1131 | import static Graph.Representation.LinkedList.*; 1132 | import Graph.Pair; 1133 | 1134 | public class SpanningTree { 1135 | 1136 | // for max spanning tree, add -weight and return -treeCost 1137 | // for product trees, take the log of each weight (log (ab) = log (a) + log (b)) 1138 | private static int minSpanningTree () { // Prim's algorithm 1139 | boolean [] visited = new boolean [N]; 1140 | PriorityQueue pq = new PriorityQueue (); 1141 | int treeCost = 0, treeSize = 0; 1142 | pq.add (new Pair (0, 0)); 1143 | 1144 | while (treeSize < N) { 1145 | int node = pq.peek ().a, weight = pq.peek ().b; 1146 | pq.poll (); 1147 | if (visited[node]) 1148 | continue; 1149 | treeSize++; 1150 | treeCost += weight; 1151 | visited[node] = true; 1152 | 1153 | for (int e = elast[node]; e != -1; e = eprev[e]) 1154 | if (!visited[eadj[e]]) 1155 | pq.add (new Pair (eadj[e], ecost[e])); 1156 | } 1157 | 1158 | return treeCost; 1159 | } 1160 | } 1161 | package Graph.Algorithms; 1162 | 1163 | import java.util.Arrays; 1164 | import static Graph.Representation.LinkedList.*; 1165 | 1166 | public class StronglyConnectedComponents { 1167 | private static int [] part, index, lowlink, stack, size; 1168 | private static int pidx, sidx, ssize; 1169 | private static boolean [] instack; 1170 | 1171 | private static void tarjan() { 1172 | stack = new int [N]; 1173 | index = new int [N]; 1174 | part = new int [N]; 1175 | lowlink = new int [N]; 1176 | instack = new boolean [N]; 1177 | size = new int [N]; 1178 | Arrays.fill (index, -1); 1179 | 1180 | pidx = 0; sidx = 0; ssize = 0; 1181 | for (int i = 0; i < N; i++) 1182 | if (index [i] == -1) 1183 | strongconnect (i); 1184 | } 1185 | 1186 | private static void strongconnect (int node) { 1187 | index [node] = pidx; 1188 | lowlink [node] = pidx; 1189 | pidx++; 1190 | stack [sidx++] = node; 1191 | instack [node] = true; 1192 | 1193 | for (int e = elast [node]; e != -1; e = eprev [e]) { 1194 | if (index [eadj [e]] == -1) { 1195 | strongconnect (eadj [e]); 1196 | if (lowlink [eadj [e]] < lowlink [node]) 1197 | lowlink [node] = lowlink [eadj [e]]; 1198 | } else if (instack [eadj [e]]) { 1199 | if (index [eadj [e]] < lowlink [node]) 1200 | lowlink [node] = index [eadj [e]]; 1201 | } 1202 | } 1203 | 1204 | if (lowlink [node] == index [node]) { 1205 | int cur, csize = 0; 1206 | do { 1207 | cur = stack [--sidx]; 1208 | csize++; 1209 | part [cur] = ssize; 1210 | instack [cur] = false; 1211 | } while (cur != node); 1212 | size [ssize++] = csize; 1213 | } 1214 | } 1215 | } 1216 | package Graph.Algorithms; 1217 | import static Graph.Representation.LinkedList.*; 1218 | 1219 | public class TopologicalSort { 1220 | private static int [] indeg; 1221 | 1222 | // note new addEdge method 1223 | private static void d_addEdge (int a, int b, int c) { // directed + indegrees 1224 | indeg[b]++; eadj[eidx] = b; eprev[eidx] = elast[a]; ecost[eidx] = c; elast[a] = eidx++; 1225 | } 1226 | 1227 | private static boolean toposort (int [] topo) { 1228 | int [] queue = new int [N]; 1229 | int front = 0, back = 0, idx = 0; 1230 | 1231 | // add all nodes with no incoming edges 1232 | for (int i = 0; i < indeg.length; i++) 1233 | if (indeg[i] == 0) 1234 | queue[back++] = i; 1235 | 1236 | while (front != back) { 1237 | int node = queue[front++]; 1238 | topo[idx++] = node; 1239 | 1240 | // expand current node, removing all of its edges 1241 | for (int e = elast[node]; e != -1; e = eprev[e]) 1242 | if (--indeg[eadj[e]] == 0) 1243 | queue[back++] = eadj[e]; 1244 | } 1245 | 1246 | return idx != topo.length; // true if successful, false if not a DAG 1247 | // topo will contain topologically sorted list of nodes 1248 | } 1249 | } 1250 | package Graph; 1251 | 1252 | public class Pair implements Comparable { 1253 | public int a, b; 1254 | public Pair (int a, int b) { 1255 | this.a = a; 1256 | this.b = b; 1257 | } 1258 | 1259 | public int compareTo(Pair other) { 1260 | return b == other.b ? a - other.a : b - other.b; 1261 | } 1262 | } 1263 | package Graph.Representation; 1264 | 1265 | /** 1266 | * 1267 | * @author Lewin 1268 | * 1269 | */ 1270 | public class AdjacencyMatrix implements Graph { 1271 | public static int N; 1272 | public static int [][] grid; 1273 | 1274 | @Override 1275 | public void init(int N, int M) { 1276 | this.N = N; 1277 | grid = new int [N][N]; 1278 | } 1279 | 1280 | @Override 1281 | public void addEdge(int a, int b, int weight) { 1282 | grid [a][b] = weight; 1283 | // if don't want bidirectional, comment out next line 1284 | grid [b][a] = weight; 1285 | } 1286 | 1287 | } 1288 | package Graph.Representation; 1289 | 1290 | public class EdgeList implements Graph { 1291 | static class Edge { 1292 | public int from, to, weight; 1293 | public Edge (int from, int to, int weight) { 1294 | this.from = from; 1295 | this.to = to; 1296 | this.weight = weight; 1297 | } 1298 | } 1299 | 1300 | public static int N, M, idx; 1301 | public static Edge [] edges; 1302 | 1303 | @Override 1304 | public void init(int N, int M) { 1305 | this.N = N; 1306 | this.M = M; 1307 | edges = new Edge [M]; 1308 | idx = 0; 1309 | } 1310 | 1311 | @Override 1312 | public void addEdge(int a, int b, int weight) { 1313 | edges [idx++] = new Edge (a, b, weight); 1314 | } 1315 | 1316 | } 1317 | package Graph.Representation; 1318 | 1319 | public interface Graph { 1320 | // N number of nodes 1321 | // nodes labeled 0...N-1 1322 | // M number of edges 1323 | public static final int INF = 1 << 29; 1324 | public void init (int N, int M); 1325 | public void addEdge (int a, int b, int weight); 1326 | } 1327 | package Graph.Representation; 1328 | 1329 | /** 1330 | * 1331 | * @author Lewin 1332 | * 1333 | */ 1334 | public class LinkedList implements Graph { 1335 | public static int [] eadj, elast, eprev, ecost; 1336 | public static int eidx; 1337 | public static int N, M; 1338 | 1339 | @Override 1340 | public void init (int N, int M) { 1341 | this.N = N; 1342 | this.M = M; 1343 | 1344 | eadj = new int [2 * M]; 1345 | eprev = new int [2 * M]; 1346 | ecost = new int [2 * M]; 1347 | elast = new int [N]; 1348 | eidx = 0; 1349 | } 1350 | 1351 | @Override 1352 | public void addEdge (int a, int b, int weight) { 1353 | eadj [eidx] = b; ecost [eidx] = weight; eprev [eidx] = elast [a]; elast [a] = eidx++; 1354 | // if don't want bidirectional, comment out below line 1355 | eadj [eidx] = a; ecost [eidx] = weight; eprev [eidx] = elast [b]; elast [b] = eidx++; 1356 | } 1357 | } 1358 | package Graph; 1359 | 1360 | public class Triplet implements Comparable { 1361 | public int a, b, c; 1362 | 1363 | public Triplet (int a, int b, int c) { 1364 | this.a = a; 1365 | this.b = b; 1366 | this.c = c; 1367 | } 1368 | 1369 | public int compareTo (Triplet other) { 1370 | return c == other.c ? b == other.b ? a - other.a : b - other.b : c - other.c; 1371 | } 1372 | } 1373 | package LinearProgramming; 1374 | 1375 | public class LPSolver { 1376 | public static double EPS = 1e-9; 1377 | public int m, n; 1378 | public int[] B, N; 1379 | public double[][] D; 1380 | public double[] x; 1381 | 1382 | public LPSolver(double[][] A, double[] b, double[] c) { 1383 | n = c.length; 1384 | m = b.length; 1385 | N = new int[n + 1]; 1386 | B = new int[m]; 1387 | D = new double[m + 2][n + 2]; 1388 | for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) D[i][j] = A[i][j]; 1389 | for (int i = 0; i < m; i++) { B[i] = n+i; D[i][n] = -1; D[i][n+1] = b[i]; } 1390 | for (int j = 0; j < n; j++) { N[j] = j; D[m][j] = -c[j]; } 1391 | N[n] = -1; D[m+1][n] = 1; 1392 | } 1393 | 1394 | public void pivot(int r, int s) { 1395 | for (int i = 0; i < m+2; i++) if (i != r) 1396 | for (int j = 0; j < n+2; j++) if (j != s) 1397 | D[i][j] -= D[r][j] * D[i][s] / D[r][s]; 1398 | for (int j = 0; j < n+2; j++) if (j != s) D[r][j] /= D[r][s]; 1399 | for (int i = 0; i < m+2; i++) if (i != r) D[i][s] /= -D[r][s]; 1400 | D[r][s] = 1.0 / D[r][s]; 1401 | int t = B[r]; B[r] = N[s]; N[s] = t; 1402 | } 1403 | 1404 | public boolean simplex(int phase) { 1405 | int x = phase == 1 ? m+1 : m; 1406 | while (true) { 1407 | int s = -1; 1408 | for (int j = 0; j <= n; j++) { 1409 | if (phase == 2 && N[j] == -1) continue; 1410 | if (s == -1 || D[x][j] < D[x][s] || (Math.abs(D[x][j] - D[x][s]) < EPS && N[j] < N[s])) s = j; 1411 | } 1412 | if (D[x][s] >= -EPS) return true; 1413 | int r = -1; 1414 | for (int i = 0; i < m; i++) { 1415 | if (D[i][s] <= 0) continue; 1416 | if (r == -1 || D[i][n+1] * D[r][s] < D[r][n+1] * D[i][s] || 1417 | (Math.abs(D[i][n+1] * D[r][s] - D[r][n+1] * D[i][s]) < EPS && B[i] < B[r])) r = i; 1418 | } 1419 | if (r == -1) return false; 1420 | pivot(r, s); 1421 | } 1422 | } 1423 | 1424 | public double solve() { 1425 | int r = 0; 1426 | for (int i = 1; i < m; i++) if (D[i][n+1] < D[r][n+1]) r = i; 1427 | if (D[r][n+1] <= -EPS) { 1428 | pivot(r, n); 1429 | if (!simplex(1) || D[m+1][n+1] < -EPS) return Double.NEGATIVE_INFINITY; 1430 | for (int i = 0; i < m; i++) if (B[i] == -1) { 1431 | int s = -1; 1432 | for (int j = 0; j <= n; j++) 1433 | if (s == -1 || D[i][j] < D[i][s] || (Math.abs(D[i][j] - D[i][s]) < EPS && N[j] < N[s])) s = j; 1434 | pivot(i, s); 1435 | } 1436 | } 1437 | if (!simplex(2)) return Double.POSITIVE_INFINITY; 1438 | x = new double[n]; 1439 | for (int i = 0; i < m; i++) if (B[i] < n) x[B[i]] = D[i][n+1]; 1440 | return D[m][n+1]; 1441 | } 1442 | } 1443 | package Matrix; 1444 | 1445 | public class Determinant { 1446 | 1447 | // square matrix 1448 | private static double det (double [][] arr) { 1449 | int N = arr.length; 1450 | double [][] M = new double [N][N]; 1451 | for (int i = 0; i < arr.length; i++) 1452 | System.arraycopy (arr[i], 0, M[i], 0, N); 1453 | 1454 | double mult = 1; 1455 | for (int r = 0; r < N; r++) { 1456 | int k = r; 1457 | while (M[k][r] == 0) { 1458 | k++; 1459 | if (k == N) 1460 | return 0; 1461 | } 1462 | double [] temp = M[r]; 1463 | M[r] = M[k]; 1464 | M[k] = temp; 1465 | if (r != k) { 1466 | mult *= -1; 1467 | } 1468 | 1469 | double lv = M[r][r]; 1470 | for (int j = 0; j < N; j++) 1471 | M[r][j] /= lv; 1472 | mult *= lv; 1473 | 1474 | for (int i = r; i < N; i++) { 1475 | if (i != r) { 1476 | lv = M[i][r]; 1477 | for (int j = r; j < N; j++) 1478 | M[i][j] -= lv * M[r][j]; 1479 | } 1480 | } 1481 | } 1482 | return mult; 1483 | } 1484 | } 1485 | package Matrix; 1486 | 1487 | public class MatrixInverse { 1488 | 1489 | // square matrix 1490 | // returns null if no inverse 1491 | private static double[][] inv (double [][] arr) { 1492 | int N = arr.length; 1493 | double [][] M = new double [N][2 * N]; 1494 | for (int i = 0; i < arr.length; i++) { 1495 | System.arraycopy (arr[i], 0, M[i], 0, N); 1496 | M[i][i + N] = 1; 1497 | } 1498 | 1499 | for (int r = 0; r < N; r++) { 1500 | int k = r; 1501 | while (M[k][r] == 0) { 1502 | k++; 1503 | if (k == N) 1504 | return null; // no inverse 1505 | } 1506 | double [] temp = M[r]; 1507 | M[r] = M[k]; 1508 | M[k] = temp; 1509 | 1510 | double lv = M[r][r]; 1511 | for (int j = 0; j < 2 * N; j++) 1512 | M[r][j] /= lv; 1513 | 1514 | for (int i = 0; i < N; i++) { 1515 | if (i != r) { 1516 | lv = M[i][r]; 1517 | for (int j = 0; j < 2 * N; j++) 1518 | M[i][j] -= lv * M[r][j]; 1519 | } 1520 | } 1521 | } 1522 | 1523 | double [][] ret = new double [N][N]; 1524 | for (int i = 0; i < N; i++) 1525 | System.arraycopy (M[i], N, ret[i], 0, N); 1526 | return ret; 1527 | } 1528 | } 1529 | package Matrix; 1530 | 1531 | /** 1532 | * Operations on matrices 1533 | * @author Lewin 1534 | * 1535 | */ 1536 | public class MatrixOperations { 1537 | private static int mod; 1538 | 1539 | private static int [][] mat_exp (int [][] A, int e) { 1540 | if (e == 1) 1541 | return A; 1542 | else if (e % 2 == 0) { 1543 | int [][] A1 = mat_exp (A, e / 2); 1544 | return matrix_mult (A1, A1); 1545 | } else 1546 | return matrix_mult (A, mat_exp (A, e - 1)); 1547 | } 1548 | 1549 | private static int [][] matrix_mult (int [][] A, int [][] B) { 1550 | int [][] C = new int [A.length] [A.length]; 1551 | for (int i = 0; i < A.length; i++) 1552 | for (int j = 0; j < A.length; j++) 1553 | for (int k = 0; k < A.length; k++) 1554 | C[i][k] = (C[i][k] + A[i][j] * B[j][k]) % mod; 1555 | return C; 1556 | } 1557 | } 1558 | package Matrix; 1559 | 1560 | /** 1561 | * Row reduce function 1562 | * @author Lewin 1563 | * 1564 | */ 1565 | public class RowReduce { 1566 | private static void rref (double [][] M) { 1567 | int row = M.length; 1568 | if (row == 0) 1569 | return; 1570 | 1571 | int col = M[0].length; 1572 | 1573 | int lead = 0; 1574 | for (int r = 0; r < row; r++) { 1575 | if (lead >= col) 1576 | return; 1577 | 1578 | int k = r; 1579 | while (M[k][lead] == 0) { 1580 | k++; 1581 | if (k == row) { 1582 | k = r; 1583 | lead++; 1584 | if (lead == col) 1585 | return; 1586 | } 1587 | } 1588 | double [] temp = M[r]; 1589 | M[r] = M[k]; 1590 | M[k] = temp; 1591 | 1592 | double lv = M[r][lead]; 1593 | for (int j = 0; j < col; j++) 1594 | M[r][j] /= lv; 1595 | 1596 | for (int i = 0; i < row; i++) { 1597 | if (i != r) { 1598 | lv = M[i][lead]; 1599 | for (int j = 0; j < col; j++) 1600 | M[i][j] -= lv * M[r][j]; 1601 | } 1602 | } 1603 | lead++; 1604 | } 1605 | } 1606 | } 1607 | package NumberTheory; 1608 | 1609 | /** 1610 | * Implementation of Chinese Remainder Theorem 1611 | * @author Lewin 1612 | * 1613 | */ 1614 | public class ChineseRemainderTheorem { 1615 | private static long [] sol; 1616 | private static int s_idx; 1617 | /** 1618 | * Chinese Remainder Theorem 1619 | * @param nums List of moduli 1620 | * @param arr Each moduli has an array of possible values it could take on 1621 | * All solutions will be in sol (has arr[0].length*arr[1].length*...*arr[N].length solutions) 1622 | */ 1623 | private static void CRT (int [] nums, int [][] arr) { 1624 | CRT (0, nums, arr, 0, 1); 1625 | } 1626 | 1627 | private static void CRT (int idx, int [] nums, int [][] arr, long res, long f) { 1628 | if (idx == nums.length) { 1629 | while (res < f) res += f; 1630 | res %= f; 1631 | sol [s_idx++] = res; 1632 | return; 1633 | } 1634 | for (int i = 0; i < arr [idx].length; i++) 1635 | CRT (idx + 1, nums, arr, euclid (f, nums [idx], res, arr [idx][i]), f * nums [idx]); 1636 | } 1637 | 1638 | private static long euclid (long m, long n, long a, long b) { 1639 | if (m == 0 && a == 0) return a; 1640 | long s = m, t = n, v = 1, u = 0, lastv = 0, lastu = 1, temp, q, r; 1641 | do { 1642 | q = s / t; r = s - t * q; s = t; t = r; 1643 | temp = u; u = lastu - u * q; lastu = temp; 1644 | temp = v; v = lastv - v * q; lastv = temp; 1645 | } while (r != 0); 1646 | a = (a * lastv * n) % (m * n); 1647 | b = (b * lastu * m) % (m * n); 1648 | if (m * lastu > n * lastv) return b - a; 1649 | else return a - b; 1650 | } 1651 | } 1652 | package NumberTheory; 1653 | 1654 | import java.util.HashMap; 1655 | import static NumberTheory.Utils.inv; 1656 | import static NumberTheory.SafeArithmetic.mod_exp; 1657 | 1658 | 1659 | public class DiscreteLog { 1660 | // gcd (g, mod) = 1 1661 | public static long discreteLog (long g, long gn, long mod) { 1662 | long m = (long)Math.ceil (mod); 1663 | HashMap mp = new HashMap (); 1664 | long cur = 1; 1665 | for (int i = 0; i < m; i++) { 1666 | mp.put(cur, (long)i); 1667 | cur = (cur * g) % mod; 1668 | } 1669 | long st2 = mod_exp (inv (g, mod), m, mod); 1670 | long y = gn; 1671 | for (int i = 0; i < m; i++) { 1672 | if (mp.containsKey(y)) 1673 | return i * m + mp.get(y); 1674 | y = (y * st2) % mod; 1675 | } 1676 | return -1; 1677 | } 1678 | } 1679 | package NumberTheory; 1680 | 1681 | import java.math.BigInteger; 1682 | import java.security.SecureRandom; 1683 | 1684 | /** 1685 | * Implementation of Pollard Rho's factoring algorithm 1686 | * @author Lewin 1687 | * http://en.wikipedia.org/wiki/Pollard's_rho_algorithm 1688 | */ 1689 | 1690 | public class PollardRho { 1691 | private final static BigInteger ZERO = new BigInteger ("0"); 1692 | private final static BigInteger ONE = new BigInteger ("1"); 1693 | private final static BigInteger TWO = new BigInteger ("2"); 1694 | private final static SecureRandom random = new SecureRandom (); 1695 | 1696 | // cycle detection 1697 | public static BigInteger rho (BigInteger N) { 1698 | BigInteger divisor; 1699 | BigInteger c = new BigInteger (N.bitLength (), random); 1700 | BigInteger x = new BigInteger (N.bitLength (), random); 1701 | BigInteger xx = x; 1702 | 1703 | // check divisibility by 2 1704 | if (N.mod (TWO).compareTo (ZERO) == 0) 1705 | return TWO; 1706 | 1707 | do { 1708 | x = x.multiply (x).mod (N).add (c).mod (N); 1709 | xx = xx.multiply (xx).mod (N).add (c).mod (N); 1710 | xx = xx.multiply (xx).mod (N).add (c).mod (N); 1711 | divisor = x.subtract (xx).gcd (N); 1712 | } while ((divisor.compareTo (ONE)) == 0); 1713 | 1714 | return divisor; 1715 | } 1716 | 1717 | // prints out all factors 1718 | // can modify to store these factors into some data structure 1719 | public static void factor (BigInteger N) { 1720 | if (N.compareTo (ONE) == 0) 1721 | return; 1722 | if (N.isProbablePrime (20)) { 1723 | System.out.println (N); 1724 | return; 1725 | } 1726 | BigInteger divisor = rho (N); 1727 | factor (divisor); 1728 | factor (N.divide (divisor)); 1729 | } 1730 | } 1731 | package NumberTheory; 1732 | /** 1733 | * Prime Siever 1734 | * @author Lewin 1735 | * 1736 | */ 1737 | public class PrimeSieve { 1738 | public static boolean [] isPrime; 1739 | public static int [] prime; 1740 | public static int idx, len; 1741 | 1742 | private static void generatePrimes () { 1743 | isPrime = new boolean [len + 1]; 1744 | prime = new int [len / 2]; 1745 | isPrime [2] = true; prime [idx++] = 2; 1746 | int i; 1747 | for (i = 3; i <= len; i += 2) isPrime [i] = true; 1748 | for (i = 3; i * i <= len; i += 2) { 1749 | if (isPrime [i]) { 1750 | prime [idx++] = i; 1751 | for (int j = i * i; j <= len; j += 2 * i) 1752 | isPrime [j] = false; 1753 | } 1754 | } 1755 | for (; i <= len; i += 2) 1756 | if (isPrime [i]) 1757 | prime [idx++] = i; 1758 | } 1759 | } 1760 | package NumberTheory; 1761 | 1762 | /** 1763 | * Safely multiplies and adds number under a modulus to prevent overflow 1764 | * Operations may still overflow if modulus is greater than Long.MAX_VALUE / 2 1765 | * @author Lewin 1766 | * 1767 | */ 1768 | public class SafeArithmetic { 1769 | public static long mod_mult (long x, long y, long p) { 1770 | if (x == 0 || y == 0) return 0; 1771 | long a = x, b = y, c = 0; 1772 | while (a > 0) { 1773 | if ((a & 1) == 1) c = (c + b) % p; 1774 | a >>= 1; 1775 | b = (b * 2) % p; 1776 | } 1777 | return c; 1778 | } 1779 | 1780 | public static long mod_exp (long b, long e, long mod) { 1781 | if (b == 0 || b == 1) return b; 1782 | long res = 1; 1783 | while (e > 0) { 1784 | if ((e & 1) == 1) 1785 | res = mod_mult (res, b, mod); 1786 | e >>= 1; 1787 | b = mod_mult (b, b, mod); 1788 | } 1789 | return res; 1790 | } 1791 | } 1792 | package NumberTheory; 1793 | /** 1794 | * Euler's Totient Function Siever 1795 | * @author Lewin 1796 | * http://en.wikipedia.org/wiki/Euler's_totient_function 1797 | */ 1798 | public class TotientSieve { 1799 | private static boolean [] isPrime; 1800 | private static int [] prime; 1801 | private static int idx, len; 1802 | private static int [] phi; 1803 | 1804 | private static void phi_prime_sieve () { 1805 | isPrime = new boolean [len + 1]; 1806 | prime = new int [len / 2]; 1807 | phi = new int [len + 1]; 1808 | phi [0] = 0; phi [1] = 1; 1809 | for (int i = 2; i <= len; i++) { 1810 | isPrime [i] = true; 1811 | phi [i] = i; 1812 | } 1813 | for (int i = 2; i <= len; i++) { 1814 | if (isPrime [i]) { 1815 | prime [idx++] = i; 1816 | phi [i] = i - 1; 1817 | for (int j = i + i; j <= len; j += i) { 1818 | isPrime [j] = false; 1819 | phi [j] /= i; phi [j] *= i - 1; 1820 | } 1821 | } 1822 | } 1823 | } 1824 | } 1825 | package NumberTheory; 1826 | 1827 | import static NumberTheory.PrimeSieve.*; 1828 | /** 1829 | * Collection of common operations 1830 | * @author Lewin 1831 | * 1832 | */ 1833 | 1834 | public class Utils { 1835 | // Euler's Totient Function 1836 | public static long phi (long n) {// make sure to generate primes 1837 | long temp = n; 1838 | for (int i = 0; prime [i] * prime [i] <= temp && i < idx; i++) 1839 | if (temp % prime [i] == 0) { 1840 | n -= n / prime [i]; 1841 | while (temp % prime [i] == 0) 1842 | temp /= prime [i]; 1843 | } 1844 | return temp == 1 ? n : n / temp * (temp - 1); 1845 | } 1846 | 1847 | // N choose K 1848 | public static long comb (int n, int k) { 1849 | int a = Math.min (k, n - k); 1850 | long res = 1; 1851 | for (int i = 1; i <= a; i++) { 1852 | res *= n--; res /= i; 1853 | } 1854 | return res; 1855 | } 1856 | 1857 | // Greatest Common Divisor 1858 | public static long gcd (long x, long y) { 1859 | for (; x != 0; x ^= y, y ^= x, x ^= y, x %= y); 1860 | return y; 1861 | } 1862 | 1863 | // Inverse of N mod M; 1864 | public static long inv (long N, long M) { 1865 | long x = 0, lastx = 1, y = 1, lasty = 0, q, t, a = N, b = M; 1866 | while (b != 0) { 1867 | q = a / b; t = a % b; a = b; b = t; 1868 | t = x; x = lastx - q * x; lastx = t; 1869 | t = y; y = lasty - q * y; lasty = t; 1870 | } 1871 | return (lastx + M) % M; 1872 | } 1873 | } 1874 | package String; 1875 | /** 1876 | * Implementation of Knuth-Morris-Pratt 1877 | * 1878 | * See http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm 1879 | * 1880 | * @author Lewin 1881 | * 1882 | */ 1883 | public class KnuthMorrisPratt { 1884 | private static int KMP (String text, String word) { 1885 | char [] a = text.toCharArray (), b = word.toCharArray (); 1886 | int [] T = new int [a.length + b.length]; 1887 | 1888 | int pos = 2, cnd = 0; 1889 | T [0] = -1; T [1] = 0; 1890 | while (pos < b.length) { 1891 | if (b [pos - 1] == b [cnd]) { 1892 | cnd++; T [pos] = cnd; 1893 | pos++; 1894 | } else if (cnd > 0) cnd = T [cnd]; 1895 | else {T [pos] = 0; pos++;} 1896 | } 1897 | 1898 | int m = 0, i = 0; 1899 | while (m + i < a.length) { 1900 | if (b [i] == a [m + i]) { 1901 | if (i == b.length - 1) 1902 | return m; 1903 | i++; 1904 | } else { 1905 | m += i - T [i]; 1906 | if (T [i] > -1) i = T [i]; 1907 | else i = 0; 1908 | } 1909 | } 1910 | return a.length; 1911 | } 1912 | } 1913 | package String; 1914 | 1915 | import java.util.Arrays; 1916 | /** 1917 | * O(n log n) suffix array 1918 | * O(n) longest common prefix 1919 | * 1920 | * @author Lewin 1921 | * 1922 | */ 1923 | public class SuffixArray { 1924 | 1925 | private static int [] suffix_array (char [] s) { 1926 | int n = s.length; 1927 | int [] id = new int [n]; 1928 | for (int i = 0; i < n; i++) 1929 | id[i] = s[i] - 'a'; 1930 | 1931 | for (int k = 1; k <= n; k <<= 1) { 1932 | Triplet [] elem = new Triplet [n]; 1933 | for (int i = 0; i < n; i++) 1934 | elem[i] = new Triplet (id[i], (i + k < n) ? id[i + k] : -1, i); 1935 | Arrays.sort (elem); 1936 | int cur = -1; 1937 | for (int i = 0; i < n; i++) { 1938 | if (i == 0 1939 | || !(elem[i].a == elem[i - 1].a && elem[i].b == elem[i - 1].b)) 1940 | cur++; 1941 | id[elem[i].c] = cur; 1942 | } 1943 | } 1944 | 1945 | return id; 1946 | } 1947 | 1948 | private static int [] lcp (char [] A, int [] order, int [] rank) { 1949 | int n = order.length; 1950 | int [] height = new int [n]; 1951 | 1952 | int h = 0; 1953 | for (int i = 0; i < n; i++) { 1954 | if (order [i] > 0) { 1955 | int j = rank [order [i] - 1]; 1956 | while (i + h < n && j + h < n 1957 | && A [i + h] == A [j + h]) h++; 1958 | height [order [i]] = h; 1959 | if (h > 0) h--; 1960 | } 1961 | } 1962 | 1963 | return height; 1964 | } 1965 | 1966 | static class Triplet implements Comparable { 1967 | public int a, b, c; 1968 | 1969 | public Triplet (int _a, int _b, int _c) { 1970 | a = _a; 1971 | b = _b; 1972 | c = _c; 1973 | } 1974 | 1975 | public int compareTo (Triplet other) { 1976 | return (a == other.a) ? b - other.b : a - other.a; 1977 | } 1978 | } 1979 | } 1980 | package String; 1981 | 1982 | public class SuffixTree { 1983 | static String alphabet = "abcdefghijklmnopqrstuvwxyz12"; 1984 | static int alphabetSize = alphabet.length(); 1985 | 1986 | static class Node { 1987 | int depth; // from start of suffix 1988 | int begin; 1989 | int end; 1990 | Node[] children; 1991 | Node parent; 1992 | Node suffixLink; 1993 | int mask; 1994 | boolean mark; 1995 | 1996 | Node(int begin, int end, int depth, Node parent) { 1997 | children = new Node[alphabetSize]; 1998 | this.begin = begin; 1999 | this.end = end; 2000 | this.parent = parent; 2001 | this.depth = depth; 2002 | mask = 0; 2003 | mark = false; 2004 | } 2005 | 2006 | boolean contains(int d) { 2007 | return depth <= d && d < depth + (end - begin); 2008 | } 2009 | } 2010 | 2011 | public static Node buildSuffixTree(String s) { 2012 | int n = s.length(); 2013 | byte[] a = new byte[n]; 2014 | for (int i = 0; i < n; i++) { 2015 | a[i] = (byte) alphabet.indexOf(s.charAt(i)); 2016 | } 2017 | Node root = new Node(0, 0, 0, null); 2018 | Node cn = root; 2019 | // root.suffixLink must be null, but that way it gets more convenient 2020 | // processing 2021 | root.suffixLink = root; 2022 | Node needsSuffixLink = null; 2023 | int lastRule = 0; 2024 | int j = 0; 2025 | for (int i = -1; i < n - 1; i++) {// strings s[j..i] already in tree, 2026 | // add s[i+l] to it. 2027 | int cur = a[i + 1]; // last char of current string 2028 | for (; j <= i + 1; j++) { 2029 | int curDepth = i + 1 - j; 2030 | if (lastRule != 3) { 2031 | cn = cn.suffixLink != null ? cn.suffixLink : cn.parent.suffixLink; 2032 | int k = j + cn.depth; 2033 | while (curDepth > 0 && !cn.contains(curDepth - 1)) { 2034 | k += cn.end - cn.begin; 2035 | cn = cn.children[a[k]]; 2036 | } 2037 | } 2038 | if (!cn.contains(curDepth)) { // explicit node 2039 | if (needsSuffixLink != null) { 2040 | needsSuffixLink.suffixLink = cn; 2041 | needsSuffixLink = null; 2042 | } 2043 | if (cn.children[cur] == null) { 2044 | // no extension - add leaf 2045 | cn.children[cur] = new Node(i + 1, n, curDepth, cn); 2046 | lastRule = 2; 2047 | } else { 2048 | cn = cn.children[cur]; 2049 | lastRule = 3; // already exists 2050 | break; 2051 | } 2052 | } else { // implicit node 2053 | int end = cn.begin + curDepth - cn.depth; 2054 | if (a[end] != cur) { // split implicit node here 2055 | Node newn = new Node(cn.begin, end, cn.depth, cn.parent); 2056 | newn.children[cur] = new Node(i + 1, n, curDepth, newn); 2057 | newn.children[a[end]] = cn; 2058 | cn.parent.children[a[cn.begin]] = newn; 2059 | if (needsSuffixLink != null) { 2060 | needsSuffixLink.suffixLink = newn; 2061 | } 2062 | cn.begin = end; 2063 | cn.depth = curDepth; 2064 | cn.parent = newn; 2065 | cn = needsSuffixLink = newn; 2066 | lastRule = 2; 2067 | } else if (cn.end != n || cn.begin - cn.depth < j) { 2068 | lastRule = 3; 2069 | break; 2070 | } else { 2071 | lastRule = 1; 2072 | } 2073 | } 2074 | } 2075 | } 2076 | root.suffixLink = null; 2077 | return root; 2078 | } 2079 | 2080 | } 2081 | package String; 2082 | 2083 | public class ZAlgorithm { 2084 | public int[] zAlgorithm(char[] let) { 2085 | int N = let.length; 2086 | int[] z = new int[N]; 2087 | int L = 0, R = 0; 2088 | for (int i = 1; i < N; i++) { 2089 | if (i > R) { 2090 | L = R = i; 2091 | while (R < N && let[R-L] == let[R]) R++; 2092 | z[i] = R-L; R--; 2093 | } else { 2094 | int k = i-L; 2095 | if (z[k] < R-i+1) z[i] = z[k]; 2096 | else { 2097 | L = i; 2098 | while (R < N && let[R-L] == let[R]) R++; 2099 | z[i] = R-L; R--; 2100 | } 2101 | } 2102 | } 2103 | z[0] = N; 2104 | return z; 2105 | } 2106 | } 2107 | package Trees; 2108 | /** 2109 | * Given a list of N numbers in a row, we can use this structure for 2110 | * exactly 1 of 2 uses: 2111 | * a) range query, point update 2112 | * b) range update, point query 2113 | * 2114 | * For more info, see: 2115 | * http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=binaryIndexedTrees 2116 | * @author Lewin 2117 | */ 2118 | public class BinaryIndexedTrees { 2119 | private static int [] tree; 2120 | private static int N; 2121 | 2122 | private static int query (int K) { 2123 | int sum = 0; 2124 | for (int i = K; i > 0; i -= (i & -i)) 2125 | sum += tree [i]; 2126 | return sum; 2127 | } 2128 | 2129 | private static void update (int K, int val) { 2130 | for (int i = K; i <= N; i += (i & -i)) 2131 | tree [i] += val; 2132 | } 2133 | } 2134 | package Trees; 2135 | 2136 | import java.util.Arrays; 2137 | 2138 | public class HeavyLightTree { 2139 | public static int MAXN = 10000; 2140 | static { 2141 | size = new int[MAXN]; 2142 | cp = new int[MAXN]; 2143 | depth = new int[MAXN]; 2144 | anc = new int[15][MAXN]; 2145 | bestchild = new int[MAXN]; 2146 | whchain = new int[MAXN]; 2147 | chainhead = new int[MAXN]; 2148 | index = new int[MAXN]; 2149 | chains = new int[MAXN]; 2150 | emp = new Edge[MAXN]; 2151 | g = new Graph (MAXN, MAXN - 1); 2152 | } 2153 | 2154 | static class Graph { 2155 | public int[] eadj, eprev, elast, ecost; 2156 | public int eidx; 2157 | 2158 | public Graph(int N, int M) { 2159 | eadj = new int[2 * M]; 2160 | eprev = new int[2 * M]; 2161 | ecost = new int[2 * M]; 2162 | elast = new int[N]; 2163 | reset(); 2164 | } 2165 | 2166 | public void reset() { 2167 | Arrays.fill (elast, -1); 2168 | eidx = 0; 2169 | } 2170 | 2171 | public void addEdge(int a, int b, int c) { 2172 | eadj[eidx] = b; 2173 | ecost[eidx] = c; 2174 | eprev[eidx] = elast[a]; 2175 | elast[a] = eidx++; 2176 | eadj[eidx] = a; 2177 | ecost[eidx] = c; 2178 | eprev[eidx] = elast[b]; 2179 | elast[b] = eidx++; 2180 | } 2181 | } 2182 | 2183 | static class Edge { 2184 | public int a, b; 2185 | 2186 | public Edge(int a, int b) { 2187 | this.a = a; 2188 | this.b = b; 2189 | } 2190 | 2191 | @Override 2192 | public int hashCode() { 2193 | return a * 10000 + b; 2194 | } 2195 | 2196 | @Override 2197 | public boolean equals(Object other) { 2198 | if (!(other instanceof Edge)) 2199 | return false; 2200 | return ((Edge) other).a == a && ((Edge) other).b == b; 2201 | } 2202 | } 2203 | 2204 | public static int[] arr; 2205 | 2206 | static class SegmentTree { 2207 | public int start, end, max; 2208 | public SegmentTree left, right; 2209 | 2210 | public SegmentTree(int start, int end) { 2211 | this.start = start; 2212 | this.end = end; 2213 | if (start == end) { 2214 | max = arr[start]; 2215 | } else { 2216 | int mid = (start + end) >> 1; 2217 | left = new SegmentTree(start, mid); 2218 | right = new SegmentTree(mid + 1, end); 2219 | max = Math.max(left.max, right.max); 2220 | } 2221 | } 2222 | 2223 | public void update(int pos, int val) { 2224 | if (start == pos && end == pos) { 2225 | max = val; 2226 | return; 2227 | } 2228 | int mid = (start + end) >> 1; 2229 | if (mid >= pos) 2230 | left.update(pos, val); 2231 | else 2232 | right.update(pos, val); 2233 | max = Math.max(left.max, right.max); 2234 | } 2235 | 2236 | public int query(int s, int e) { 2237 | if (start == s && end == e) { 2238 | return max; 2239 | } 2240 | int mid = (start + end) >> 1; 2241 | if (mid >= e) 2242 | return left.query(s, e); 2243 | else if (mid < s) 2244 | return right.query(s, e); 2245 | else 2246 | return Math.max(left.query(s, mid), right.query(mid + 1, e)); 2247 | } 2248 | } 2249 | 2250 | public static int N; 2251 | public static Graph g; 2252 | public static Edge[] emp; 2253 | 2254 | public static int[] size, cp, depth; 2255 | public static int[][] anc; 2256 | public static int[] bestchild; 2257 | 2258 | public static int dfs0(int node, int par) { 2259 | anc[0][node] = par; 2260 | depth[node] = par == -1 ? 0 : depth[par] + 1; 2261 | size[node] = 1; 2262 | bestchild[node] = -1; 2263 | int max = 0; 2264 | for (int e = g.elast[node]; e != -1; e = g.eprev[e]) { 2265 | int next = g.eadj[e]; 2266 | if (next == par) 2267 | continue; 2268 | cp[next] = g.ecost[e]; 2269 | int sizen = dfs0(next, node); 2270 | if (sizen > max) { 2271 | max = sizen; 2272 | bestchild[node] = next; 2273 | } 2274 | size[node] += sizen; 2275 | } 2276 | return size[node]; 2277 | } 2278 | 2279 | public static int[] whchain, chainhead, index, chains; 2280 | public static int cidx, widx; 2281 | 2282 | public static void dfs1(int node, int par) { 2283 | whchain[node] = widx; 2284 | index[node] = cidx; 2285 | chains[cidx++] = node; 2286 | 2287 | if (bestchild[node] == -1) 2288 | return; 2289 | dfs1(bestchild[node], node); 2290 | for (int e = g.elast[node]; e != -1; e = g.eprev[e]) { 2291 | int next = g.eadj[e]; 2292 | if (next == par || next == bestchild[node]) 2293 | continue; 2294 | widx++; 2295 | chainhead[widx] = next; 2296 | dfs1(next, node); 2297 | } 2298 | } 2299 | 2300 | public static SegmentTree root; 2301 | public static void init() { 2302 | dfs0(0, -1); 2303 | for (int i = 1; i < 15; i++) { 2304 | for (int j = 0; j < N; j++) { 2305 | anc[i][j] = anc[i - 1][j] == -1 ? -1 : anc[i - 1][anc[i - 1][j]]; 2306 | } 2307 | } 2308 | chainhead[0] = 0; 2309 | widx = 0; 2310 | cidx = 0; 2311 | dfs1(0, -1); 2312 | arr = new int[cidx]; 2313 | for (int i = 0; i < cidx; i++) 2314 | arr[i] = cp[chains[i]]; 2315 | root = new SegmentTree(0, cidx - 1); 2316 | } 2317 | 2318 | public static int lca(int a, int b) { 2319 | if (depth[a] < depth[b]) { 2320 | a ^= b; 2321 | b ^= a; 2322 | a ^= b; 2323 | } 2324 | 2325 | int diff = depth[a] - depth[b]; 2326 | for (int i = 0; i < anc.length && diff > 0; i++, diff >>= 1) 2327 | if ((diff & 1) != 0) 2328 | a = anc[i][a]; 2329 | 2330 | if (a == b) 2331 | return a; 2332 | 2333 | for (int i = anc.length - 1; i >= 0; i--) 2334 | if (anc[i][a] != anc[i][b]) { 2335 | a = anc[i][a]; 2336 | b = anc[i][b]; 2337 | } 2338 | 2339 | return anc[0][a]; 2340 | } 2341 | 2342 | public static int query_up(int a, int b) { 2343 | // a is an ancestor of b 2344 | int achain = whchain[a], bchain = whchain[b]; 2345 | int ans = 0; 2346 | while (achain != bchain) { // try to get them on the same chain 2347 | if (b != chainhead[bchain]) 2348 | ans = Math.max(ans, root.query(index[chainhead[bchain]], index[b])); 2349 | b = anc[0][chainhead[bchain]]; 2350 | bchain = whchain[b]; 2351 | } 2352 | if (a != b) 2353 | ans = Math.max(ans, root.query(index[a] + 1, index[b])); 2354 | return ans; 2355 | } 2356 | 2357 | public static int query(int a, int b) { 2358 | int lca = lca(a, b); 2359 | return Math.max(query_up(lca, a), query_up(lca, b)); 2360 | } 2361 | 2362 | public static void update(int x, int c) { 2363 | Edge e = emp[x]; 2364 | int a = e.a, b = e.b; 2365 | if (depth[a] < depth[b]) { 2366 | int t = a; a = b; b = t; 2367 | } 2368 | root.update(index[b], c); 2369 | } 2370 | } 2371 | package Trees; 2372 | 2373 | public class KDTree { 2374 | // don't know if this works 2375 | static class kd_tree { 2376 | public kd_tree Lchild = null, Rchild = null; 2377 | public Point[] points; 2378 | public int d; 2379 | 2380 | public kd_tree(Point[] points, int depth) { 2381 | this.points = points; 2382 | int k = points[0].coord.length; 2383 | int N = points.length; 2384 | d = depth % k; 2385 | 2386 | if (N == 1) 2387 | return; 2388 | 2389 | Point[] temp; 2390 | int lo = 0, hi = N - 1, comp; 2391 | while (true) { 2392 | temp = new Point[N]; 2393 | comp = points[lo].coord[d]; 2394 | int f1 = 0, f2 = N - 1; 2395 | for (int i = lo; i <= hi; i++) { 2396 | if (points[i].coord[d] < comp) 2397 | temp[f1++] = points[i]; 2398 | else 2399 | temp[f2--] = points[i]; 2400 | } 2401 | points = temp; 2402 | if (f1 == N / 2) 2403 | break; 2404 | if (f1 < N / 2) 2405 | lo = f1; 2406 | else 2407 | hi = f2; 2408 | } 2409 | 2410 | Point[] first = new Point[N / 2], second = new Point[N - N / 2]; 2411 | System.arraycopy(points, 0, first, 0, N / 2); 2412 | System.arraycopy(points, N / 2, second, 0, N - N / 2); 2413 | Lchild = new kd_tree(first, depth + 1); 2414 | Rchild = new kd_tree(second, depth + 1); 2415 | } 2416 | 2417 | } 2418 | 2419 | static class Point { 2420 | public int[] coord; 2421 | 2422 | public Point(int[] coord) { 2423 | this.coord = coord; 2424 | } 2425 | } 2426 | } 2427 | package Trees; 2428 | 2429 | public class LazyIntervalTree { 2430 | public int min, max, lazy, start, end; 2431 | public LazyIntervalTree child1 = null, child2 = null; 2432 | 2433 | public LazyIntervalTree (int start, int end) { 2434 | this.start = start; 2435 | this.end = end; 2436 | if (start != end) { 2437 | int mid = (start + end) >> 1; 2438 | child1 = new LazyIntervalTree (start, mid); 2439 | child2 = new LazyIntervalTree (mid + 1, end); 2440 | } 2441 | } 2442 | 2443 | public void modify (int val) { 2444 | min += val; 2445 | max += val; 2446 | lazy += val; 2447 | } 2448 | 2449 | public void push () { 2450 | if (child1 == null) 2451 | return; 2452 | child1.modify (lazy); 2453 | child2.modify (lazy); 2454 | lazy = 0; 2455 | } 2456 | 2457 | public void join () { 2458 | if (child1 == null) 2459 | return; 2460 | min = Math.min (child1.min, child2.min); 2461 | max = Math.max (child1.max, child2.max); 2462 | } 2463 | 2464 | public int minQuery (int a, int b) { 2465 | if (a <= start && end <= b) 2466 | return min; 2467 | if (start > b || a > end) 2468 | return Integer.MAX_VALUE; 2469 | if (child1 == null) 2470 | return min; 2471 | 2472 | push (); 2473 | return Math.min (child1.minQuery (a, b), child2.minQuery (a, b)); 2474 | } 2475 | 2476 | public int maxQuery (int a, int b) { 2477 | if (a <= start && end <= b) 2478 | return max; 2479 | if (start > b || a > end) 2480 | return -Integer.MAX_VALUE; 2481 | if (child1 == null) 2482 | return max; 2483 | 2484 | push (); 2485 | return Math.max (child1.maxQuery (a, b), child2.maxQuery (a, b)); 2486 | } 2487 | 2488 | public void updateRange (int a, int b, int val) { 2489 | if (a <= start && end <= b) { 2490 | modify (val); 2491 | return; 2492 | } 2493 | if (start > b || a > end) 2494 | return; 2495 | if (child1 == null) 2496 | return; 2497 | 2498 | push (); 2499 | child1.updateRange (a, b, val); 2500 | child2.updateRange (a, b, val); 2501 | join (); 2502 | } 2503 | } 2504 | package Trees; 2505 | 2506 | public class LazySegmentTree { 2507 | public static int [] tree, lazy; 2508 | public static final int INF = 1 << 29; 2509 | public static int PN, N; 2510 | 2511 | // PN = 1<<(f(N)) 2512 | // f(N): for(i = 0; N>>i > 0; i++) 2513 | 2514 | private static void modify (int pos, int val) { 2515 | tree[pos] += val; 2516 | lazy[pos] += val; 2517 | } 2518 | 2519 | private static void push (int pos) { 2520 | modify (2 * pos, lazy[pos]); 2521 | modify (2 * pos + 1, lazy[pos]); 2522 | lazy[pos] = 0; 2523 | } 2524 | 2525 | private static void join (int pos) { 2526 | tree[pos] = Math.min (tree[2 * pos], tree[2 * pos + 1]); 2527 | } 2528 | 2529 | private static int query (int pos, int start, int end, int a, int b) { 2530 | if (a <= start && end <= b) 2531 | return tree[pos]; 2532 | if (pos >= PN || start >= b || a >= end) 2533 | return INF; 2534 | push (pos); 2535 | int mid = (start + end) >> 1; 2536 | return Math.min (query (2 * pos, start, mid, a, b), 2537 | query (2 * pos + 1, mid + 1, end, a, b)); 2538 | } 2539 | 2540 | private static void update (int pos, int start, int end, int a, int b, 2541 | int val) { 2542 | if (a <= start && end <= b) { 2543 | modify (pos, val); 2544 | return; 2545 | } 2546 | if (pos >= PN || start >= b || a >= end) 2547 | return; 2548 | push (pos); 2549 | int mid = (start + end) >> 1; 2550 | update (2 * pos, start, mid, a, b, val); 2551 | update (2 * pos + 1, mid + 1, end, a, b, val); 2552 | join (pos); 2553 | } 2554 | 2555 | private static void build (int pos, int start, int end) { 2556 | if (pos >= PN || start >= N) 2557 | return; 2558 | int mid = (start + end) >> 1; 2559 | build (2 * pos, start, mid); 2560 | build (2 * pos + 1, mid + 1, end); 2561 | tree[pos] = tree[2 * pos]; 2562 | lazy[pos] = 0; 2563 | if (mid < N) 2564 | tree[pos] = Math.min (tree[pos], tree[2 * pos + 1]); 2565 | } 2566 | } 2567 | package Trees; 2568 | 2569 | public class LinkCutTree { 2570 | private static final int INF = 1000000000; 2571 | private static final TEdge NULL = new TEdge(null, INF); 2572 | 2573 | static class TEdge { 2574 | public Node n; 2575 | public int weight; 2576 | 2577 | public TEdge(Node n, int weight) { 2578 | this.n = n; 2579 | this.weight = n == null ? INF : weight; 2580 | } 2581 | 2582 | public String toString() { 2583 | return (n == null ? null : n.id) + " " + weight; 2584 | } 2585 | } 2586 | 2587 | static class Node { 2588 | int id, min; 2589 | TEdge left; 2590 | TEdge right; 2591 | TEdge parent; 2592 | boolean flip; 2593 | 2594 | public Node(int id) { 2595 | this.id = id; 2596 | this.min = INF; 2597 | left = NULL; 2598 | right = NULL; 2599 | parent = NULL; 2600 | } 2601 | 2602 | public String toString() { 2603 | return id + " " + "|L: " + left + " |R: " + right + " |P: " + parent; 2604 | } 2605 | } 2606 | 2607 | static void push(Node x) { 2608 | if (!x.flip) 2609 | return; 2610 | x.flip = false; 2611 | TEdge t = x.left; 2612 | x.left = x.right; 2613 | x.right = t; 2614 | if (x.left.n != null) 2615 | x.left.n.flip = !x.left.n.flip; 2616 | if (x.right.n != null) 2617 | x.right.n.flip = !x.right.n.flip; 2618 | } 2619 | 2620 | // Whether x is a root of a splay tree 2621 | static boolean isRoot(Node x) { 2622 | return x.parent.n == null || (x.parent.n.left.n != x && x.parent.n.right.n != x); 2623 | } 2624 | 2625 | static void connect(Node ch, Node p, int weight, boolean leftChild) { 2626 | if (leftChild) 2627 | p.left = new TEdge(ch, weight); 2628 | else 2629 | p.right = new TEdge(ch, weight); 2630 | 2631 | p.min = 2632 | Math.min(p.right.n == null ? INF : Math.min(p.right.n.min, p.right.weight), 2633 | p.left.n == null ? INF : Math.min(p.left.n.min, p.left.weight)); 2634 | 2635 | if (ch != null) { 2636 | ch.parent = new TEdge(p, weight); 2637 | } 2638 | } 2639 | 2640 | // rotate edge (x, x.parent) 2641 | static void rotate(Node x) { 2642 | Node p = x.parent.n; 2643 | Node g = p.parent.n; 2644 | boolean isRootP = isRoot(p); 2645 | boolean leftChildX = (x == p.left.n); 2646 | 2647 | TEdge next = leftChildX ? x.right : x.left; 2648 | int w1 = p.parent.weight; 2649 | int w2 = x.parent.weight; 2650 | int w3 = next.n == null ? w2 : next.weight; 2651 | connect(next.n, p, w2, leftChildX); 2652 | connect(p, x, w3, !leftChildX); 2653 | 2654 | if (!isRootP) 2655 | connect(x, g, w1, p == g.left.n); 2656 | else 2657 | x.parent = new TEdge(g, w1); 2658 | } 2659 | 2660 | static void splay(Node x) { 2661 | while (!isRoot(x)) { 2662 | Node p = x.parent.n; 2663 | Node g = p.parent.n; 2664 | if (!isRoot(p)) 2665 | push(g); 2666 | push(p); 2667 | push(x); 2668 | if (!isRoot(p)) 2669 | rotate((x == p.left.n) == (p == g.left.n) ? p : x); 2670 | rotate(x); 2671 | } 2672 | push(x); 2673 | } 2674 | 2675 | // Makes node x the root of the virtual tree, and also x is the leftmost 2676 | // node in its splay tree 2677 | static Node expose(Node x) { 2678 | Node last = null; 2679 | int lw = INF; 2680 | for (Node y = x; y != null; y = y.parent.n) { 2681 | splay(y); 2682 | y.left = new TEdge(last, lw); 2683 | y.min = 2684 | Math.min(last == null ? INF : Math.min(last.min, lw), 2685 | y.right.n == null ? INF : Math.min(y.right.n.min, y.right.weight)); 2686 | last = y; 2687 | lw = y.parent.weight; 2688 | } 2689 | splay(x); 2690 | return last; 2691 | } 2692 | 2693 | public static Node findRoot(Node x) { 2694 | expose(x); 2695 | while (x.right.n != null) { 2696 | x = x.right.n; 2697 | push(x); 2698 | } 2699 | return x; 2700 | } 2701 | 2702 | // prerequisite: x and y are in distinct trees 2703 | public static void link(Node x, Node y, int idx) { 2704 | if (findRoot(x) == findRoot(y)) 2705 | throw new RuntimeException("error: x and y are connected"); 2706 | expose(x); 2707 | x.flip = !x.flip; // evert 2708 | x.parent = new TEdge(y, idx); 2709 | expose(x); 2710 | } 2711 | 2712 | public static boolean connected(Node x, Node y) { 2713 | if (x == y) 2714 | return true; 2715 | return findRoot(x) == findRoot(y); 2716 | } 2717 | 2718 | public static void cut(Node x, Node y) { 2719 | expose(x); 2720 | x.flip = !x.flip; // evert 2721 | expose(y); 2722 | if (y.right.n != x || x.left.n != null || x.right.n != null) 2723 | throw new RuntimeException("error: no edge (x,y)"); 2724 | y.right.n.parent = NULL; 2725 | y.right = NULL; 2726 | y.min = y.left.n == null ? INF : Math.min(y.left.weight, y.left.n.min); 2727 | } 2728 | 2729 | static int find(Node x, Node y) { 2730 | expose(x); 2731 | x.flip = !x.flip; 2732 | expose(y); 2733 | int res = INF; 2734 | Node last = null; 2735 | for (Node z = x; z != y; z = z.parent.n) { 2736 | if (z.left.n != null && z != last) 2737 | res = Math.min(res, Math.min(z.left.weight, z.left.n.min)); 2738 | res = Math.min(res, z.parent.weight); 2739 | last = z.left.n; 2740 | } 2741 | return res; 2742 | } 2743 | } 2744 | package Trees; 2745 | 2746 | import java.util.ArrayList; 2747 | import java.util.Comparator; 2748 | import java.util.HashMap; 2749 | import java.util.Iterator; 2750 | 2751 | // A custom heap that is backed by a hashmap and arraylist 2752 | public class QriorityPueue { 2753 | private int size; 2754 | private ArrayList list; 2755 | private HashMap pos; 2756 | private Comparator comp; 2757 | 2758 | public QriorityPueue(Comparator comp) { 2759 | size = 0; 2760 | list = new ArrayList(); 2761 | pos = new HashMap(); 2762 | this.comp = comp; 2763 | } 2764 | 2765 | public boolean add(E e) { 2766 | if (e == null) 2767 | throw new NullPointerException(); 2768 | list.add(e); 2769 | pos.put(e, size); 2770 | bubbleUp(size, e); 2771 | size++; 2772 | return true; 2773 | } 2774 | 2775 | public E poll() { 2776 | if (size == 0) 2777 | return null; 2778 | size--; 2779 | E ret = list.get(0); 2780 | pos.remove(ret); 2781 | E last = list.get(size); 2782 | list.remove(size); 2783 | if (size != 0) 2784 | bubbleDown(0, last); 2785 | return ret; 2786 | } 2787 | 2788 | public E peek() { 2789 | if (size == 0) 2790 | return null; 2791 | return list.get(0); 2792 | } 2793 | 2794 | public boolean updateKey(E e) { 2795 | Integer ps = pos.get(e); 2796 | if (ps == null) 2797 | return false; 2798 | 2799 | // try moving it up and down 2800 | bubbleUp(ps, e); 2801 | ps = pos.get(e); 2802 | bubbleDown(ps, e); 2803 | 2804 | return true; 2805 | } 2806 | 2807 | public int size() { 2808 | return size; 2809 | } 2810 | 2811 | public boolean isEmpty() { 2812 | return size == 0; 2813 | } 2814 | 2815 | public boolean remove(E e) { 2816 | Integer ps = pos.get(e); 2817 | if (ps == null) 2818 | return false; 2819 | pos.remove(e); 2820 | size--; 2821 | E last = list.get(size); 2822 | if (size != 0) 2823 | bubbleDown(ps, last); 2824 | return true; 2825 | } 2826 | 2827 | public boolean contains(E e) { 2828 | return pos.containsKey(e); 2829 | } 2830 | 2831 | public Iterator iterator() { 2832 | return list.iterator(); 2833 | } 2834 | 2835 | private void bubbleUp(int idx, E e) { 2836 | while (idx > 0) { 2837 | int par = (idx - 1) >> 1; 2838 | E toComp = list.get(par); 2839 | if (comp.compare(e, toComp) >= 0) // greater than parent 2840 | break; 2841 | list.set(idx, toComp); 2842 | pos.put(toComp, idx); 2843 | idx = par; 2844 | } 2845 | list.set(idx, e); 2846 | pos.put(e, idx); 2847 | } 2848 | 2849 | private void bubbleDown(int idx, E e) { 2850 | int half = size >> 1; 2851 | while (idx < half) { 2852 | int next = (idx << 1) + 1, test = next + 1; 2853 | E toComp = list.get(next); 2854 | // get biggest child 2855 | if (test < size && comp.compare(toComp, list.get(test)) > 0) 2856 | toComp = list.get(next = test); 2857 | if (comp.compare(e, toComp) <= 0) // less than biggest child 2858 | break; 2859 | list.set(idx, toComp); 2860 | pos.put(toComp, idx); 2861 | idx = next; 2862 | } 2863 | list.set(idx, e); 2864 | pos.put(e, idx); 2865 | } 2866 | } 2867 | package Trees; 2868 | 2869 | public class RangeTree { 2870 | public int start, end, num; 2871 | public RangeTree child1 = null, child2 = null; 2872 | 2873 | public RangeTree (int start, int end) { 2874 | this.start = start; 2875 | this.end = end; 2876 | if (start != end) { 2877 | child1 = new RangeTree (start, (start + end) / 2); 2878 | child2 = new RangeTree ((start + end) / 2 + 1, end); 2879 | } 2880 | } 2881 | 2882 | public void insert (int ind) { 2883 | num++; 2884 | if (child1 == null) 2885 | return; 2886 | if (child1.end >= ind) 2887 | child1.insert (ind); 2888 | else 2889 | child2.insert (ind); 2890 | } 2891 | 2892 | public void delete (int ind) { 2893 | num--; 2894 | if (child1 == null) 2895 | return; 2896 | if (child1.end >= ind) 2897 | child1.delete (ind); 2898 | else 2899 | child2.delete (ind); 2900 | } 2901 | 2902 | public int query (int st, int en) { 2903 | if (start == st && end == en) 2904 | return num; 2905 | if (st > child1.end) 2906 | return child2.query (st, en); 2907 | if (en < child2.start) 2908 | return child1.query (st, en); 2909 | return child1.query (st, child1.end) + child2.query (child2.start, en); 2910 | } 2911 | 2912 | } 2913 | package Trees; 2914 | 2915 | // from Sedgewick 2916 | public class SplayTree, Value> { 2917 | 2918 | private Node root; 2919 | 2920 | private class Node { 2921 | private Key key; 2922 | private Value value; 2923 | private Node left, right; 2924 | 2925 | public Node(Key key, Value value) { 2926 | this.key = key; 2927 | this.value = value; 2928 | } 2929 | } 2930 | 2931 | public boolean contains(Key key) { 2932 | return (get(key) != null); 2933 | } 2934 | 2935 | // return value associated with the given key 2936 | // if no such value, return null 2937 | public Value get(Key key) { 2938 | root = splay(root, key); 2939 | int cmp = key.compareTo(root.key); 2940 | if (cmp == 0) return root.value; 2941 | else return null; 2942 | } 2943 | 2944 | public void put(Key key, Value value) { 2945 | // splay key to root 2946 | if (root == null) { 2947 | root = new Node(key, value); 2948 | return; 2949 | } 2950 | 2951 | root = splay(root, key); 2952 | 2953 | int cmp = key.compareTo(root.key); 2954 | 2955 | // Insert new node at root 2956 | if (cmp < 0) { 2957 | Node n = new Node(key, value); 2958 | n.left = root.left; 2959 | n.right = root; 2960 | root.left = null; 2961 | root = n; 2962 | } 2963 | 2964 | // Insert new node at root 2965 | else if (cmp > 0) { 2966 | Node n = new Node(key, value); 2967 | n.right = root.right; 2968 | n.left = root; 2969 | root.right = null; 2970 | root = n; 2971 | } 2972 | 2973 | // It was a duplicate key. Simply replace the value 2974 | else if (cmp == 0) { 2975 | root.value = value; 2976 | } 2977 | 2978 | } 2979 | 2980 | public void remove(Key key) { 2981 | if (root == null) return; // empty tree 2982 | 2983 | root = splay(root, key); 2984 | 2985 | int cmp = key.compareTo(root.key); 2986 | 2987 | if (cmp == 0) { 2988 | if (root.left == null) { 2989 | root = root.right; 2990 | } 2991 | else { 2992 | Node x = root.right; 2993 | root = root.left; 2994 | splay(root, key); 2995 | root.right = x; 2996 | } 2997 | } 2998 | 2999 | // else: it wasn't in the tree to remove 3000 | } 3001 | 3002 | private Node splay(Node h, Key key) { 3003 | if (h == null) return null; 3004 | 3005 | int cmp1 = key.compareTo(h.key); 3006 | 3007 | if (cmp1 < 0) { 3008 | if (h.left == null) { 3009 | return h; 3010 | } 3011 | int cmp2 = key.compareTo(h.left.key); 3012 | if (cmp2 < 0) { 3013 | h.left.left = splay(h.left.left, key); 3014 | h = rotateRight(h); 3015 | } 3016 | else if (cmp2 > 0) { 3017 | h.left.right = splay(h.left.right, key); 3018 | if (h.left.right != null) 3019 | h.left = rotateLeft(h.left); 3020 | } 3021 | 3022 | if (h.left == null) return h; 3023 | else return rotateRight(h); 3024 | } 3025 | 3026 | else if (cmp1 > 0) { 3027 | if (h.right == null) { 3028 | return h; 3029 | } 3030 | 3031 | int cmp2 = key.compareTo(h.right.key); 3032 | if (cmp2 < 0) { 3033 | h.right.left = splay(h.right.left, key); 3034 | if (h.right.left != null) 3035 | h.right = rotateRight(h.right); 3036 | } 3037 | else if (cmp2 > 0) { 3038 | h.right.right = splay(h.right.right, key); 3039 | h = rotateLeft(h); 3040 | } 3041 | 3042 | if (h.right == null) return h; 3043 | else return rotateLeft(h); 3044 | } 3045 | 3046 | else return h; 3047 | } 3048 | 3049 | // height of tree (1-node tree has height 0) 3050 | public int height() { return height(root); } 3051 | private int height(Node x) { 3052 | if (x == null) return -1; 3053 | return 1 + Math.max(height(x.left), height(x.right)); 3054 | } 3055 | 3056 | 3057 | public int size() { 3058 | return size(root); 3059 | } 3060 | 3061 | private int size(Node x) { 3062 | if (x == null) return 0; 3063 | else return (1 + size(x.left) + size(x.right)); 3064 | } 3065 | 3066 | // right rotate 3067 | private Node rotateRight(Node h) { 3068 | Node x = h.left; 3069 | h.left = x.right; 3070 | x.right = h; 3071 | return x; 3072 | } 3073 | 3074 | // left rotate 3075 | private Node rotateLeft(Node h) { 3076 | Node x = h.right; 3077 | h.right = x.left; 3078 | x.left = h; 3079 | return x; 3080 | } 3081 | } 3082 | package Trees; 3083 | 3084 | public class SplayTree2 { 3085 | static class Node { 3086 | int size; 3087 | Node left; 3088 | Node right; 3089 | Node parent; 3090 | boolean flip; 3091 | char id; 3092 | 3093 | public Node(char id) { 3094 | this.id = id; 3095 | this.size = 1; 3096 | left = null; 3097 | right = null; 3098 | parent = null; 3099 | } 3100 | 3101 | public String toString() { 3102 | return id + " " + size; 3103 | } 3104 | } 3105 | 3106 | static void push(Node x) { 3107 | if (!x.flip) 3108 | return; 3109 | x.flip = false; 3110 | Node t = x.left; 3111 | x.left = x.right; 3112 | x.right = t; 3113 | if (x.left != null) 3114 | x.left.flip = !x.left.flip; 3115 | if (x.right != null) 3116 | x.right.flip = !x.right.flip; 3117 | join(x); 3118 | } 3119 | 3120 | // Whether x is a root of a splay tree 3121 | static boolean isRoot(Node x) { 3122 | return x.parent == null; 3123 | } 3124 | 3125 | static void connect(Node ch, Node p, boolean leftChild) { 3126 | if (leftChild) 3127 | p.left = ch; 3128 | else 3129 | p.right = ch; 3130 | join(p); 3131 | if (ch != null) { 3132 | ch.parent = p; 3133 | } 3134 | } 3135 | 3136 | // rotate edge (x, x.parent) 3137 | static void rotate(Node x) { 3138 | Node p = x.parent; 3139 | Node g = p.parent; 3140 | boolean isRootP = isRoot(p); 3141 | boolean leftChildX = (x == p.left); 3142 | 3143 | Node next = leftChildX ? x.right : x.left; 3144 | connect(next, p, leftChildX); 3145 | connect(p, x, !leftChildX); 3146 | 3147 | if (!isRootP) 3148 | connect(x, g, p == g.left); 3149 | else 3150 | x.parent = g; 3151 | } 3152 | 3153 | static void splay(Node x) { 3154 | while (!isRoot(x)) { 3155 | Node p = x.parent; 3156 | Node g = p.parent; 3157 | if (!isRoot(p)) 3158 | push(g); 3159 | push(p); 3160 | push(x); 3161 | if (!isRoot(p)) 3162 | rotate((x == p.left) == (p == g.left) ? p : x); 3163 | rotate(x); 3164 | } 3165 | push(x); 3166 | root = x; 3167 | } 3168 | 3169 | static Node cutLeft(Node x) { 3170 | Node ret = x.left; 3171 | if (ret != null) { 3172 | x.left.parent = null; 3173 | x.left = null; 3174 | join(x); 3175 | } 3176 | return ret; 3177 | } 3178 | 3179 | static Node cutRight(Node x) { 3180 | Node ret = x.right; 3181 | if (ret != null) { 3182 | x.right.parent = null; 3183 | x.right = null; 3184 | join(x); 3185 | } 3186 | return ret; 3187 | } 3188 | 3189 | static void join(Node x) { 3190 | x.size = (x.left == null ? 0 : x.left.size) + (x.right == null ? 0 : x.right.size) + 1; 3191 | } 3192 | 3193 | private static Node getElementAtPosition(Node start, int a) { 3194 | Node cur = start; 3195 | while (a > 0) { 3196 | push(cur); 3197 | int sz = (cur.left == null ? 0 : cur.left.size); 3198 | if (a <= sz) { 3199 | cur = cur.left; 3200 | continue; 3201 | } 3202 | a -= sz + 1; 3203 | if (a == 0) 3204 | break; 3205 | cur = cur.right; 3206 | } 3207 | splay(cur); 3208 | return cur; 3209 | } 3210 | 3211 | private static char getElement(int a) { 3212 | return getElementAtPosition(root, a).id; 3213 | } 3214 | 3215 | private static void flip(int a, int b) { 3216 | if (a == b) 3217 | return; 3218 | Node right = getElementAtPosition(root, b); 3219 | Node ra = cutRight(right); 3220 | Node left = getElementAtPosition(root, a); 3221 | Node la = cutLeft(left); 3222 | splay(left); 3223 | left.flip = !left.flip; 3224 | push(left); 3225 | connect(ra, left, false); 3226 | splay(right); 3227 | connect(la, right, true); 3228 | } 3229 | 3230 | private static String s; 3231 | private static Node initRec(int start, int end) { 3232 | if (start == end) { 3233 | return new Node(s.charAt(start - 1)); 3234 | } 3235 | int mid = (start + end) >> 1; 3236 | Node x = new Node(s.charAt(mid - 1)); 3237 | if (start <= mid - 1) 3238 | connect(initRec(start, mid - 1), x, true); 3239 | if (mid + 1 <= end) 3240 | connect(initRec(mid + 1, end), x, false); 3241 | return x; 3242 | } 3243 | 3244 | private static Node root; 3245 | } --------------------------------------------------------------------------------