├── .fonts └── ttf │ ├── Consolas-Bold.ttf │ ├── Consolas-Italic.ttf │ ├── Consolas-Regular.ttf │ ├── Monaco-Bold.ttf │ ├── Monaco-Italic.ttf │ ├── Monaco-Regular.ttf │ └── NotoSansCJKtc-VF.ttf ├── README.md ├── basic ├── IncStack.cpp ├── IncStack_windows.cpp ├── ac ├── default.cpp ├── default_code.cpp ├── java-related.java ├── misc.cpp ├── python_trick.py ├── random.cpp ├── run.bat ├── run.sh ├── time.cpp ├── vimrc ├── vimrc_warner └── wa ├── codebook.pdf ├── codebook.tex ├── dataStructure ├── DisjointSet.cpp ├── DisjointSet1.cpp ├── KDTree.cpp ├── Leftist_Heap.cpp ├── LiChaoST.cpp ├── binary_indexed_tree.cpp ├── extc_bt.cpp ├── link_cut_tree.cpp ├── pairing_heap.cpp ├── seg_tree.cpp ├── seg_tree2.cpp ├── sparse_table.cpp ├── treap.cpp ├── treap_split_key&kth.cpp └── treap_test.cpp ├── flow ├── BoundedMaxflow.cpp ├── DMST.cpp ├── FlowMethod.txt ├── HLPPA.cpp ├── HLPPA2.cpp ├── Hungarian.cpp ├── HungarianUnbalanced.cpp ├── KM2.cpp ├── Kuhn_Munkres.cpp ├── MaxCostCirculation.cpp ├── MaxCostCirculationSlow.cpp ├── MinCostFlow.cpp ├── SW-mincut.cpp ├── dinic.cpp ├── dinic_BCW.cpp ├── gusfield.cpp ├── isap.cpp ├── relabelToFront.cpp ├── relabelToFront_old.cpp └── zkwflow.cpp ├── geometry ├── Area_of_Rectangles.cpp ├── CircleCover.cpp ├── ConvexHulltrick.cpp ├── ConvexHulltrick2.cpp ├── Convexhull3D.cpp ├── DelaunayTriangulation.cpp ├── DelaunayTriangulation_test.cpp ├── DynamicConvexHull.pdf ├── Half_plane_intersection.cpp ├── Half_plane_intersection_old_wrong_version.cpp ├── Intersection_of_circle_and_segment.cpp ├── Intersection_of_polygon_and_circle.cpp ├── Intersection_of_polygon_and_circle2.cpp ├── Intersection_of_two_circles.cpp ├── Intersection_of_two_lines.cpp ├── Intersection_of_two_segments.cpp ├── KD_Tree.cpp ├── KD_Tree1.cpp ├── LiChaoST.cpp ├── Minkowski_Sum.cpp ├── Points.cpp ├── Tangent_line_of_two_circles.cpp ├── convex_hull.cpp ├── definition.cpp ├── halfPlaneIntersection.cpp ├── lowerConcaveHull.cpp ├── lowerConcaveHull2.cpp ├── lowerConcaveHull3.cpp ├── mec.cpp ├── minDistOfTwoConvex.cpp ├── minDistonCuboid.cpp ├── minEnclosingBall.cpp ├── minEnclosingCircle.cpp ├── minMaxEnclosingRectangle.cpp ├── minkowski-convex-hull.cpp ├── pointInPolygon.cpp ├── polyUnion.cpp └── triangle.cpp ├── graph ├── BorrowedGeneralWeightedMatching.cpp ├── CentroidDecomposition.cpp ├── CentroidDecomposition2.cpp ├── DirectedGraphMinCycle.cpp ├── DirectedGraphMinCycle_test.cpp ├── DominatorTree.cpp ├── DynamicMST.cpp ├── HeavyLightDecomp.cpp ├── HeavyLightDecomp2.cpp ├── KSP.cpp ├── MaxClique.cpp ├── MaximalClique.cpp ├── MaximumClique.cpp ├── MinMeanCycle.cpp ├── MinimumSteinerTree.cpp ├── Minimum_General_Weighted_Matching.cpp ├── NumberofMaximalClique.cpp ├── SystemOfDifferenceConstraints.tex ├── bcc_vertex.cpp ├── eulerPath.cpp ├── generalMatching.cpp ├── generalMatching_test.cpp ├── generalWeightedGraphMaxMatching.cpp ├── graphHash.tex ├── kosaraju.cpp └── spfa.cpp ├── math ├── Bigint.cpp ├── Bigint_full.cpp ├── DiscreteKthsqrt.cpp ├── DiscreteSqrt.cpp ├── FFT.cpp ├── FWT.cpp ├── Faulhaber.cpp ├── Josephus.cpp ├── MOD.cpp ├── Martix_fast_pow.cpp ├── Miller_Rabin.cpp ├── O(1)mul.cpp ├── PolyGen.cpp ├── PolyOp_new.cpp ├── Romberg.cpp ├── SSG.cpp ├── SchreierSims.cpp ├── Simplex.cpp ├── Square_Matrix_pinv.cpp ├── Stirling_approximation.tex ├── ax+by=gcd.cpp ├── chineseRemainder.cpp ├── chineseRemainder_old.cpp ├── eigen_sys.cpp ├── gauss.cpp ├── heapSubtreeCount.cpp ├── inverse.cpp ├── linearRecurrence.cpp ├── ntt.cpp ├── ntt_old.cpp ├── phi.cpp ├── pollardRho.cpp ├── polyop.cpp ├── prefixInv.cpp ├── primes.cpp ├── rootsOfPolynomial.cpp ├── theorem.tex └── theorem_old.cpp ├── other-codebook ├── ICPC-Cheat-sheet.pdf ├── mycodebook .docx └── notebook.pdf ├── others ├── DeBrujin.cpp ├── HibertCurve.cpp ├── QQ.cpp ├── SOS_dp.cpp ├── cat.cpp ├── exactCoverSet.cpp ├── exactCoverSet_test.cpp ├── funny.cpp ├── maxtan.cpp ├── numberCount.cpp ├── sohot.png └── zeller.cpp ├── scoreboard ├── NCPCfinal2018.pdf ├── NCPCfinal2019.pdf ├── NCPCfinal2020.jpg ├── NCPCfinal2021.png ├── NCPCfinal2022.pdf ├── NCPCfinal2023.png ├── NCPCfinal2024.png ├── NCPCpreliminary2019.pdf ├── NCPCpreliminary2020.pdf ├── NCPCpreliminary2021.png ├── NCPCpreliminary2022.pdf ├── NCPCpreliminary2023.png ├── NCPCpreliminary2024.png ├── icpc2018.jpg ├── icpc2020.pdf ├── icpc2020.png ├── icpc2021.png ├── icpc2022.jpg ├── icpc2023.jpeg ├── icpc2024.png ├── topc2018.jpg ├── topc2020.pdf ├── topc2021.png ├── topc2022.png ├── topc2023.png └── topc2024.png └── string ├── Aho-Corasick.cpp ├── BWT.cpp ├── KMP.cpp ├── PalTree.cpp ├── PalTree1.cpp ├── PalTree2.cpp ├── RollingHash.cpp ├── SAIS.cpp ├── SAIS_old.cpp ├── SAM.cpp ├── SAM_test.cpp ├── Suffix_Array.cpp ├── Trie.cpp ├── bakerBird.cpp ├── cyclicLCS.cpp ├── minRotation.cpp ├── sa.cpp ├── smallest_rotation.cpp ├── zvalue.cpp └── zvalue_palindrome.cpp /.fonts/ttf/Consolas-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/.fonts/ttf/Consolas-Bold.ttf -------------------------------------------------------------------------------- /.fonts/ttf/Consolas-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/.fonts/ttf/Consolas-Italic.ttf -------------------------------------------------------------------------------- /.fonts/ttf/Consolas-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/.fonts/ttf/Consolas-Regular.ttf -------------------------------------------------------------------------------- /.fonts/ttf/Monaco-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/.fonts/ttf/Monaco-Bold.ttf -------------------------------------------------------------------------------- /.fonts/ttf/Monaco-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/.fonts/ttf/Monaco-Italic.ttf -------------------------------------------------------------------------------- /.fonts/ttf/Monaco-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/.fonts/ttf/Monaco-Regular.ttf -------------------------------------------------------------------------------- /.fonts/ttf/NotoSansCJKtc-VF.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/.fonts/ttf/NotoSansCJKtc-VF.ttf -------------------------------------------------------------------------------- /basic/IncStack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | void increase_stack_size() { 3 | const rlim_t ks = 64*1024*1024; 4 | struct rlimit rl; 5 | int res=getrlimit(RLIMIT_STACK, &rl); 6 | if(res==0){ 7 | if(rl.rlim_cur void dbg(T a, U ...b) { cerr << a << ' ', dbg(b...); } 4 | template void org(T l, T r) { while (l != r) cerr << *l++ << ' '; cerr << '\n'; } 5 | #define debug(args...) (dbg("#> (" + string(#args) + ") = (", args, ")")) 6 | #define orange(args...) (cerr << "#> [" + string(#args) + ") = ", org(args)) 7 | #else // ======== OnlineJudge ======== 8 | #pragma GCC optimize("O3,unroll-loops") 9 | #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") 10 | #define debug(...) ((void)0) 11 | #define orange(...) ((void)0) 12 | #endif 13 | template bool chmin(T &a, T b) { return b < a and (a = b, true); } 14 | template bool chmax(T &a, T b) { return b > a and (a = b, true); } -------------------------------------------------------------------------------- /basic/default_code.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | ios::sync_with_stdio(false), cin.tie(0); 6 | 7 | return 0; 8 | } -------------------------------------------------------------------------------- /basic/java-related.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.*; 3 | import java.lang.*; 4 | import java.math.*; 5 | 6 | public class filename{ 7 | static Scanner in = new Scanner(System.in); 8 | public static void main(String[] args) throws Exception { 9 | Scanner fin = new Scanner(new File("infile")); 10 | PrintWriter fout = new PrintWriter("outfile", "UTF-8"); 11 | fout.println(fin.nextLine()); 12 | fout.close(); 13 | while (in.hasNext()) { 14 | String str = in.nextLine(); // getline 15 | String stu = in.next(); // string 16 | } 17 | System.out.println("Case #" + t); 18 | System.out.printf("%d\n", 7122); 19 | int[][] d = {{7,1,2,2},{8,7}}; 20 | int g = Integer.parseInt("-123"); 21 | 22 | long f = (long)d[0][2]; 23 | 24 | List l = new ArrayList<>(); 25 | Random rg = new Random(); 26 | for (int i = 9; i >= 0; --i) { 27 | l.add(Integer.valueOf(rg.nextInt(100) + 1)); 28 | l.add(Integer.valueOf((int)(Math.random() * 100) + 1)); 29 | } 30 | Collections.sort(l, new Comparator() { 31 | public int compare(Integer a, Integer b) { return a - b; } 32 | }); 33 | for (int i = 0; i < l.size(); ++i) 34 | System.out.print(l.get(i)); 35 | 36 | Set s = new HashSet(); // TreeSet 37 | s.add("jizz"); 38 | System.out.println(s); 39 | System.out.println(s.contains("jizz")); 40 | 41 | Map m = new HashMap(); 42 | m.put("lol", 7122); 43 | System.out.println(m); 44 | for(String key: m.keySet()) 45 | System.out.println(key + " : " + m.get(key)); 46 | System.out.println(m.containsKey("lol")); 47 | System.out.println(m.containsValue(7122)); 48 | 49 | System.out.println(Math.PI); 50 | System.out.println(Math.acos(-1)); 51 | 52 | BigInteger bi = in.nextBigInteger(), bj = new BigInteger("-8787"), bk = BigInteger.valueOf(87878); 53 | int sgn = bi.signum(); // sign(bi) 54 | bi = bi.subtract(BigInteger.ONE).multiply(bj).divide(bj).and(bj).gcd(bj).max(bj).pow(87); 55 | int meow = bi.compareTo(bj); // -1 0 1 56 | String stz = "HongLongLongLong"; 57 | BigInteger b16 = new BigInteger(stz, 16); 58 | System.out.println(b16.toString(2)); 59 | } 60 | } -------------------------------------------------------------------------------- /basic/misc.cpp: -------------------------------------------------------------------------------- 1 | 編譯參數:-std=c++17 -Wall -Wshadow -fsanitize=undefined 2 | 3 | mt19937 gen(chrono::steady_clock::now().time_since_epoch().count()); 4 | int randint(int lb, int ub) 5 | { return uniform_int_distribution(lb, ub)(gen); } 6 | 7 | #define SECs ((double)clock() / CLOCKS_PER_SEC) 8 | 9 | struct KeyHasher { 10 | size_t operator()(const Key& k) const { 11 | return k.first + k.second * 100000; 12 | } }; 13 | typedef unordered_map map_t; 14 | 15 | __builtin_popcountll // 二進位有幾個1 16 | __builtin_clzll // 左起第一個1之前0的個數 17 | __builtin_parityll // 1的個數的奇偶性 18 | __builtin_mul_overflow(a,b,&h) // a*b是否溢位 19 | -------------------------------------------------------------------------------- /basic/python_trick.py: -------------------------------------------------------------------------------- 1 | int(eval(num.replace("/","//"))) # parser string num 2 | 3 | from fractions import Fraction 4 | from decimal import Decimal, getcontext 5 | getcontext().prec = 250 # set precision (MAX_PREC) 6 | getcontext().Emax = 250 # set exponent limit (MAX_EMAX) 7 | getcontext().rounding = ROUND_FLOOR # set round floor 8 | itwo,two,N = Decimal(0.5),Decimal(2),200 9 | def angle(cosT): 10 | """given cos(theta) in decimal return theta""" 11 | for i in range(N): 12 | cosT = ((cosT + 1) / two) ** itwo 13 | sinT = (1 - cosT * cosT) ** itwo 14 | return sinT * (2 ** N) 15 | pi = angle(Decimal(-1)) 16 | Fraction('3.1415926535897932').limit_denominator(1000) 17 | 18 | format(x, '0.10f') # set precision 19 | 20 | x = Fraction(1, 2), y = Fraction(1) 21 | print(x.as_integer_ratio()) # print 1/2 22 | print(x.denominator == 1) # return true if x is integer 23 | print(x.__round__()) 24 | print(float(x)) # print 0.5 -------------------------------------------------------------------------------- /basic/random.cpp: -------------------------------------------------------------------------------- 1 | mt19937 gen(0x5EED); 2 | int randint(int lb, int ub) 3 | { return uniform_int_distribution(lb, ub)(gen); } 4 | -------------------------------------------------------------------------------- /basic/run.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | :loop 4 | echo %%x 5 | python gen.py > input 6 | ac.exe < input > ac 7 | wa.exe < input > wa 8 | fc ac wa 9 | if not errorlevel 1 goto loop -------------------------------------------------------------------------------- /basic/run.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | for ((i=0;;i++)) 3 | do 4 | echo "$i" 5 | python3 gen.py > input 6 | ./ac < input > ac.out 7 | ./wa < input > wa.out 8 | diff ac.out wa.out || break 9 | done -------------------------------------------------------------------------------- /basic/time.cpp: -------------------------------------------------------------------------------- 1 | cout << 1.0 * clock() / CLOCKS_PER_SEC; 2 | -------------------------------------------------------------------------------- /basic/vimrc: -------------------------------------------------------------------------------- 1 | syn on 2 | se ai nu ru cul mouse=a 3 | se cin et ts=2 sw=2 sts=2 4 | so $VIMRUNTIME/mswin.vim 5 | colo desert 6 | se gfn=Monospace\ 14 7 | -------------------------------------------------------------------------------- /basic/vimrc_warner: -------------------------------------------------------------------------------- 1 | set nu rnu ts=4 sw=4 bs=2 ai hls cin mouse=a 2 | color default 3 | sy on 4 | inoremap { {}O 5 | inoremap jk 6 | nnoremap J 5j 7 | nnoremap K 5k 8 | nnoremap run :w!g++ -std=c++14 -DLOCAL -Wfatal-errors -o test "%" && echo "done." && time ./test -------------------------------------------------------------------------------- /basic/wa: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/basic/wa -------------------------------------------------------------------------------- /codebook.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/codebook.pdf -------------------------------------------------------------------------------- /dataStructure/DisjointSet.cpp: -------------------------------------------------------------------------------- 1 | struct DisjointSet{ 2 | // save() is like recursive 3 | // undo() is like return 4 | int n, fa[ N ], sz[ N ]; 5 | vector< pair > h; 6 | vector sp; 7 | void init( int tn ){ 8 | n=tn; 9 | for( int i = 0 ; i < n ; i ++ ){ 10 | fa[ i ]=i; 11 | sz[ i ]=1; 12 | } 13 | sp.clear(); h.clear(); 14 | } 15 | void assign( int *k, int v ){ 16 | h.PB( {k, *k} ); 17 | *k = v; 18 | } 19 | void save(){ sp.PB(SZ(h)); } 20 | void undo(){ 21 | assert(!sp.empty()); 22 | int last=sp.back(); sp.pop_back(); 23 | while( SZ(h)!=last ){ 24 | auto x=h.back(); h.pop_back(); 25 | *x.first = x.second; 26 | } } 27 | void uni( int x , int y ){ 28 | x = f( x ); y = f( y ); 29 | if( x == y ) return; 30 | if( sz[ x ] < sz[ y ] ) swap( x, y ); 31 | assign( &sz[ x ] , sz[ x ] + sz[ y ] ); 32 | assign( &fa[ y ] , x); 33 | } }dsu; 34 | -------------------------------------------------------------------------------- /dataStructure/DisjointSet1.cpp: -------------------------------------------------------------------------------- 1 | struct DisjointSet { 2 | int fa[MXN], h[MXN], top; 3 | struct Node { 4 | int x, y, fa, h; 5 | Node(int _x = 0, int _y = 0, int _fa = 0, int _h = 0) 6 | : x(_x), y(_y), fa(_fa), h(_h) {} 7 | } stk[MXN]; 8 | void init(int n) { 9 | top = 0; 10 | for (int i = 0; i <= n; i++) fa[i] = i, h[i] = 0; 11 | } 12 | int find(int x) { return x == fa[x] ? x : find(fa[x]); } 13 | void merge(int u, int v) { 14 | int x = find(u), y = find(v); 15 | if (h[x] > h[y]) swap(x, y); 16 | stk[top++] = Node(x, y, fa[x], h[y]); 17 | if (h[x] == h[y]) h[y]++; 18 | fa[x] = y; 19 | } 20 | void undo(int k=1) { //undo k times 21 | for (int i = 0; i < k; i++) { 22 | Node &it = stk[--top]; 23 | fa[it.x] = it.fa; 24 | h[it.y] = it.h; 25 | } } }dsu; 26 | -------------------------------------------------------------------------------- /dataStructure/KDTree.cpp: -------------------------------------------------------------------------------- 1 | const int MXN = 100005; 2 | struct KDTree { 3 | struct Nd { 4 | int x,y,x1,y1,x2,y2; 5 | int id,f; 6 | Nd *L, *R; 7 | }tree[MXN]; 8 | int n; 9 | Nd *root; 10 | LL dis2(int x1, int y1, int x2, int y2) { 11 | LL dx = x1-x2; LL dy = y1-y2; 12 | return dx*dx+dy*dy; 13 | } 14 | static bool cmpx(Nd& a, Nd& b){ return a.x> ip) { 17 | n = ip.size(); 18 | for (int i=0; iR) return nullptr; 27 | int M = (L+R)/2; 28 | tree[M].f = dep%2; 29 | nth_element(tree+L, tree+M, tree+R+1, 30 | tree[M].f ? cmpy : cmpx); 31 | tree[M].x1 = tree[M].x2 = tree[M].x; 32 | tree[M].y1 = tree[M].y2 = tree[M].y; 33 | 34 | tree[M].L = build_tree(L, M-1, dep+1); 35 | if (tree[M].L) { 36 | tree[M].x1 = min(tree[M].x1, tree[M].L->x1); 37 | tree[M].x2 = max(tree[M].x2, tree[M].L->x2); 38 | tree[M].y1 = min(tree[M].y1, tree[M].L->y1); 39 | tree[M].y2 = max(tree[M].y2, tree[M].L->y2); 40 | } 41 | 42 | tree[M].R = build_tree(M+1, R, dep+1); 43 | if (tree[M].R) { 44 | tree[M].x1 = min(tree[M].x1, tree[M].R->x1); 45 | tree[M].x2 = max(tree[M].x2, tree[M].R->x2); 46 | tree[M].y1 = min(tree[M].y1, tree[M].R->y1); 47 | tree[M].y2 = max(tree[M].y2, tree[M].R->y2); 48 | } 49 | return tree+M; 50 | } 51 | int touch(Nd* r, int x, int y, LL d2){ 52 | LL dis = sqrt(d2)+1; 53 | if (xx1-dis || x>r->x2+dis || 54 | yy1-dis || y>r->y2+dis) 55 | return 0; 56 | return 1; 57 | } 58 | void nearest(Nd* r, int x, int y, int &mID, LL &md2){ 59 | if (!r || !touch(r, x, y, md2)) return; 60 | LL d2 = dis2(r->x, r->y, x, y); 61 | if (d2 < md2 || (d2 == md2 && mID < r->id)) { 62 | mID = r->id; md2 = d2; 63 | } 64 | // search order depends on split dim 65 | if ((r->f == 0 && x < r->x) || 66 | (r->f == 1 && y < r->y)) { 67 | nearest(r->L, x, y, mID, md2); 68 | nearest(r->R, x, y, mID, md2); 69 | } else { 70 | nearest(r->R, x, y, mID, md2); 71 | nearest(r->L, x, y, mID, md2); 72 | } 73 | } 74 | int query(int x, int y) { 75 | int id = 1029384756; 76 | LL d2 = 102938475612345678LL; 77 | nearest(root, x, y, id, d2); 78 | return id; 79 | } 80 | }tree; 81 | -------------------------------------------------------------------------------- /dataStructure/Leftist_Heap.cpp: -------------------------------------------------------------------------------- 1 | const int MAXN = 10000; 2 | struct Node{ 3 | int num,lc,rc; 4 | Node() : num(0), lc(-1), rc(-1){} 5 | Node( int _v ) : num(_v), lc(-1), rc(-1){} 6 | }tree[ MAXN ]; 7 | int merge( int x, int y ){ 8 | if( x == -1 ) return y; 9 | if( y == -1 ) return x; 10 | if( tree[ x ].num < tree[ y ].num ) 11 | swap(x, y); 12 | tree[ x ].rc = merge(tree[ x ].rc, y); 13 | swap(tree[ x ].lc, tree[ x ].rc); 14 | return x; 15 | } 16 | /* Usage 17 | merge: root = merge(x, y) 18 | delmin: root = merge(root.lc, root.rc) 19 | */ 20 | -------------------------------------------------------------------------------- /dataStructure/LiChaoST.cpp: -------------------------------------------------------------------------------- 1 | struct LiChao_min{ 2 | struct line{ 3 | LL m, c; 4 | line(LL _m=0, LL _c=0) { m = _m; c = _c; } 5 | LL eval(LL x) { return m * x + c; } 6 | }; 7 | struct node{ 8 | node *l, *r; line f; 9 | node(line v) { f = v; l = r = NULL; } 10 | }; 11 | typedef node* pnode; 12 | pnode root; int sz; 13 | #define mid ((l+r)>>1) 14 | void insert(line &v, int l, int r, pnode &nd){ 15 | if(!nd) { nd = new node(v); return; } 16 | LL trl = nd->f.eval(l), trr = nd->f.eval(r); 17 | LL vl = v.eval(l), vr = v.eval(r); 18 | if(trl <= vl && trr <= vr) return; 19 | if(trl > vl && trr > vr) { nd->f = v; return; } 20 | if(trl > vl) swap(nd->f, v); 21 | if(nd->f.eval(mid) < v.eval(mid)) insert(v, mid + 1, r, nd->r); 22 | else swap(nd->f, v), insert(v, l, mid, nd->l); 23 | } 24 | LL query(int x, int l, int r, pnode &nd){ 25 | if(!nd) return LLONG_MAX; 26 | if(l == r) return nd->f.eval(x); 27 | if(mid >= x) return min(nd->f.eval(x), query(x, l, mid, nd->l)); 28 | return min(nd->f.eval(x), query(x, mid + 1, r, nd->r)); 29 | } 30 | /* -sz <= query_x <= sz */ 31 | void init(int _sz){ sz = _sz + 1; root = NULL; } 32 | void add_line(LL m, LL c){ line v(m, c); insert(v, -sz, sz, root); } 33 | LL query(LL x) { return query(x, -sz, sz, root); } 34 | }; 35 | -------------------------------------------------------------------------------- /dataStructure/binary_indexed_tree.cpp: -------------------------------------------------------------------------------- 1 | struct BIT{ 2 | #define lowbit(x) (x&-x) 3 | int n; 4 | vector a; 5 | BIT(int _n){ 6 | n = _n; 7 | a.clear(); a.resize(n+1, 0); 8 | } 9 | void update(int x, int v){ 10 | while(x < a.size()){ 11 | a[x] += v; 12 | x += lowbit(x); 13 | } 14 | } 15 | long long query(int x){ 16 | long long ret = 0; 17 | while(x){ 18 | ret += a[x]; 19 | x -= lowbit(x); 20 | } 21 | return ret; 22 | } 23 | long long query(int l, int r){ 24 | return query(r) - query(l-1); 25 | } 26 | int kth(int k){ 27 | int x = 0; 28 | for (int i = 1 << __lg(n); i; i >>= 1){ 29 | if (x + i <= n and k >= a[x + i]){ 30 | x += i; 31 | k -= a[x]; 32 | } 33 | } 34 | return x; 35 | } 36 | }; -------------------------------------------------------------------------------- /dataStructure/extc_bt.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace __gnu_pbds; 3 | typedef tree,rb_tree_tag,tree_order_statistics_node_update> set_t; 4 | #include 5 | typedef cc_hash_table umap_t; 6 | typedef priority_queue heap; 7 | #include 8 | using namespace __gnu_cxx; 9 | int main(){ 10 | // Insert some entries into s. 11 | set_t s; s.insert(12); s.insert(505); 12 | // The order of the keys should be: 12, 505. 13 | assert(*s.find_by_order(0) == 12); 14 | assert(*s.find_by_order(3) == 505); 15 | // The order of the keys should be: 12, 505. 16 | assert(s.order_of_key(12) == 0); 17 | assert(s.order_of_key(505) == 1); 18 | // Erase an entry. 19 | s.erase(12); 20 | // The order of the keys should be: 505. 21 | assert(*s.find_by_order(0) == 505); 22 | // The order of the keys should be: 505. 23 | assert(s.order_of_key(505) == 0); 24 | 25 | heap h1 , h2; h1.join( h2 ); 26 | 27 | rope r[ 2 ]; 28 | r[ 1 ] = r[ 0 ]; // persistenet 29 | string t = "abc"; 30 | r[ 1 ].insert( 0 , t.c_str() ); 31 | r[ 1 ].erase( 1 , 1 ); 32 | cout << r[ 1 ].substr( 0 , 2 ); 33 | } 34 | -------------------------------------------------------------------------------- /dataStructure/link_cut_tree.cpp: -------------------------------------------------------------------------------- 1 | struct Splay { 2 | static Splay nil, mem[MEM], *pmem; 3 | Splay *ch[2], *f; 4 | int val, rev, size; 5 | Splay (int _val=-1) : val(_val), rev(0), size(1) 6 | { f = ch[0] = ch[1] = &nil; } 7 | bool isr() 8 | { return f->ch[0] != this && f->ch[1] != this; } 9 | int dir() 10 | { return f->ch[0] == this ? 0 : 1; } 11 | void setCh(Splay *c, int d){ 12 | ch[d] = c; 13 | if (c != &nil) c->f = this; 14 | pull(); 15 | } 16 | void push(){ 17 | if( !rev ) return; 18 | swap(ch[0], ch[1]); 19 | if (ch[0] != &nil) ch[0]->rev ^= 1; 20 | if (ch[1] != &nil) ch[1]->rev ^= 1; 21 | rev=0; 22 | } 23 | void pull(){ 24 | size = ch[0]->size + ch[1]->size + 1; 25 | if (ch[0] != &nil) ch[0]->f = this; 26 | if (ch[1] != &nil) ch[1]->f = this; 27 | } 28 | } Splay::nil, Splay::mem[MEM], *Splay::pmem = Splay::mem; 29 | Splay *nil = &Splay::nil; 30 | void rotate(Splay *x){ 31 | Splay *p = x->f; 32 | int d = x->dir(); 33 | if (!p->isr()) p->f->setCh(x, p->dir()); 34 | else x->f = p->f; 35 | p->setCh(x->ch[!d], d); 36 | x->setCh(p, !d); 37 | p->pull(); x->pull(); 38 | } 39 | vector splayVec; 40 | void splay(Splay *x){ 41 | splayVec.clear(); 42 | for (Splay *q=x;; q=q->f){ 43 | splayVec.push_back(q); 44 | if (q->isr()) break; 45 | } 46 | reverse(begin(splayVec), end(splayVec)); 47 | for (auto it : splayVec) it->push(); 48 | while (!x->isr()) { 49 | if (x->f->isr()) rotate(x); 50 | else if (x->dir()==x->f->dir()) 51 | rotate(x->f),rotate(x); 52 | else rotate(x),rotate(x); 53 | } 54 | } 55 | int id(Splay *x) { return x - Splay::mem + 1; } 56 | Splay* access(Splay *x){ 57 | Splay *q = nil; 58 | for (;x!=nil;x=x->f){ 59 | splay(x); 60 | x->setCh(q, 1); 61 | q = x; 62 | } 63 | return q; 64 | } 65 | void chroot(Splay *x){ 66 | access(x); 67 | splay(x); 68 | x->rev ^= 1; 69 | x->push(); x->pull(); 70 | } 71 | void link(Splay *x, Splay *y){ 72 | access(x); 73 | splay(x); 74 | chroot(y); 75 | x->setCh(y, 1); 76 | } 77 | void cut_p(Splay *y) { 78 | access(y); 79 | splay(y); 80 | y->push(); 81 | y->ch[0] = y->ch[0]->f = nil; 82 | } 83 | void cut(Splay *x, Splay *y){ 84 | chroot(x); 85 | cut_p(y); 86 | } 87 | Splay* get_root(Splay *x) { 88 | access(x); 89 | splay(x); 90 | for(; x->ch[0] != nil; x = x->ch[0]) 91 | x->push(); 92 | splay(x); 93 | return x; 94 | } 95 | bool conn(Splay *x, Splay *y) { 96 | x = get_root(x); 97 | y = get_root(y); 98 | return x == y; 99 | } 100 | Splay* lca(Splay *x, Splay *y) { 101 | access(x); 102 | access(y); 103 | splay(x); 104 | if (x->f == nil) return x; 105 | else return x->f; 106 | } 107 | -------------------------------------------------------------------------------- /dataStructure/pairing_heap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace __gnu_pbds; 3 | typedef priority_queue heap; 4 | int main(){ 5 | heap h1 , h2; 6 | h1.push( 1 ); 7 | h2.push( 4 ); 8 | h1.join( h2 ); 9 | h1.size(); // 2 10 | h2.size(); // 0 11 | h1.top(); // 4 12 | } 13 | -------------------------------------------------------------------------------- /dataStructure/seg_tree.cpp: -------------------------------------------------------------------------------- 1 | struct seg_tree{ 2 | ll a[MXN],val[MXN*4],tag[MXN*4],NO_TAG=0; 3 | void push(int i,int l,int r){ 4 | if(tag[i]!=NO_TAG){ 5 | val[i]+=tag[i]; // update by tag 6 | if(l!=r){ 7 | tag[cl(i)]+=tag[i]; // push 8 | tag[cr(i)]+=tag[i]; // push 9 | } 10 | tag[i]=NO_TAG; 11 | } } 12 | void pull(int i,int l,int r){ 13 | int mid=(l+r)>>1; 14 | push(cl(i),l,mid);push(cr(i),mid+1,r); 15 | val[i]=max(val[cl(i)],val[cr(i)]); // pull 16 | } 17 | void build(int i,int l,int r){ 18 | if(l==r){ 19 | val[i]=a[l]; // set value 20 | return; 21 | } 22 | int mid=(l+r)>>1; 23 | build(cl(i),l,mid);build(cr(i),mid+1,r); 24 | pull(i,l,r); 25 | } 26 | void update(int i,int l,int r,int ql,int qr,int v){ 27 | push(i,l,r); 28 | if(ql<=l&&r<=qr){ 29 | tag[i]+=v; // update tag 30 | return; 31 | } 32 | int mid=(l+r)>>1; 33 | if(ql<=mid) update(cl(i),l,mid,ql,qr,v); 34 | if(qr>mid) update(cr(i),mid+1,r,ql,qr,v); 35 | pull(i,l,r); 36 | } 37 | ll query(int i,int l,int r,int ql,int qr){ 38 | push(i,l,r); 39 | if(ql<=l&&r<=qr) 40 | return val[i]; // update answer 41 | ll mid=(l+r)>>1,ret=0; 42 | if(ql<=mid) ret=max(ret,query(cl(i),l,mid,ql,qr)); 43 | if(qr>mid) ret=max(ret,query(cr(i),mid+1,r,ql,qr)); 44 | return ret; 45 | } }tree; -------------------------------------------------------------------------------- /dataStructure/seg_tree2.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct SegmentTree { // 1-base 3 | #define cl (i << 1) 4 | #define cr (i << 1 | 1) 5 | #define NO_TAG 0 6 | #define INF 1e9 7 | int n; 8 | vector seg, tag; 9 | SegmentTree(int _n) { 10 | n = _n; 11 | seg.resize(n * 4, NO_TAG); 12 | tag.resize(n * 4, NO_TAG); 13 | } 14 | SegmentTree(vector &arr) { 15 | n = arr.size(); 16 | seg.resize(n * 4); 17 | tag.resize(n * 4, NO_TAG); 18 | build(1, 0, n - 1, arr); 19 | } 20 | T add(T ori, T addValue){ 21 | return (ori + addValue); // range add value 22 | // return addValue; // range set value 23 | } 24 | T combine(T lhs, T rhs){ 25 | return (lhs + rhs); // query range sum 26 | // return max(lhs, rhs); // query range max 27 | } 28 | void push(int i, int l, int r) { 29 | if (tag[i] != NO_TAG) { 30 | seg[i] = add(seg[i], tag[i]); 31 | if (l != r) { 32 | tag[cl] = add(tag[cl], tag[i]); 33 | tag[cr] = add(tag[cr], tag[i]); 34 | } 35 | tag[i] = NO_TAG; 36 | } 37 | } 38 | void pull(int i, int l, int r) { 39 | int mid = (l + r) >> 1; 40 | push(cl, l, mid); 41 | push(cr, mid + 1, r); 42 | seg[i] = combine(seg[cl], seg[cr]); 43 | } 44 | void build(int i, int l, int r, vector &arr) { 45 | if (l == r) { 46 | seg[i] = arr[l]; // set value 47 | return; 48 | } 49 | int mid = (l + r) >> 1; 50 | build(cl, l, mid, arr); 51 | build(cr, mid + 1, r, arr); 52 | pull(i, l, r); 53 | } 54 | void update(int i, int l, int r, int ql, int qr, T v) { 55 | push(i, l, r); 56 | if (ql <= l && r <= qr) { 57 | tag[i] = add(tag[i], v); 58 | return; 59 | } 60 | int mid = (l + r) >> 1; 61 | if (ql <= mid) 62 | update(cl, l, mid, ql, qr, v); 63 | if (qr > mid) 64 | update(cr, mid + 1, r, ql, qr, v); 65 | pull(i, l, r); 66 | } 67 | T query(int i, int l, int r, int ql, int qr) { 68 | push(i, l, r); 69 | if (ql <= l && r <= qr) { 70 | return seg[i]; 71 | } 72 | int mid = (l + r) >> 1; 73 | T ret = NO_TAG; 74 | bool ok = false; 75 | if (ql <= mid){ 76 | ret = query(cl, l, mid, ql, qr), ok = true; 77 | } 78 | if (qr > mid){ 79 | if(ok) ret = combine(ret, query(cr, mid + 1, r, ql, qr)); 80 | else ret = query(cr, mid + 1, r, ql, qr); 81 | } 82 | return ret; 83 | } 84 | void update(int ql, int qr, T v) { 85 | update(1, 0, n - 1, ql, qr, v); 86 | } 87 | T query(int ql, int qr) { 88 | return query(1, 0, n - 1, ql, qr); 89 | } 90 | }; -------------------------------------------------------------------------------- /dataStructure/sparse_table.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct SparseTable{ 3 | #define MAXN 500005 4 | #define K 20 5 | int n; 6 | T st[K + 1][MAXN]; 7 | T add(T lhs, T rhs){ 8 | return lhs + rhs; 9 | } 10 | SparseTable(vector &arr){ 11 | n = arr.size(); 12 | copy(arr.begin(), arr.end(), st[0]); 13 | for (int i = 1; i <= K; i++) 14 | for (int j = 0; j + (1 << i) <= n; j++) 15 | st[i][j] = add(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]); 16 | } 17 | T query(int L, int R){ //assert L <= R 18 | T ret = st[0][L]; ++L; 19 | for (int i = K; i >= 0; i--) { 20 | if ((1 << i) <= R - L + 1) { 21 | ret = add(ret, st[i][L]); 22 | L += 1 << i; 23 | } 24 | } 25 | return ret; 26 | } 27 | pair less_equal(int L, int v){//sum, index 28 | T sum = st[0][L]; 29 | ++L; 30 | for (int i = K; i >= 0; i--) { 31 | if ((1 << i) <= n - L && add(sum, st[i][L]) <= v) { 32 | sum = add(sum, st[i][L]); 33 | L += (1 << i); 34 | } 35 | } 36 | return make_pair(sum, L-1); 37 | } 38 | }; -------------------------------------------------------------------------------- /dataStructure/treap.cpp: -------------------------------------------------------------------------------- 1 | struct Treap{ 2 | int sz , val , pri , tag; 3 | Treap *l , *r; 4 | Treap( int _val ){ 5 | val = _val; sz = 1; 6 | pri = rand(); l = r = NULL; tag = 0; 7 | } 8 | }; 9 | void push( Treap * a ){ 10 | if( a->tag ){ 11 | Treap *swp = a->l; a->l = a->r; a->r = swp; 12 | int swp2; 13 | if( a->l ) a->l->tag ^= 1; 14 | if( a->r ) a->r->tag ^= 1; 15 | a->tag = 0; 16 | } 17 | } 18 | int Size( Treap * a ){ return a ? a->sz : 0; } 19 | void pull( Treap * a ){ 20 | a->sz = Size( a->l ) + Size( a->r ) + 1; 21 | } 22 | Treap* merge( Treap *a , Treap *b ){ 23 | if( !a || !b ) return a ? a : b; 24 | if( a->pri > b->pri ){ 25 | push( a ); 26 | a->r = merge( a->r , b ); 27 | pull( a ); 28 | return a; 29 | }else{ 30 | push( b ); 31 | b->l = merge( a , b->l ); 32 | pull( b ); 33 | return b; 34 | } 35 | } 36 | void split( Treap *t , int k , Treap*&a , Treap*&b ){ 37 | if( !t ){ a = b = NULL; return; } 38 | push( t ); 39 | if( Size( t->l ) + 1 <= k ){ 40 | a = t; 41 | split( t->r , k - Size( t->l ) - 1 , a->r , b ); 42 | pull( a ); 43 | }else{ 44 | b = t; 45 | split( t->l , k , a , b->l ); 46 | pull( b ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /dataStructure/treap_split_key&kth.cpp: -------------------------------------------------------------------------------- 1 | struct Treap{ 2 | int sz , val , pri , tag; 3 | Treap *l , *r; 4 | Treap( int _val ){ 5 | val = _val; sz = 1; 6 | pri = rand(); l = r = NULL; tag = 0; 7 | } 8 | }; 9 | void push( Treap * a ){ 10 | if( a->tag ){ 11 | Treap *swp = a->l; a->l = a->r; a->r = swp; 12 | int swp2; 13 | if( a->l ) a->l->tag ^= 1; 14 | if( a->r ) a->r->tag ^= 1; 15 | a->tag = 0; 16 | } } 17 | inline int Size( Treap * a ){ return a ? a->sz : 0; } 18 | void pull( Treap * a ){ 19 | a->sz = Size( a->l ) + Size( a->r ) + 1; 20 | } 21 | Treap* merge( Treap *a , Treap *b ){ 22 | if( !a || !b ) return a ? a : b; 23 | if( a->pri > b->pri ){ 24 | push( a ); 25 | a->r = merge( a->r , b ); 26 | pull( a ); 27 | return a; 28 | }else{ 29 | push( b ); 30 | b->l = merge( a , b->l ); 31 | pull( b ); 32 | return b; 33 | } } 34 | void split_kth( Treap *t , int k, Treap*&a, Treap*&b ){ 35 | if( !t ){ a = b = NULL; return; } 36 | push( t ); 37 | if( Size( t->l ) + 1 <= k ){ 38 | a = t; 39 | split_kth( t->r , k - Size( t->l ) - 1 , a->r , b ); 40 | pull( a ); 41 | }else{ 42 | b = t; 43 | split_kth( t->l , k , a , b->l ); 44 | pull( b ); 45 | } } 46 | void split_key(Treap *t, int k, Treap*&a, Treap*&b){ 47 | if(!t){ a = b = NULL; return; } 48 | push(t); 49 | if(k<=t->val){ 50 | b = t; 51 | split_key(t->l,k,a,b->l); 52 | pull(b); 53 | } 54 | else{ 55 | a = t; 56 | split_key(t->r,k,a->r,b); 57 | pull(a); 58 | } } -------------------------------------------------------------------------------- /flow/BoundedMaxflow.cpp: -------------------------------------------------------------------------------- 1 | // flow use ISAP 2 | // Max flow with lower/upper bound on edges 3 | // source = 1 , sink = n 4 | int in[ N ] , out[ N ]; 5 | int l[ M ] , r[ M ] , a[ M ] , b[ M ];//0-base,a下界,b上界 6 | int solve(){ 7 | flow.init( n ); //n為點的數量,m為邊的數量,點是1-base 8 | for( int i = 0 ; i < m ; i ++ ){ 9 | in[ r[ i ] ] += a[ i ]; 10 | out[ l[ i ] ] += a[ i ]; 11 | flow.addEdge( l[ i ] , r[ i ] , b[ i ] - a[ i ] ); 12 | // flow from l[i] to r[i] must in [a[ i ], b[ i ]] 13 | } 14 | int nd = 0; 15 | for( int i = 1 ; i <= n ; i ++ ){ 16 | if( in[ i ] < out[ i ] ){ 17 | flow.addEdge( i , flow.t , out[ i ] - in[ i ] ); 18 | nd += out[ i ] - in[ i ]; 19 | } 20 | if( out[ i ] < in[ i ] ) 21 | flow.addEdge( flow.s , i , in[ i ] - out[ i ] ); 22 | } 23 | // original sink to source 24 | flow.addEdge( n , 1 , INF ); 25 | if( flow.maxflow() != nd ) 26 | return -1; // no solution 27 | int ans = flow.G[ 1 ].back().c; // source to sink 28 | flow.G[ 1 ].back().c = flow.G[ n ].back().c = 0; 29 | // take out super source and super sink 30 | for( size_t i = 0 ; i < flow.G[ flow.s ].size() ; i ++ ){ 31 | flow.G[ flow.s ][ i ].c = 0; 32 | Edge &e = flow.G[ flow.s ][ i ]; 33 | flow.G[ e.v ][ e.r ].c = 0; 34 | } 35 | for( size_t i = 0 ; i < flow.G[ flow.t ].size() ; i ++ ){ 36 | flow.G[ flow.t ][ i ].c = 0; 37 | Edge &e = flow.G[ flow.t ][ i ]; 38 | flow.G[ e.v ][ e.r ].c = 0; 39 | } 40 | flow.addEdge( flow.s , 1 , INF ); 41 | flow.addEdge( n , flow.t , INF ); 42 | flow.reset(); 43 | return ans + flow.maxflow(); 44 | } 45 | -------------------------------------------------------------------------------- /flow/DMST.cpp: -------------------------------------------------------------------------------- 1 | /* Edmond's algoirthm for Directed MST 2 | * runs in O(VE) */ 3 | const int MAXV = 10010; 4 | const int MAXE = 10010; 5 | const int INF = 2147483647; 6 | struct Edge{ 7 | int u, v, c; 8 | Edge(int x=0, int y=0, int z=0) : u(x), v(y), c(z){} 9 | }; 10 | int V, E, root; 11 | Edge edges[MAXE]; 12 | inline int newV(){ return ++ V; } 13 | inline void addEdge(int u, int v, int c) 14 | { edges[++E] = Edge(u, v, c); } 15 | bool con[MAXV]; 16 | int mnInW[MAXV], prv[MAXV], cyc[MAXV], vis[MAXV]; 17 | inline int DMST(){ 18 | fill(con, con+V+1, 0); 19 | int r1 = 0, r2 = 0; 20 | while(1){ 21 | fill(mnInW, mnInW+V+1, INF); 22 | fill(prv, prv+V+1, -1); 23 | REP(i, 1, E){ 24 | int u=edges[i].u, v=edges[i].v, c=edges[i].c; 25 | if(u != v && v != root && c < mnInW[v]) 26 | mnInW[v] = c, prv[v] = u; 27 | } 28 | fill(vis, vis+V+1, -1); 29 | fill(cyc, cyc+V+1, -1); 30 | r1 = 0; 31 | bool jf = 0; 32 | REP(i, 1, V){ 33 | if(con[i]) continue ; 34 | if(prv[i] == -1 && i != root) return -1; 35 | if(prv[i] > 0) r1 += mnInW[i]; 36 | int s; 37 | for(s = i; s != -1 && vis[s] == -1; s = prv[s]) 38 | vis[s] = i; 39 | if(s > 0 && vis[s] == i){ 40 | // get a cycle 41 | jf = 1; int v = s; 42 | do{ 43 | cyc[v] = s, con[v] = 1; 44 | r2 += mnInW[v]; v = prv[v]; 45 | }while(v != s); 46 | con[s] = 0; 47 | } } 48 | if(!jf) break ; 49 | REP(i, 1, E){ 50 | int &u = edges[i].u; 51 | int &v = edges[i].v; 52 | if(cyc[v] > 0) edges[i].c -= mnInW[edges[i].v]; 53 | if(cyc[u] > 0) edges[i].u = cyc[edges[i].u]; 54 | if(cyc[v] > 0) edges[i].v = cyc[edges[i].v]; 55 | if(u == v) edges[i--] = edges[E--]; 56 | } } 57 | return r1+r2; 58 | } 59 | -------------------------------------------------------------------------------- /flow/FlowMethod.txt: -------------------------------------------------------------------------------- 1 | Maximize c^T x subject to Ax ≤ b, x ≥ 0; 2 | with the corresponding symmetric dual problem, 3 | Minimize b^T y subject to A^T y ≥ c, y ≥ 0. 4 | 5 | Maximize c^T x subject to Ax ≤ b; 6 | with the corresponding asymmetric dual problem, 7 | Minimize b^T y subject to A^T y = c, y ≥ 0. 8 | 9 | Minimum vertex cover on bipartite graph = 10 | Maximum matching on bipartite graph 11 | 12 | Minimum edge cover on bipartite graph = 13 | vertex number - Minimum vertex cover(Maximum matching) 14 | 15 | Independent set on bipartite graph = 16 | vertex number - Minimum vertex cover(Maximum matching) 17 | 18 | 找出最小點覆蓋,做完dinic之後,從源點dfs只走還有流量的 19 | 邊,左邊沒被走到的點跟右邊被走到的點就是答案,其他點為最大獨立集 20 | 21 | Maximum density subgraph ( \sum W_e + \sum W_v ) / |V| 22 | 23 | Binary search on answer: 24 | For a fixed D, construct a Max flow model as follow: 25 | Let S be Sum of all weight( or inf) 26 | 1. from source to each node with cap = S 27 | 2. For each (u,v,w) in E, (u->v,cap=w), (v->u,cap=w) 28 | 3. For each node v, from v to sink with cap = S + 2 * D - deg[v] - 2 * (W of v) 29 | where deg[v] = \sum weight of edge associated with v 30 | If maxflow < S * |V|, D is an answer. 31 | 32 | Requiring subgraph: all vertex can be reached from source with 33 | edge whose cap > 0. 34 | -------------------------------------------------------------------------------- /flow/HLPPA.cpp: -------------------------------------------------------------------------------- 1 | /* Highest-Label Preflow Push Algorithm */ 2 | // tested with sgu-212 (more testing suggested) 3 | int n,m,src,sink; 4 | int deg[MAXN],adj[MAXN][MAXN],res[MAXN][MAXN]; // residual capacity 5 | // graph (i.e. all things above) should be constructed beforehand 6 | int ef[MAXN],ht[MAXN]; // excess flow, height 7 | int apt[MAXN]; // the next adj index to try push 8 | int htodo; // highest label to check with 9 | int hcnt[MAXN*2]; // number of nodes with height h 10 | queue ovque[MAXN*2]; // used to implement highest-label selection 11 | bool inque[MAXN]; 12 | inline void push(int v,int u) { 13 | int a=min(ef[v],res[v][u]); 14 | ef[v]-=a; ef[u]+=a; 15 | res[v][u]-=a; res[u][v]+=a; 16 | if(!inque[u]) { 17 | inque[u]=1; 18 | ovque[ht[u]].push(u); 19 | } 20 | } 21 | inline void relabel(int v) { 22 | int i,u,oldh; 23 | oldh=ht[v]; ht[v]=2*n; 24 | for(i=0;ioldh&&ht[i]::iterator it; 85 | initPreflow(); 86 | while(htodo>=0) { 87 | if(!ovque[htodo].size()) { 88 | htodo--; continue; 89 | } 90 | v=ovque[htodo].front(); 91 | ovque[htodo].pop(); 92 | inque[v]=0; 93 | discharge(v); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /flow/HLPPA2.cpp: -------------------------------------------------------------------------------- 1 | template 2 | struct HLPP { 3 | const T INF = numeric_limits::max(); 4 | struct Edge { 5 | int to, rev; T f; 6 | }; 7 | int n, s, t; 8 | vector adj[MAXN]; 9 | deque lst[MAXN]; 10 | vector gap[MAXN]; 11 | int ptr[MAXN]; 12 | T ef[MAXN]; 13 | int h[MAXN], cnt[MAXN], work, hst=0/*highest*/; 14 | void init(int _n, int _s, int _t) { 15 | n=_n+1; s = _s; t = _t; 16 | for(int i=0;i0) lst[nh].push_back(v), ptr[nh]++; 29 | } 30 | void globalRelabel() { 31 | work = 0; 32 | fill(h, h+n, n); 33 | fill(cnt, cnt+n, 0); 34 | for(int i=0; i<=hst; i++) 35 | lst[i].clear(), gap[i].clear(), ptr[i] = 0; 36 | queue q({t}); h[t] = 0; 37 | while(!q.empty()) { 38 | int v = q.front(); q.pop(); 39 | for(auto &e : adj[v]) 40 | if(h[e.to] == n && adj[e.to][e.rev].f > 0) 41 | q.push(e.to), updHeight(e.to, h[v] + 1); 42 | hst = h[v]; 43 | } } 44 | void push(int v, Edge &e) { 45 | if(ef[e.to] == 0) 46 | lst[h[e.to]].push_back(e.to), ptr[h[e.to]]++; 47 | T df = min(ef[v], e.f); 48 | e.f -= df, adj[e.to][e.rev].f += df; 49 | ef[v] -= df, ef[e.to] += df; 50 | } 51 | void discharge(int v) { 52 | int nh = n; 53 | for(auto &e : adj[v]) { 54 | if(e.f > 0) { 55 | if(h[v] == h[e.to] + 1) { 56 | push(v, e); 57 | if(ef[v] <= 0) return; 58 | } 59 | else nh = min(nh, h[e.to] + 1); 60 | } } 61 | if(cnt[h[v]] > 1) updHeight(v, nh); 62 | else { 63 | for(int i = h[v]; i < n; i++) { 64 | for(auto j : gap[i]) updHeight(j, n); 65 | gap[i].clear(), ptr[i] = 0; 66 | } } } 67 | T solve() { 68 | fill(ef, ef+n, 0); 69 | ef[s] = INF, ef[t] = -INF; 70 | globalRelabel(); 71 | for(auto &e : adj[s]) push(s, e); 72 | for(; hst >= 0; hst--) { 73 | while(!lst[hst].empty()) { 74 | int v=lst[hst].back(); lst[hst].pop_back(); 75 | discharge(v); 76 | if(work > 4 * n) globalRelabel(); 77 | } } 78 | return ef[t] + INF; 79 | } }; 80 | -------------------------------------------------------------------------------- /flow/Hungarian.cpp: -------------------------------------------------------------------------------- 1 | #define NIL -1 2 | #define INF 100000000 3 | int n,matched; 4 | int cost[MAXN][MAXN]; 5 | bool sets[MAXN]; // whether x is in set S 6 | bool sett[MAXN]; // whether y is in set T 7 | int xlabel[MAXN],ylabel[MAXN]; 8 | int xy[MAXN],yx[MAXN]; // matched with whom 9 | int slack[MAXN]; // given y: min{xlabel[x]+ylabel[y]-cost[x][y]} | x not in S 10 | int prev[MAXN]; // for augmenting matching 11 | inline void relabel() { 12 | int i,delta=INF; 13 | for(i=0;iyN) { 58 | swapxy=1; 59 | int mn=max(xN,yN); 60 | swap(xN,yN); 61 | for(i=0;i q; q.push(st); 17 | for(;;) { 18 | while(q.size()) { 19 | int x=q.front(); q.pop(); vx[x]=1; 20 | for(int y=1; y<=n; ++y) if(!vy[y]){ 21 | ll t = lx[x]+ly[y]-g[x][y]; 22 | if(t==0){ 23 | pa[y]=x; 24 | if(!my[y]){augment(y);return;} 25 | vy[y]=1, q.push(my[y]); 26 | }else if(sy[y]>t) pa[y]=x,sy[y]=t; 27 | } } 28 | ll cut = INF; 29 | for(int y=1; y<=n; ++y) 30 | if(!vy[y]&&cut>sy[y]) cut=sy[y]; 31 | for(int j=1; j<=n; ++j){ 32 | if(vx[j]) lx[j] -= cut; 33 | if(vy[j]) ly[j] += cut; 34 | else sy[j] -= cut; 35 | } 36 | for(int y=1; y<=n; ++y) if(!vy[y]&&sy[y]==0){ 37 | if(!my[y]){augment(y);return;} 38 | vy[y]=1, q.push(my[y]); 39 | } } } 40 | ll solve(){ 41 | fill(mx, mx+n+1, 0); fill(my, my+n+1, 0); 42 | fill(ly, ly+n+1, 0); fill(lx, lx+n+1, -INF); 43 | for(int x=1; x<=n; ++x) for(int y=1; y<=n; ++y) 44 | lx[x] = max(lx[x], g[x][y]); 45 | for(int x=1; x<=n; ++x) bfs(x); 46 | ll ans = 0; 47 | for(int y=1; y<=n; ++y) ans += g[my[y]][y]; 48 | return ans; 49 | } }graph; -------------------------------------------------------------------------------- /flow/Kuhn_Munkres.cpp: -------------------------------------------------------------------------------- 1 | struct KM{ 2 | // Maximum Bipartite Weighted Matching (Perfect Match) 3 | // 最小則邊權加負號,結果再加負號 4 | static const int MXN = 650; 5 | static const int INF = 2147483647; // LL 6 | int n,match[MXN],vx[MXN],vy[MXN]; 7 | int edge[MXN][MXN],lx[MXN],ly[MXN],slack[MXN]; 8 | // ^^^^ LL 9 | void init(int _n){ 10 | n = _n; 11 | for(int i=0; i edge[x][y]){ 21 | slack[y]=min(slack[y], lx[x]+ly[y]-edge[x][y]); 22 | } else { 23 | vy[y] = 1; 24 | if (match[y] == -1 || DFS(match[y])) 25 | { match[y] = x; return true; } 26 | } 27 | } 28 | return false; 29 | } 30 | int solve(){ 31 | fill(match,match+n,-1); 32 | fill(lx,lx+n,-INF); fill(ly,ly+n,0); 33 | for (int i=0; i g[ MAXN ]; 6 | int dis[ MAXN ] , prv[ MAXN ] , prve[ MAXN ]; 7 | bool vis[ MAXN ]; 8 | int ans; 9 | void init( int _n , int _m ) : n(_n), m(_m) {} 10 | void adde( int u , int v , int w , int c ) { 11 | g[ u ].push_back( { v , w , c , SZ( g[ v ] ) } ); 12 | g[ v ].push_back( { u , -w , 0 , SZ( g[ u ] )-1 } ); 13 | } 14 | bool poscyc() { 15 | fill( dis , dis+n+1 , 0 ); 16 | fill( prv , prv+n+1 , 0 ); 17 | fill( vis , vis+n+1 , 0 ); 18 | int tmp = -1; 19 | FOR( t , n+1 ) { 20 | REP( i , 1 , n ) { 21 | FOR( j , SZ( g[ i ] ) ) { 22 | Edge& e = g[ i ][ j ]; 23 | if( e.c && dis[ e.v ] < dis[ i ]+e.w ) { 24 | dis[ e.v ] = dis[ i ]+e.w; 25 | prv[ e.v ] = i; 26 | prve[ e.v ] = j; 27 | if( t == n ) { 28 | tmp = i; 29 | break; 30 | } } } } } 31 | if( tmp == -1 ) return 0; 32 | int cur = tmp; 33 | while( !vis[ cur ] ) { 34 | vis[ cur ] = 1; 35 | cur = prv[ cur ]; 36 | } 37 | int now = cur , cost = 0 , df = 100000; 38 | do{ 39 | Edge &e = g[ prv[ now ] ][ prve[ now ] ]; 40 | df = min( df , e.c ); 41 | cost += e.w; 42 | now = prv[ now ]; 43 | }while( now != cur ); 44 | ans += df*cost; now = cur; 45 | do{ 46 | Edge &e = g[ prv[ now ] ][ prve[ now ] ]; 47 | Edge &re = g[ now ][ e.r ]; 48 | e.c -= df; 49 | re.c += df; 50 | now = prv[ now ]; 51 | }while( now != cur ); 52 | return 1; 53 | } 54 | } circ; 55 | -------------------------------------------------------------------------------- /flow/MaxCostCirculationSlow.cpp: -------------------------------------------------------------------------------- 1 | /* Tested with: (more tests encouraged) 2 | * 3 | * - World Final 2011, pD - Chip Challenge */ 4 | class Edge { public: 5 | int v,u,c; 6 | Edge() {} 7 | Edge(int vi,int ui,int ci):v(vi),u(ui),c(ci) {} 8 | }; 9 | /* CONSTRUCT */ 10 | // res[][] of existing edge have to be correct 11 | int vn,deg[MAXV],adj[MAXV][MAXV]; 12 | int res[MAXV][MAXV],cost[MAXV][MAXV]; 13 | // all edges should be added into array 14 | int en; 15 | Edge ed[MAXE]; 16 | // other contruction depends 17 | /* MAX-COST CIRCULATION */ 18 | // be sure to check whether double is necessary 19 | const int inf=100000000; 20 | const double eps=1e-9; 21 | int dist[MAXV][MAXV],pred[MAXV][MAXV]; 22 | int cl,carr[MAXV]; 23 | inline void bellman_ford() { 24 | int i,j; 25 | for(j=0;j<=vn;j++) dist[0][j]=0; 26 | for(i=0;idist[i+1][u]) { 32 | dist[i+1][u]=dist[i][v]+ed[j].c; 33 | pred[i+1][u]=v; 34 | } 35 | } 36 | } 37 | } 38 | inline void trace_cycle(int end) { 39 | int v=end; 40 | ++visid; 41 | cl=0; 42 | for(int i=vn;;i--) { 43 | carr[cl++]=v; 44 | if(visited[v]==visid) break; 45 | visited[v]=visid; 46 | v=pred[i][v]; 47 | } 48 | for(int i=cl-1;i>=0;i--) { 49 | int u=carr[i],w=carr[i-1]; 50 | res[u][w]--; res[w][u]++; 51 | curcost+=cost[u][w]; 52 | if(w==v) break; 53 | } 54 | } 55 | inline bool karp_mmc() { 56 | int i,k,end; 57 | double mmc=-inf,avg; 58 | bellman_ford(); 59 | for(i=0;immc) { mmc=avg; end=i; } 66 | } 67 | if(mmc<=eps) return 0; 68 | trace_cycle(end); 69 | return 1; 70 | } 71 | inline void find_max_circulation() { 72 | while(karp_mmc()); 73 | } 74 | /* SOLVE (SAMPLE USAGE) */ 75 | inline void solve() { 76 | construct(); // TODO 77 | find_max_circulation(); 78 | } 79 | -------------------------------------------------------------------------------- /flow/MinCostFlow.cpp: -------------------------------------------------------------------------------- 1 | struct MinCostMaxFlow{ 2 | typedef int Tcost; 3 | static const int MAXV = 20010; 4 | static const int INFf = 1000000; 5 | static const Tcost INFc = 1e9; 6 | struct Edge{ 7 | int v, cap; 8 | Tcost w; 9 | int rev; 10 | Edge(){} 11 | Edge(int t2, int t3, Tcost t4, int t5) 12 | : v(t2), cap(t3), w(t4), rev(t5) {} 13 | }; 14 | int V, s, t; 15 | vector g[MAXV]; 16 | void init(int n, int _s, int _t){ 17 | V = n; s = _s; t = _t; 18 | for(int i = 0; i <= V; i++) g[i].clear(); 19 | } 20 | void addEdge(int a, int b, int cap, Tcost w){ 21 | g[a].push_back(Edge(b, cap, w, (int)g[b].size())); 22 | g[b].push_back(Edge(a, 0, -w, (int)g[a].size()-1)); 23 | } 24 | Tcost d[MAXV]; 25 | int id[MAXV], mom[MAXV]; 26 | bool inqu[MAXV]; 27 | queue q; 28 | pair solve(){ 29 | int mxf = 0; Tcost mnc = 0; 30 | while(1){ 31 | fill(d, d+1+V, INFc); 32 | fill(inqu, inqu+1+V, 0); 33 | fill(mom, mom+1+V, -1); 34 | mom[s] = s; 35 | d[s] = 0; 36 | q.push(s); inqu[s] = 1; 37 | while(q.size()){ 38 | int u = q.front(); q.pop(); 39 | inqu[u] = 0; 40 | for(int i = 0; i < (int) g[u].size(); i++){ 41 | Edge &e = g[u][i]; 42 | int v = e.v; 43 | if(e.cap > 0 && d[v] > d[u]+e.w){ 44 | d[v] = d[u]+e.w; 45 | mom[v] = u; 46 | id[v] = i; 47 | if(!inqu[v]) q.push(v), inqu[v] = 1; 48 | } } } 49 | if(mom[t] == -1) break ; 50 | int df = INFf; 51 | for(int u = t; u != s; u = mom[u]) 52 | df = min(df, g[mom[u]][id[u]].cap); 53 | for(int u = t; u != s; u = mom[u]){ 54 | Edge &e = g[mom[u]][id[u]]; 55 | e.cap -= df; 56 | g[e.v][e.rev].cap += df; 57 | } 58 | mxf += df; 59 | mnc += df*d[t]; 60 | } 61 | return {mxf,mnc}; 62 | } }flow; 63 | -------------------------------------------------------------------------------- /flow/SW-mincut.cpp: -------------------------------------------------------------------------------- 1 | // global min cut 2 | struct SW{ // O(V^3) 3 | int n,vst[MXN],del[MXN]; 4 | int edge[MXN][MXN],wei[MXN]; 5 | void init(int _n){ 6 | n = _n; FZ(edge); FZ(del); 7 | } 8 | void addEdge(int u, int v, int w){ 9 | edge[u][v] += w; edge[v][u] += w; 10 | } 11 | void search(int &s, int &t){ 12 | FZ(vst); FZ(wei); 13 | s = t = -1; 14 | while (true){ 15 | int mx=-1, cur=0; 16 | for (int i=0; i 0 && ceng[ to[ i ] ] < 0 ){ 32 | ceng[ to[ i ] ] = ceng[ sta ] + 1; 33 | que[ t ++ ] = to[ i ]; 34 | } 35 | } 36 | return ceng[ End ] != -1; 37 | } 38 | ll find( ll x , ll low ){ 39 | ll tmp = 0 , result = 0; 40 | if( x == End ) return low; 41 | for( ll i = head[ x ] ; ~i && result < low ; i = nxt[ i ] ) 42 | if( w[ i ] > 0 && ceng[ to[ i ] ] == ceng[ x ] + 1 ){ 43 | tmp = find( to[ i ] , min( w[ i ] , low - result ) ); 44 | w[ i ] -= tmp; 45 | w[ i^1 ] += tmp; 46 | result += tmp; 47 | } 48 | if( !result ) ceng[ x ] = -1; 49 | return result; 50 | } 51 | ll dinic(){ 52 | ll ans = 0 , tmp; 53 | while( bfs() ) ans += find( start , inf ); 54 | return ans; 55 | } 56 | int main(){ 57 | read(); 58 | cout << dinic() << endl; 59 | } 60 | -------------------------------------------------------------------------------- /flow/dinic_BCW.cpp: -------------------------------------------------------------------------------- 1 | struct Dinic{ 2 | struct Edge{ int v,f,re; }; 3 | int n,s,t,level[MXN]; 4 | vector E[MXN]; 5 | void init(int _n, int _s, int _t){ 6 | n = _n; s = _s; t = _t; 7 | for (int i=0; i que; 16 | que.push(s); 17 | level[s] = 0; 18 | while (!que.empty()){ 19 | int u = que.front(); que.pop(); 20 | for (auto it : E[u]){ 21 | if (it.f > 0 && level[it.v] == -1){ 22 | level[it.v] = level[u]+1; 23 | que.push(it.v); 24 | } } } 25 | return level[t] != -1; 26 | } 27 | int DFS(int u, int nf){ 28 | if (u == t) return nf; 29 | int res = 0; 30 | for (auto &it : E[u]){ 31 | if (it.f > 0 && level[it.v] == level[u]+1){ 32 | int tf = DFS(it.v, min(nf,it.f)); 33 | res += tf; nf -= tf; it.f -= tf; 34 | E[it.v][it.re].f += tf; 35 | if (nf == 0) return res; 36 | } } 37 | if (!res) level[u] = -1; 38 | return res; 39 | } 40 | int flow(int res=0){ 41 | while ( BFS() ) 42 | res += DFS(s,2147483647); 43 | return res; 44 | } }flow; 45 | -------------------------------------------------------------------------------- /flow/gusfield.cpp: -------------------------------------------------------------------------------- 1 | #define SOURCE 0 2 | #define SINK 1 3 | const unsigned int inf=4000000000u; 4 | int n,m,deg[MAXN],adj[MAXN][MAXN]; 5 | unsigned int res[MAXN][MAXN],cap[MAXN][MAXN]; 6 | int nei[MAXN],gdeg[MAXN],gadj[MAXN][MAXN]; 7 | unsigned int gres[MAXN][MAXN]; 8 | unsigned int cut[MAXN][MAXN]; 9 | unsigned int cutarr[MAXN*MAXN]; 10 | int cutn,ql,qr,que[MAXN],pred[MAXN]; 11 | unsigned int aug[MAXN]; 12 | bool cutset[MAXN]; 13 | int visited[MAXN],visid=0; 14 | inline void augment(int src,int sink) { 15 | int v=sink; unsigned a=aug[sink]; 16 | while(v!=src) { 17 | res[pred[v]][v]-=a; 18 | res[v][pred[v]]+=a; 19 | v=pred[v]; 20 | } 21 | } 22 | inline bool bfs(int src,int sink) { 23 | int i,v,u; ++visid; 24 | ql=qr=0; que[qr++]=src; 25 | visited[src]=visid; aug[src]=inf; 26 | while(ql G[MAXV*2]; 11 | int iter[MAXV*2], d[MAXV*2], gap[MAXV*2], tot; 12 | void init(int x) { 13 | tot = x+2; 14 | s = x+1, t = x+2; 15 | for(int i = 0; i <= tot; i++) { 16 | G[i].clear(); 17 | iter[i] = d[i] = gap[i] = 0; 18 | } } 19 | void addEdge(int u, int v, int c) { 20 | G[u].push_back(Edge(v, c, SZ(G[v]) )); 21 | G[v].push_back(Edge(u, 0, SZ(G[u]) - 1)); 22 | } 23 | int dfs(int p, int flow) { 24 | if(p == t) return flow; 25 | for(int &i = iter[p]; i < SZ(G[p]); i++) { 26 | Edge &e = G[p][i]; 27 | if(e.c > 0 && d[p] == d[e.v]+1) { 28 | int f = dfs(e.v, min(flow, e.c)); 29 | if(f) { 30 | e.c -= f; 31 | G[e.v][e.r].c += f; 32 | return f; 33 | } } } 34 | if( (--gap[d[p]]) == 0) d[s] = tot; 35 | else { 36 | d[p]++; 37 | iter[p] = 0; 38 | ++gap[d[p]]; 39 | } 40 | return 0; 41 | } 42 | int solve() { 43 | int res = 0; 44 | gap[0] = tot; 45 | for(res = 0; d[s] < tot; res += dfs(s, INF)); 46 | return res; 47 | } 48 | void reset() { 49 | for(int i=0;i<=tot;i++) { 50 | iter[i]=d[i]=gap[i]=0; 51 | } } }flow; 52 | -------------------------------------------------------------------------------- /flow/relabelToFront.cpp: -------------------------------------------------------------------------------- 1 | // O(N^3), 0-base 2 | struct Edge{ 3 | int from, to, cap, flow; 4 | Edge(int _from, int _to, int _cap, int _flow = 0): 5 | from(_from), to(_to), cap(_cap), flow(_flow) {} 6 | }; 7 | struct PushRelabel{ 8 | int n; 9 | vector edges; 10 | vector count, h, inQ, excess; 11 | vector > G; 12 | queue Q; 13 | PushRelabel(int _n): 14 | n(_n), count(_n<<1), G(_n), h(_n), inQ(_n), excess(_n) {} 15 | void addEdge(int from, int to, int cap) { 16 | G[from].push_back(edges.size()); 17 | edges.push_back(Edge(from, to, cap)); 18 | G[to].push_back(edges.size()); 19 | edges.push_back(Edge(to, from, 0)); 20 | } 21 | void enQueue(int u) { 22 | if(!inQ[u] && excess[u] > 0) Q.push(u), inQ[u] = true; 23 | } 24 | void Push(int EdgeIdx) { 25 | Edge & e = edges[EdgeIdx]; 26 | int toPush = min(e.cap - e.flow, excess[e.from]); 27 | if(toPush > 0 && h[e.from] > h[e.to]) { 28 | e.flow += toPush; 29 | excess[e.to] += toPush; 30 | excess[e.from] -= toPush; 31 | edges[EdgeIdx^1].flow -= toPush; 32 | enQueue(e.to); 33 | } 34 | } 35 | void Relabel(int u) { 36 | count[h[u]] -= 1; h[u] = 2*n-2; 37 | for (size_t i = 0; i < G[u].size(); ++i) { 38 | Edge & e = edges[G[u][i]]; 39 | if(e.cap > e.flow) h[u] = min(h[u], h[e.to]); 40 | } 41 | count[++h[u]] += 1; 42 | } 43 | void gapRelabel(int height) { 44 | for (int u = 0; u < n; ++u) if(h[u] >= height && h[u] < n) { 45 | count[h[u]] -= 1; 46 | count[h[u] = n] += 1; 47 | enQueue(u); 48 | } 49 | } 50 | void Discharge(int u) { 51 | for (size_t i = 0; excess[u] > 0 && i < G[u].size(); ++i) 52 | Push(G[u][i]); 53 | if(excess[u] > 0) { 54 | if(h[u] < n && count[h[u]] < 2) gapRelabel(h[u]); 55 | else Relabel(u); 56 | } 57 | else if(!Q.empty()) { // dequeue 58 | Q.pop(); 59 | inQ[u] = false; 60 | } 61 | } 62 | int solve(int src, int snk) { 63 | h[src] = n; inQ[src] = inQ[snk] = true; 64 | count[0] = n - (count[n] = 1); 65 | for (size_t i = 0; i < G[src].size(); ++i) { 66 | excess[src] += edges[G[src][i]].cap; 67 | Push(G[src][i]); 68 | } 69 | while (!Q.empty()) 70 | Discharge(Q.front()); 71 | return excess[snk]; 72 | } 73 | }; 74 | -------------------------------------------------------------------------------- /flow/relabelToFront_old.cpp: -------------------------------------------------------------------------------- 1 | /* Relabel-to-Front */ 2 | // tested with sgu-212 (more testing suggested) 3 | int n,m,layer,src,sink,lvl[MAXN]; 4 | int deg[MAXN],adj[MAXN][MAXN]; 5 | int res[MAXN][MAXN]; // residual capacity 6 | // graph (i.e. all things above) should be constructed beforehand 7 | list lst; // discharge list 8 | int ef[MAXN],ht[MAXN]; 9 | // excess flow, height 10 | int apt[MAXN]; // the next adj index to try push 11 | inline void push(int v,int u) { 12 | int a=min(ef[v],res[v][u]); 13 | ef[v]-=a; ef[u]+=a; 14 | res[v][u]-=a; res[u][v]+=a; 15 | } 16 | inline void relabel(int v) { 17 | int i,u; 18 | ht[v]=2*n; 19 | for(i=0;i::iterator it; 56 | initPreflow(); 57 | for(it=lst.begin();it!=lst.end();it++) { 58 | v=*it; oldh=ht[v]; discharge(v); 59 | if(ht[v]>oldh) { 60 | lst.push_front(v); 61 | lst.erase(it); 62 | it=lst.begin(); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /flow/zkwflow.cpp: -------------------------------------------------------------------------------- 1 | struct zkwflow{ 2 | static const int maxN=10000; 3 | struct Edge{ int v,f,re; ll w;}; 4 | int n,s,t,ptr[maxN]; bool vis[maxN]; ll dis[maxN]; 5 | vector E[maxN]; 6 | void init(int _n,int _s,int _t){ 7 | n=_n,s=_s,t=_t; 8 | for(int i=0;i q; q.push(s); dis[s]=0; 17 | while (!q.empty()){ 18 | int u=q.front(); q.pop(); vis[u]=false; 19 | for(auto &it:E[u]){ 20 | if(it.f>0&&dis[it.v]>dis[u]+it.w){ 21 | dis[it.v]=dis[u]+it.w; 22 | if(!vis[it.v]){ 23 | vis[it.v]=true; q.push(it.v); 24 | } } } } 25 | return dis[t]!=LLONG_MAX; 26 | } 27 | int DFS(int u,int nf){ 28 | if(u==t) return nf; 29 | int res=0; vis[u]=true; 30 | for(int &i=ptr[u];i<(int)E[u].size();i++){ 31 | auto &it=E[u][i]; 32 | if(it.f>0&&dis[it.v]==dis[u]+it.w&&!vis[it.v]){ 33 | int tf=DFS(it.v,min(nf,it.f)); 34 | res+=tf,nf-=tf,it.f-=tf; 35 | E[it.v][it.re].f+=tf; 36 | if(nf==0){ vis[u]=false; break; } 37 | } 38 | } 39 | return res; 40 | } 41 | pair flow(){ 42 | int flow=0; ll cost=0; 43 | while (SPFA()){ 44 | fill_n(ptr,n,0); 45 | int f=DFS(s,INT_MAX); 46 | flow+=f; cost+=dis[t]*f; 47 | } 48 | return{ flow,cost }; 49 | } // reset: do nothing 50 | } flow; 51 | -------------------------------------------------------------------------------- /geometry/Area_of_Rectangles.cpp: -------------------------------------------------------------------------------- 1 | struct AreaofRectangles{ 2 | #define cl(x) (x<<1) 3 | #define cr(x) (x<<1|1) 4 | ll n, id, sid; 5 | pair tree[MXN<<3]; // count, area 6 | vector ind; 7 | tuple scan[MXN<<1]; 8 | void pull(int i, int l, int r){ 9 | if(tree[i].first) tree[i].second = ind[r+1] - ind[l]; 10 | else if(l != r){ 11 | int mid = (l+r)>>1; 12 | tree[i].second = tree[cl(i)].second + tree[cr(i)].second; 13 | } 14 | else tree[i].second = 0; 15 | } 16 | void upd(int i, int l, int r, int ql, int qr, int v){ 17 | if(ql <= l && r <= qr){ 18 | tree[i].first += v; 19 | pull(i, l, r); return; 20 | } 21 | int mid = (l+r) >> 1; 22 | if(ql <= mid) upd(cl(i), l, mid, ql, qr, v); 23 | if(qr > mid) upd(cr(i), mid+1, r, ql, qr, v); 24 | pull(i, l, r); 25 | } 26 | void init(int _n){ 27 | n = _n; id = sid = 0; 28 | ind.clear(); ind.resize(n<<1); 29 | fill(tree, tree+(n<<2), make_pair(0, 0)); 30 | } 31 | void addRectangle(int lx, int ly, int rx, int ry){ 32 | ind[id++] = lx; ind[id++] = rx; 33 | scan[sid++] = make_tuple(ly, 1, lx, rx); 34 | scan[sid++] = make_tuple(ry, -1, lx, rx); 35 | } 36 | ll solve(){ 37 | sort(ind.begin(), ind.end()); 38 | ind.resize(unique(ind.begin(), ind.end()) - ind.begin()); 39 | sort(scan, scan + sid); 40 | ll area = 0, pre = get<0>(scan[0]); 41 | for(int i = 0; i < sid; i++){ 42 | auto [x, v, l, r] = scan[i]; 43 | area += tree[1].second * (x-pre); 44 | upd(1, 0, ind.size()-1, lower_bound(ind.begin(), ind.end(), l)-ind.begin(), lower_bound(ind.begin(),ind.end(),r)-ind.begin()-1, v); 45 | pre = x; 46 | } 47 | return area; 48 | } }rect; 49 | -------------------------------------------------------------------------------- /geometry/DynamicConvexHull.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/geometry/DynamicConvexHull.pdf -------------------------------------------------------------------------------- /geometry/Half_plane_intersection.cpp: -------------------------------------------------------------------------------- 1 | // for point or line solution, change > to >= 2 | bool onleft(Line L, Pt p) { 3 | return dcmp(L.v^(p-L.s)) > 0; 4 | } // segment should add Counterclockwise 5 | // assume that Lines intersect 6 | vector HPI(vector& L) { 7 | sort(L.begin(), L.end()); // sort by angle 8 | int n = L.size(), fir, las; 9 | Pt *p = new Pt[n]; 10 | Line *q = new Line[n]; 11 | q[fir=las=0] = L[0]; 12 | for(int i = 1 ; i < n ; i++) { 13 | while(fir < las && !onleft(L[i], p[las-1])) las--; 14 | while(fir < las && !onleft(L[i], p[fir])) fir++; 15 | q[++las] = L[i]; 16 | if(dcmp(q[las].v^q[las-1].v) == 0) { 17 | las--; 18 | if(onleft(q[las], L[i].s)) q[las] = L[i]; 19 | } 20 | if(fir < las) p[las-1] = LLIntersect(q[las-1], q[las]); 21 | } 22 | while(fir < las && !onleft(q[fir], p[las-1])) las--; 23 | if(las-fir <= 1) return {}; 24 | p[las] = LLIntersect(q[las], q[fir]); 25 | int m = 0; 26 | vector ans(las-fir+1); 27 | for(int i = fir ; i <= las ; i++) ans[m++] = p[i]; 28 | return ans; 29 | } -------------------------------------------------------------------------------- /geometry/Intersection_of_circle_and_segment.cpp: -------------------------------------------------------------------------------- 1 | bool Inter( const Pt& p1 , const Pt& p2 , Circle& cc ){ 2 | Pt dp = p2 - p1; 3 | double a = dp * dp; 4 | double b = 2 * ( dp * ( p1 - cc.O ) ); 5 | double c = cc.O * cc.O + p1 * p1 - 2 * ( cc.O * p1 ) - cc.R * cc.R; 6 | double bb4ac = b * b - 4 * a * c; 7 | return !( fabs( a ) < eps or bb4ac < 0 ); 8 | } 9 | -------------------------------------------------------------------------------- /geometry/Intersection_of_polygon_and_circle.cpp: -------------------------------------------------------------------------------- 1 | Pt ORI , info[ N ]; 2 | D r; int n; 3 | // Divides into multiple triangle, and sum up 4 | // oriented area 5 | D area2(Pt pa, Pt pb){ 6 | if( norm(pa) < norm(pb) ) swap(pa, pb); 7 | if( norm(pb) < eps ) return 0; 8 | D S, h, theta; 9 | D a = norm( pb ), b = norm( pa ), c = norm(pb - pa); 10 | D cosB = (pb * (pb - pa)) / a / c, B = acos(cosB); 11 | D cosC = (pa * pb) / a / b, C = acos(cosC); 12 | if(a > r){ 13 | S = (C/2)*r*r; 14 | h = a*b*sin(C)/c; 15 | if (h < r && B < PI/2) S -= (acos(h/r)*r*r - h*sqrt(r*r-h*h)); 16 | }else if(b > r){ 17 | theta = PI - B - asin(sin(B)/r*a); 18 | S = .5*a*r*sin(theta) + (C-theta)/2*r*r; 19 | }else S = .5*sin(C)*a*b; 20 | return S; 21 | } 22 | D area() { 23 | D S = 0; 24 | for(int i = 0; i < n; ++i) 25 | S += abs( area2(info[i], info[i + 1]) * sign( det(info[i], info[i + 1])); 26 | return fabs(S); 27 | } 28 | -------------------------------------------------------------------------------- /geometry/Intersection_of_polygon_and_circle2.cpp: -------------------------------------------------------------------------------- 1 | ld PCIntersect(vector v, Circle cir) { 2 | for(int i = 0 ; i < (int)v.size() ; ++i) v[i] = v[i] - cir.o; 3 | ld ans = 0, r = cir.r; 4 | int n = v.size(); 5 | for(int i = 0 ; i < n ; ++i) { 6 | Pt pa = v[i], pb = v[(i+1)%n]; 7 | if(norm(pa) < norm(pb)) swap(pa, pb); 8 | if(dcmp(norm(pb)) == 0) continue; 9 | ld s, h, theta; 10 | ld a = norm(pb), b = norm(pa), c = norm(pb-pa); 11 | ld cosB = (pb*(pb-pa))/a/c, B = acos(cosB); 12 | if(cosB > 1) B = 0; 13 | else if(cosB < -1) B = PI; 14 | ld cosC = (pa*pb)/a/b, C = acos(cosC); 15 | if(cosC > 1) C = 0; 16 | else if(cosC < -1) C = PI; 17 | if(a > r) { 18 | s = (C/2)*r*r; 19 | h = a*b*sin(C)/c; 20 | if(h < r && B < PI/2) s -= (acos(h/r)*r*r - h*sqrt(r*r-h*h)); 21 | } 22 | else if(b > r) { 23 | theta = PI - B - asin(sin(B)/r*a); 24 | s = 0.5*a*r*sin(theta) + (C-theta)/2*r*r; 25 | } 26 | else s = 0.5*sin(C)*a*b; 27 | ans += abs(s)*dcmp(v[i]^v[(i+1)%n]); 28 | } 29 | return abs(ans); 30 | } 31 | -------------------------------------------------------------------------------- /geometry/Intersection_of_two_circles.cpp: -------------------------------------------------------------------------------- 1 | vector interCircle( Pt o1 , D r1 , Pt o2 , D r2 ){ 2 | if( norm( o1 - o2 ) > r1 + r2 ) return {}; 3 | if( norm( o1 - o2 ) < max(r1, r2) - min(r1, r2) ) return {}; 4 | D d2 = ( o1 - o2 ) * ( o1 - o2 ); 5 | D d = sqrt(d2); 6 | if( d > r1 + r2 ) return {}; 7 | Pt u = (o1+o2)*0.5 + (o1-o2)*((r2*r2-r1*r1)/(2*d2)); 8 | D A = sqrt((r1+r2+d)*(r1-r2+d)*(r1+r2-d)*(-r1+r2+d)); 9 | Pt v = Pt( o1.Y-o2.Y , -o1.X + o2.X ) * A / (2*d2); 10 | return {u+v, u-v}; 11 | } 12 | -------------------------------------------------------------------------------- /geometry/Intersection_of_two_lines.cpp: -------------------------------------------------------------------------------- 1 | Pt LLIntersect(Line a, Line b) { 2 | Pt p1 = a.s, p2 = a.e, q1 = b.s, q2 = b.e; 3 | ld f1 = (p2-p1)^(q1-p1),f2 = (p2-p1)^(p1-q2),f; 4 | if(dcmp(f=f1+f2) == 0) 5 | return dcmp(f1)?Pt(NAN,NAN):Pt(INFINITY,INFINITY); 6 | return q1*(f2/f) + q2*(f1/f); 7 | } -------------------------------------------------------------------------------- /geometry/Intersection_of_two_segments.cpp: -------------------------------------------------------------------------------- 1 | int ori( const Pt& o , const Pt& a , const Pt& b ){ 2 | LL ret = ( a - o ) ^ ( b - o ); 3 | return (ret > 0) - (ret < 0); 4 | } 5 | // p1 == p2 || q1 == q2 need to be handled 6 | bool banana( const Pt& p1 , const Pt& p2 , 7 | const Pt& q1 , const Pt& q2 ){ 8 | if( ( ( p2 - p1 ) ^ ( q2 - q1 ) ) == 0 ){ // parallel 9 | if( ori( p1 , p2 , q1 ) ) return false; 10 | return ( ( p1 - q1 ) * ( p2 - q1 ) ) <= 0 || 11 | ( ( p1 - q2 ) * ( p2 - q2 ) ) <= 0 || 12 | ( ( q1 - p1 ) * ( q2 - p1 ) ) <= 0 || 13 | ( ( q1 - p2 ) * ( q2 - p2 ) ) <= 0; 14 | } 15 | return (ori( p1, p2, q1 ) * ori( p1, p2, q2 )<=0) && 16 | (ori( q1, q2, p1 ) * ori( q1, q2, p2 )<=0); 17 | } 18 | -------------------------------------------------------------------------------- /geometry/KD_Tree.cpp: -------------------------------------------------------------------------------- 1 | const int MXN = 100005; 2 | struct KDTree { 3 | struct Node { 4 | int x,y,x1,y1,x2,y2; 5 | int id,f; 6 | Node *L, *R; 7 | }tree[MXN]; 8 | int n; 9 | Node *root; 10 | LL dis2(int x1, int y1, int x2, int y2) { 11 | LL dx = x1-x2; 12 | LL dy = y1-y2; 13 | return dx*dx+dy*dy; 14 | } 15 | static bool cmpx(Node& a, Node& b){ return a.x> ip) { 18 | n = ip.size(); 19 | for (int i=0; iR) return nullptr; 28 | int M = (L+R)/2; 29 | tree[M].f = dep%2; 30 | nth_element(tree+L, tree+M, tree+R+1, tree[M].f ? cmpy : cmpx); 31 | tree[M].x1 = tree[M].x2 = tree[M].x; 32 | tree[M].y1 = tree[M].y2 = tree[M].y; 33 | 34 | tree[M].L = build_tree(L, M-1, dep+1); 35 | if (tree[M].L) { 36 | tree[M].x1 = min(tree[M].x1, tree[M].L->x1); 37 | tree[M].x2 = max(tree[M].x2, tree[M].L->x2); 38 | tree[M].y1 = min(tree[M].y1, tree[M].L->y1); 39 | tree[M].y2 = max(tree[M].y2, tree[M].L->y2); 40 | } 41 | tree[M].R = build_tree(M+1, R, dep+1); 42 | if (tree[M].R) { 43 | tree[M].x1 = min(tree[M].x1, tree[M].R->x1); 44 | tree[M].x2 = max(tree[M].x2, tree[M].R->x2); 45 | tree[M].y1 = min(tree[M].y1, tree[M].R->y1); 46 | tree[M].y2 = max(tree[M].y2, tree[M].R->y2); 47 | } 48 | return tree+M; 49 | } 50 | int touch(Node* r, int x, int y, LL d2){ 51 | LL dis = sqrt(d2)+1; 52 | if (xx1-dis || x>r->x2+dis || 53 | yy1-dis || y>r->y2+dis) 54 | return 0; 55 | return 1; 56 | } 57 | void nearest(Node* r, int x, int y, 58 | int &mID, LL &md2){ 59 | if (!r || !touch(r, x, y, md2)) return; 60 | LL d2 = dis2(r->x, r->y, x, y); 61 | if (d2 < md2 || (d2 == md2 && mID < r->id)) { 62 | mID = r->id; 63 | md2 = d2; 64 | } 65 | // search order depends on split dim 66 | if ((r->f == 0 && x < r->x) || 67 | (r->f == 1 && y < r->y)) { 68 | nearest(r->L, x, y, mID, md2); 69 | nearest(r->R, x, y, mID, md2); 70 | } else { 71 | nearest(r->R, x, y, mID, md2); 72 | nearest(r->L, x, y, mID, md2); 73 | } 74 | } 75 | int query(int x, int y) { 76 | int id = 1029384756; 77 | LL d2 = 102938475612345678LL; 78 | nearest(root, x, y, id, d2); 79 | return id; 80 | } 81 | }tree; -------------------------------------------------------------------------------- /geometry/KD_Tree1.cpp: -------------------------------------------------------------------------------- 1 | struct KDTree{ // O(sqrtN + K) 2 | struct Nd{ 3 | LL x[MXK],mn[MXK],mx[MXK]; 4 | int id,f; 5 | Nd *l,*r; 6 | }tree[MXN],*root; 7 | int n,k; 8 | LL dis(LL a,LL b){return (a-b)*(a-b);} 9 | LL dis(LL a[MXK],LL b[MXK]){ 10 | LL ret=0; 11 | for(int i=0;i> &ip,int _n,int _k){ 15 | n=_n,k=_k; 16 | for(int i=0;ir) return NULL; 24 | if(d==k) d=0; 25 | int m=(l+r)>>1; 26 | nth_element(tree+l,tree+m,tree+r+1,[&](const Nd &a,const Nd &b){return a.x[d]mn[i]); 34 | tree[m].mx[i]=max(tree[m].mx[i],tree[m].l->mx[i]); 35 | } } 36 | tree[m].r=build(m+1,r,d+1); 37 | if(tree[m].r){ 38 | for(int i=0;imn[i]); 40 | tree[m].mx[i]=max(tree[m].mx[i],tree[m].r->mx[i]); 41 | } } 42 | return tree+m; 43 | } 44 | LL pt[MXK],md; 45 | int mID; 46 | bool touch(Nd *r){ 47 | LL d=0; 48 | for(int i=0;imn[i]) d+=dis(pt[i],r->mn[i]); 50 | else if(pt[i]>=r->mx[i]) d+=dis(pt[i],r->mx[i]); 51 | } 52 | return dx,pt); 57 | if(tdid; 58 | nearest(pt[r->f]x[r->f]?r->l:r->r); 59 | nearest(pt[r->f]x[r->f]?r->r:r->l); 60 | } 61 | pair query(vector &_pt,LL _md=1LL<<57){ 62 | mID=-1,md=_md; 63 | copy(_pt.begin(),_pt.end(),pt); 64 | nearest(root); 65 | return {md,mID}; 66 | } }tree; -------------------------------------------------------------------------------- /geometry/LiChaoST.cpp: -------------------------------------------------------------------------------- 1 | struct LiChao_min{ 2 | struct line{ 3 | ll m,c; 4 | line(ll _m=0,ll _c=0){ m=_m; c=_c; } 5 | ll eval(ll x){ return m*x+c; } // overflow 6 | }; 7 | struct node{ 8 | node *l,*r; line f; 9 | node(line v){ f=v; l=r=NULL; } 10 | }; 11 | typedef node* pnode; 12 | pnode root; ll sz,ql,qr; 13 | #define mid ((l+r)>>1) 14 | void insert(line v,ll l,ll r,pnode &nd){ 15 | /* if(!(ql<=l&&r<=qr)){ 16 | if(!nd) nd=new node(line(0,INF)); 17 | if(ql<=mid) insert(v,l,mid,nd->l); 18 | if(qr>mid) insert(v,mid+1,r,nd->r); 19 | return; 20 | } used for adding segment */ 21 | if(!nd){ nd=new node(v); return; } 22 | ll trl=nd->f.eval(l),trr=nd->f.eval(r); 23 | ll vl=v.eval(l),vr=v.eval(r); 24 | if(trl<=vl&&trr<=vr) return; 25 | if(trl>vl&&trr>vr) { nd->f=v; return; } 26 | if(trl>vl) swap(nd->f,v); 27 | if(nd->f.eval(mid)r); 29 | else swap(nd->f,v),insert(v,l,mid,nd->l); 30 | } 31 | ll query(ll x,ll l,ll r,pnode &nd){ 32 | if(!nd) return INF; 33 | if(l==r) return nd->f.eval(x); 34 | if(mid>=x) 35 | return min(nd->f.eval(x),query(x,l,mid,nd->l)); 36 | return min(nd->f.eval(x),query(x,mid+1,r,nd->r)); 37 | } 38 | /* -sz<=ll query_x<=sz */ 39 | void init(ll _sz){ sz=_sz+1; root=NULL; } 40 | void add_line(ll m,ll c,ll l=-INF,ll r=INF){ 41 | line v(m,c); ql=l; qr=r; insert(v,-sz,sz,root); 42 | } 43 | ll query(ll x) { return query(x,-sz,sz,root); } 44 | }; -------------------------------------------------------------------------------- /geometry/Minkowski_Sum.cpp: -------------------------------------------------------------------------------- 1 | // P, Q, R(return) are counterclockwise order convex polygon 2 | vector minkowski(vector P, vector Q) { 3 | auto cmp = [&](Pt a, Pt b) { 4 | return Pt{a.y, a.x} < Pt{b.y, b.x}; 5 | }; 6 | auto reorder = [&](auto &R) { 7 | rotate(R.begin(), min_element(all(R), cmp), R.end()); 8 | R.push_back(R[0]), R.push_back(R[1]); 9 | }; 10 | const int n = P.size(), m = Q.size(); 11 | reorder(P), reorder(Q); 12 | vector R; 13 | for (int i = 0, j = 0, s; i < n || j < m; ) { 14 | R.push_back(P[i] + Q[j]); 15 | s = dcmp((P[i + 1] - P[i]) ^ (Q[j + 1] - Q[j])); 16 | if (s >= 0) i++; 17 | if (s <= 0) j++; 18 | } 19 | rotate(R.begin(), min_element(all(R)), R.end()); 20 | return R; 21 | } -------------------------------------------------------------------------------- /geometry/Points.cpp: -------------------------------------------------------------------------------- 1 | typedef double type; 2 | typedef pair Pt; 3 | typedef pair Line; 4 | typedef pair Circle; 5 | #define X first 6 | #define Y second 7 | #define O first 8 | #define R second 9 | Pt operator+( const Pt& p1 , const Pt& p2 ){ 10 | return { p1.X + p2.X , p1.Y + p2.Y }; 11 | } 12 | Pt operator-( const Pt& p1 , const Pt& p2 ){ 13 | return { p1.X - p2.X , p1.Y - p2.Y }; 14 | } 15 | Pt operator*( const Pt& tp , const type& tk ){ 16 | return { tp.X * tk , tp.Y * tk }; 17 | } 18 | Pt operator/( const Pt& tp , const type& tk ){ 19 | return { tp.X / tk , tp.Y / tk }; 20 | } 21 | type operator*( const Pt& p1 , const Pt& p2 ){ 22 | return p1.X * p2.X + p1.Y * p2.Y; 23 | } 24 | type operator^( const Pt& p1 , const Pt& p2 ){ 25 | return p1.X * p2.Y - p1.Y * p2.X; 26 | } 27 | type norm2( const Pt& tp ){ 28 | return tp * tp; 29 | } 30 | double norm( const Pt& tp ){ 31 | return sqrt( norm2( tp ) ); 32 | } 33 | Pt perp( const Pt& tp ){ 34 | return { tp.Y , -tp.X }; 35 | } 36 | -------------------------------------------------------------------------------- /geometry/Tangent_line_of_two_circles.cpp: -------------------------------------------------------------------------------- 1 | vector go( const Cir& c1 , const Cir& c2 , int sign1 ){ 2 | // sign1 = 1 for outer tang, -1 for inter tang 3 | vector ret; 4 | double d_sq = norm2( c1.O - c2.O ); 5 | if( d_sq < eps ) return ret; 6 | double d = sqrt( d_sq ); 7 | Pt v = ( c2.O - c1.O ) / d; 8 | double c = ( c1.R - sign1 * c2.R ) / d; 9 | if( c * c > 1 ) return ret; 10 | double h = sqrt( max( 0.0 , 1.0 - c * c ) ); 11 | for( int sign2 = 1 ; sign2 >= -1 ; sign2 -= 2 ){ 12 | Pt n = { v.X * c - sign2 * h * v.Y , 13 | v.Y * c + sign2 * h * v.X }; 14 | Pt p1 = c1.O + n * c1.R; 15 | Pt p2 = c2.O + n * ( c2.R * sign1 ); 16 | if( fabs( p1.X - p2.X ) < eps and 17 | fabs( p1.Y - p2.Y ) < eps ) 18 | p2 = p1 + perp( c2.O - c1.O ); 19 | ret.push_back( { p1 , p2 } ); 20 | } 21 | return ret; 22 | } 23 | -------------------------------------------------------------------------------- /geometry/convex_hull.cpp: -------------------------------------------------------------------------------- 1 | double cross(Pt o, Pt a, Pt b){ 2 | return (a-o) ^ (b-o); 3 | } 4 | vector convex_hull(vector pt){ 5 | sort(pt.begin(),pt.end()); 6 | int top=0; 7 | vector stk(2*pt.size()); 8 | for (int i=0; i<(int)pt.size(); i++){ 9 | while (top >= 2 && cross(stk[top-2],stk[top-1],pt[i]) <= 0) 10 | top--; 11 | stk[top++] = pt[i]; 12 | } 13 | for (int i=pt.size()-2, t=top+1; i>=0; i--){ 14 | while (top >= t && cross(stk[top-2],stk[top-1],pt[i]) <= 0) 15 | top--; 16 | stk[top++] = pt[i]; 17 | } 18 | stk.resize(top-1); 19 | return stk; 20 | } 21 | -------------------------------------------------------------------------------- /geometry/definition.cpp: -------------------------------------------------------------------------------- 1 | typedef long double ld; 2 | const ld eps = 1e-8; 3 | int dcmp(ld x) { 4 | if(abs(x) < eps) return 0; 5 | else return x < 0 ? -1 : 1; 6 | } 7 | struct Pt { 8 | ld x, y; 9 | Pt(ld _x=0, ld _y=0):x(_x), y(_y) {} 10 | Pt operator+(const Pt &a) const { 11 | return Pt(x+a.x, y+a.y); } 12 | Pt operator-(const Pt &a) const { 13 | return Pt(x-a.x, y-a.y); } 14 | Pt operator*(const ld &a) const { 15 | return Pt(x*a, y*a); } 16 | Pt operator/(const ld &a) const { 17 | return Pt(x/a, y/a); } 18 | ld operator*(const Pt &a) const { 19 | return x*a.x + y*a.y; } 20 | ld operator^(const Pt &a) const { 21 | return x*a.y - y*a.x; } 22 | bool operator<(const Pt &a) const { 23 | return x < a.x || (x == a.x && y < a.y); } 24 | //return dcmp(x-a.x) < 0 || (dcmp(x-a.x) == 0 && dcmp(y-a.y) < 0); } 25 | bool operator==(const Pt &a) const { 26 | return dcmp(x-a.x) == 0 && dcmp(y-a.y) == 0; } 27 | }; 28 | ld norm2(const Pt &a) { 29 | return a*a; } 30 | ld norm(const Pt &a) { 31 | return sqrt(norm2(a)); } 32 | Pt perp(const Pt &a) { 33 | return Pt(-a.y, a.x); } 34 | Pt rotate(const Pt &a, ld ang) { 35 | return Pt(a.x*cos(ang)-a.y*sin(ang), a.x*sin(ang)+a.y*cos(ang)); } 36 | struct Line { 37 | Pt s, e, v; // start, end, end-start 38 | ld ang; 39 | Line(Pt _s=Pt(0, 0), Pt _e=Pt(0, 0)):s(_s), e(_e) { v = e-s; ang = atan2(v.y, v.x); } 40 | bool operator<(const Line &L) const { 41 | return ang < L.ang; 42 | } }; 43 | struct Circle { 44 | Pt o; ld r; 45 | Circle(Pt _o=Pt(0, 0), ld _r=0):o(_o), r(_r) {} 46 | }; -------------------------------------------------------------------------------- /geometry/halfPlaneIntersection.cpp: -------------------------------------------------------------------------------- 1 | int PtSide(Pt p, Line L) { 2 | return dcmp((L.e - L.s)^(p - L.s)); 3 | } 4 | bool argcmp(const Pt &a, const Pt &b) { // arg(a) < arg(b) 5 | int f = (Pt{a.y, -a.x} > Pt{} ? 1 : -1) * (a != Pt{}); 6 | int g = (Pt{b.y, -b.x} > Pt{} ? 1 : -1) * (b != Pt{}); 7 | return f == g ? (a ^ b) > 0 : f < g; 8 | } 9 | vector HPI(vector P) { 10 | sort(P.begin(), P.end(), [&](Line l, Line m) { 11 | if (argcmp(l.v, m.v)) return true; 12 | if (argcmp(m.v, l.v)) return false; 13 | return PtSide(l.s, m) > 0; 14 | }); 15 | int n = P.size(), l = 0, r = -1; 16 | for (int i = 0; i < n; i++) { 17 | if (i and !argcmp(P[i - 1].v, P[i].v)) continue; 18 | while (l < r and PtSide(LLIntersect(P[r-1], P[r]), P[i]) <= 0) r--; 19 | while (l < r and PtSide(LLIntersect(P[l], P[l+1]), P[i]) <= 0) l++; 20 | P[++r] = P[i]; 21 | } 22 | while (l < r and PtSide(LLIntersect(P[r-1], P[r]), P[l]) <= 0) r--; 23 | while (l < r and PtSide(LLIntersect(P[l], P[l+1]), P[r]) <= 0) l++; 24 | if (r - l <= 1 or !argcmp(P[l].v, P[r].v)) 25 | return {}; // empty 26 | if (PtSide(LLIntersect(P[l], P[r]), P[l+1]) <= 0) { 27 | assert(0); 28 | return {}; // infinity 29 | } 30 | return vector(P.begin() + l, P.begin() + r + 1); 31 | } -------------------------------------------------------------------------------- /geometry/lowerConcaveHull.cpp: -------------------------------------------------------------------------------- 1 | /*maintain a "concave hull" that support the following 2 | 1. insertion of a line 3 | 2. query of height(y) on specific x on the hull 4 | ****/ 5 | /* set as needed */ 6 | typedef long double LD; 7 | const LD eps=1e-9; 8 | const LD inf=1e19; 9 | class Seg { 10 | public: 11 | LD m,c,x1,x2; // y=mx+c 12 | bool flag; 13 | Seg( 14 | LD _m,LD _c,LD _x1=-inf,LD _x2=inf,bool _flag=0) 15 | :m(_m),c(_c),x1(_x1),x2(_x2),flag(_flag) {} 16 | LD evaly(LD x) const { return m*x+c;} 17 | const bool operator<(LD x) const{return x2-eps hull; 26 | /* functions */ 27 | LD xintersection(Seg a,Seg b) 28 | { return (a.c-b.c)/(b.m-a.m); } 29 | inline set::iterator replace(set & 30 | hull,set::iterator it,Seg s) { 31 | hull.erase(it); 32 | return hull.insert(s).first; 33 | } 34 | void insert(Seg s) { 35 | // insert a line and update hull 36 | set::iterator it=hull.find(s); 37 | // check for same slope 38 | if(it!=hull.end()) { 39 | if(it->c+eps>=s.c) return; 40 | hull.erase(it); 41 | } 42 | // check if below whole hull 43 | it=hull.lower_bound(s); 44 | if(it!=hull.end()&& 45 | s.evaly(it->x1)<=it->evaly(it->x1)+eps) return; 46 | // update right hull 47 | while(it!=hull.end()) { 48 | LD x=xintersection(s,*it); 49 | if(x>=it->x2-eps) hull.erase(it++); 50 | else { 51 | s.x2=x; 52 | it=replace(hull,it,Seg(it->m,it->c,x,it->x2)); 53 | break; 54 | } 55 | } 56 | // update left hull 57 | while(it!=hull.begin()) { 58 | LD x=xintersection(s,*(--it)); 59 | if(x<=it->x1+eps) hull.erase(it++); 60 | else { 61 | s.x1=x; 62 | it=replace(hull,it,Seg(it->m,it->c,it->x1,x)); 63 | break; 64 | } 65 | } 66 | // insert s 67 | hull.insert(s); 68 | } 69 | void insert(LD m,LD c) { insert(Seg(m,c)); } 70 | LD query(LD x) { // return y @ given x 71 | set::iterator it = 72 | hull.lower_bound(Seg(0.0,0.0,x,x,1)); 73 | return it->evaly(x); 74 | } 75 | }; 76 | -------------------------------------------------------------------------------- /geometry/lowerConcaveHull2.cpp: -------------------------------------------------------------------------------- 1 | const ll is_query = -(1LL<<62); 2 | struct Line { 3 | ll m, b; 4 | mutable function succ; 5 | bool operator<(const Line& rhs) const { 6 | if (rhs.b != is_query) return m < rhs.m; 7 | const Line* s = succ(); 8 | return s ? b - s->b < (s->m - m) * rhs.m : 0; 9 | } 10 | }; // maintain upper hull for maximum 11 | struct HullDynamic : public multiset { 12 | bool bad(iterator y) { 13 | auto z = next(y); 14 | if (y == begin()) { 15 | if (z == end()) return 0; 16 | return y->m == z->m && y->b <= z->b; 17 | } 18 | auto x = prev(y); 19 | if(z==end())return y->m==x->m&&y->b<=x->b; 20 | return (x->b-y->b)*(z->m-y->m)>= 21 | (y->b-z->b)*(y->m-x->m); 22 | } 23 | void insert_line(ll m, ll b) { 24 | auto y = insert({m, b}); 25 | y->succ = [=]{return next(y)==end()?0:&*next(y);}; 26 | if(bad(y)) {erase(y); return; } 27 | while(next(y)!=end()&&bad(next(y)))erase(next(y)); 28 | while(y!=begin()&&bad(prev(y)))erase(prev(y)); 29 | } 30 | ll eval(ll x) { 31 | auto l = *lower_bound((Line) {x, is_query}); 32 | return l.m * x + l.b; 33 | } 34 | }; -------------------------------------------------------------------------------- /geometry/lowerConcaveHull3.cpp: -------------------------------------------------------------------------------- 1 | struct Line { 2 | mutable ll m, b, p; 3 | bool operator<(const Line& o) const { return m < o.m; } 4 | bool operator<(ll x) const { return p < x; } 5 | }; 6 | 7 | struct LineContainer : multiset> { 8 | // (for doubles, use inf = 1/.0, div(a,b) = a/b) 9 | const ll inf = LLONG_MAX; 10 | ll div(ll a, ll b) { // floored division 11 | return a / b - ((a ^ b) < 0 && a % b); } 12 | bool isect(iterator x, iterator y) { 13 | if (y == end()) { x->p = inf; return false; } 14 | if (x->m == y->m) x->p = x->b > y->b ? inf : -inf; 15 | else x->p = div(y->b - x->b, x->m - y->m); 16 | return x->p >= y->p; 17 | } 18 | void insert_line(ll m, ll b) { 19 | auto z = insert({m, b, 0}), y = z++, x = y; 20 | while (isect(y, z)) z = erase(z); 21 | if (x != begin() && isect(--x, y)) isect(x, y = erase(y)); 22 | while ((y = x) != begin() && (--x)->p >= y->p) 23 | isect(x, erase(y)); 24 | } 25 | ll eval(ll x) { 26 | assert(!empty()); 27 | auto l = *lower_bound(x); 28 | return l.m * x + l.b; 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /geometry/mec.cpp: -------------------------------------------------------------------------------- 1 | struct Mec{ // return pair of center and r 2 | int n; 3 | Pt p[ MXN ], cen; 4 | double r2; 5 | void init( int _n , Pt _p[] ){ 6 | n = _n; 7 | memcpy( p , _p , sizeof(Pt) * n ); 8 | } 9 | double sqr(double a){ return a*a; } 10 | Pt center(Pt p0, Pt p1, Pt p2) { 11 | Pt a = p1-p0; 12 | Pt b = p2-p0; 13 | double c1=norm2( a ) * 0.5; 14 | double c2=norm2( b ) * 0.5; 15 | double d = a ^ b; 16 | double x = p0.X + (c1 * b.Y - c2 * a.Y) / d; 17 | double y = p0.Y + (a.X * c2 - b.X * c1) / d; 18 | return Pt(x,y); 19 | } 20 | pair solve(){ 21 | random_shuffle(p,p+n); 22 | r2=0; 23 | for (int i=0; iQ[mx].y) mx=i; 5 | P[n]=P[0]; Q[m]=Q[0]; 6 | for (int i=0;i((Q[mx]-P[mn+1])^(P[mn]-P[mn+1]))) mx=(mx+1)%m; 8 | if(tmp<0) // pt to segment distance 9 | ans=min(ans,dis(Line(P[mn],P[mn+1]),Q[mx])); 10 | else // segment to segment distance 11 | ans=min(ans,dis(Line(P[mn],P[mn+1]),Line(Q[mx],Q[mx+1]))); 12 | mn=(mn+1)%n; 13 | } 14 | return ans; 15 | } -------------------------------------------------------------------------------- /geometry/minDistonCuboid.cpp: -------------------------------------------------------------------------------- 1 | typedef LL T; 2 | T r; 3 | void turn(T i, T j, T x, T y, T z, 4 | T x0, T y0, T L, T W, T H) { 5 | if (z==0) { T R = x*x+y*y; if (R=0 && i< 2) turn(i+1, j, x0+L+z, y, x0+L-x, 7 | x0+L, y0, H, W, L); 8 | if(j>=0 && j< 2) turn(i, j+1, x, y0+W+z, y0+W-y, 9 | x0, y0+W, L, H, W); 10 | if(i<=0 && i>-2) turn(i-1, j, x0-z, y, x-x0, 11 | x0-H, y0, H, W, L); 12 | if(j<=0 && j>-2) turn(i, j-1, x, y0-z, y-y0, 13 | x0, y0-H, L, H, W); 14 | } 15 | T solve(T L, T W, T H, 16 | T x1, T y1, T z1, T x2, T y2, T z2){ 17 | if( z1!=0 && z1!=H ){ 18 | if( y1==0 || y1==W ) 19 | swap(y1,z1), swap(y2,z2), swap(W,H); 20 | else swap(x1,z1), swap(x2,z2), swap(L,H); 21 | } 22 | if (z1==H) z1=0, z2=H-z2; 23 | r=INF; turn(0,0,x2-x1,y2-y1,z2,-x1,-y1,L,W,H); 24 | return r; 25 | } 26 | -------------------------------------------------------------------------------- /geometry/minEnclosingBall.cpp: -------------------------------------------------------------------------------- 1 | // Pt : { x , y , z } 2 | #define N 202020 3 | int n, nouter; Pt pt[ N ], outer[4], res; 4 | double radius,tmp; 5 | void ball() { 6 | Pt q[3]; double m[3][3], sol[3], L[3], det; 7 | int i,j; res.x = res.y = res.z = radius = 0; 8 | switch ( nouter ) { 9 | case 1: res=outer[0]; break; 10 | case 2: res=(outer[0]+outer[1])/2; radius=norm2(res, outer[0]); break; 11 | case 3: 12 | for (i=0; i<2; ++i) q[i]=outer[i+1]-outer[0]; 13 | for (i=0; i<2; ++i) for(j=0; j<2; ++j) m[i][j]=(q[i] * q[j])*2; 14 | for (i=0; i<2; ++i) sol[i]=(q[i] * q[i]); 15 | if (fabs(det=m[0][0]*m[1][1]-m[0][1]*m[1][0]) eps ){ 48 | outer[ nouter ++ ] = pt[ i ]; minball(i); --nouter; 49 | if(i>0){ Pt Tt = pt[i]; 50 | memmove(&pt[1], &pt[0], sizeof(Pt)*i); pt[0]=Tt; 51 | }}} 52 | double solve(){ 53 | // n points in pt 54 | random_shuffle(pt, pt+n); radius=-1; 55 | for(int i=0;ieps) 56 | nouter=1, outer[0]=pt[i], minball(i); 57 | return sqrt(radius); 58 | } 59 | -------------------------------------------------------------------------------- /geometry/minEnclosingCircle.cpp: -------------------------------------------------------------------------------- 1 | /* minimum enclosing circle */ 2 | int n; 3 | Pt p[ N ]; 4 | const Circle circumcircle(Pt a,Pt b,Pt c){ 5 | Circle cir; 6 | double fa,fb,fc,fd,fe,ff,dx,dy,dd; 7 | if( iszero( ( b - a ) ^ ( c - a ) ) ){ 8 | if( ( ( b - a ) * ( c - a ) ) <= 0 ) 9 | return Circle((b+c)/2,norm(b-c)/2); 10 | if( ( ( c - b ) * ( a - b ) ) <= 0 ) 11 | return Circle((c+a)/2,norm(c-a)/2); 12 | if( ( ( a - c ) * ( b - c ) ) <= 0 ) 13 | return Circle((a+b)/2,norm(a-b)/2); 14 | }else{ 15 | fa=2*(a.x-b.x); 16 | fb=2*(a.y-b.y); 17 | fc=norm2(a)-norm2(b); 18 | fd=2*(a.x-c.x); 19 | fe=2*(a.y-c.y); 20 | ff=norm2(a)-norm2(c); 21 | dx=fc*fe-ff*fb; 22 | dy=fa*ff-fd*fc; 23 | dd=fa*fe-fd*fb; 24 | cir.o=Pt(dx/dd,dy/dd); 25 | cir.r=norm(a-cir.o); 26 | return cir; 27 | } 28 | } 29 | inline Circle mec(int fixed,int num){ 30 | int i; 31 | Circle cir; 32 | if(fixed==3) return circumcircle(p[0],p[1],p[2]); 33 | cir=circumcircle(p[0],p[0],p[1]); 34 | for(i=fixed;i minkowski(vector p, vector q){ 2 | int n = p.size() , m = q.size(); 3 | Pt c = Pt(0, 0); 4 | for( int i = 0; i < m; i ++) c = c + q[i]; 5 | c = c / m; 6 | for( int i = 0; i < m; i ++) q[i] = q[i] - c; 7 | int cur = -1; 8 | for( int i = 0; i < m; i ++) 9 | if( (q[i] ^ (p[0] - p[n-1])) > -eps) 10 | if( cur == -1 || (q[i] ^ (p[0] - p[n-1])) > 11 | (q[cur] ^ (p[0] - p[n-1])) ) 12 | cur = i; 13 | vector h; 14 | p.push_back(p[0]); 15 | for( int i = 0; i < n; i ++) 16 | while( true ){ 17 | h.push_back(p[i] + q[cur]); 18 | int nxt = (cur + 1 == m ? 0 : cur + 1); 19 | if((q[cur] ^ (p[i+1] - p[i])) < -eps) cur = nxt; 20 | else if( (q[nxt] ^ (p[i+1] - p[i])) > 21 | (q[cur] ^ (p[i+1] - p[i])) ) cur = nxt; 22 | else break; 23 | } 24 | for(auto &&i : h) i = i + c; 25 | return convex_hull(h); 26 | } 27 | -------------------------------------------------------------------------------- /geometry/pointInPolygon.cpp: -------------------------------------------------------------------------------- 1 | int ptInPoly(vector ps,Pt p){ 2 | int c=0; 3 | for(int i=0;ips[b].y) swap(a,b); 10 | if(ps[a].y<=p.y&&p.y> py){ //py[0~n-1] must be filled 7 | int n = py.size(); 8 | int i,j,ii,jj,ta,tb,r,d; double z,w,s,sum=0,tc,td,area; 9 | vector> c; 10 | for(i=0;i0&&j=0 && tb<0){ 31 | tc=tri(py[j][jj],py[j][jj+1],py[i][ii]); 32 | td=tri(py[j][jj],py[j][jj+1],py[i][ii+1]); 33 | c.emplace_back(tc/(tc-td),1); 34 | }else if(ta<0 && tb>=0){ 35 | tc=tri(py[j][jj],py[j][jj+1],py[i][ii]); 36 | td=tri(py[j][jj],py[j][jj+1],py[i][ii+1]); 37 | c.emplace_back(tc/(tc-td),-1); 38 | } } } 39 | sort(c.begin(),c.end()); 40 | z=min(max(c[0].first,0.0),1.0); d=c[0].second; s=0; 41 | for(j=1;j adj[N]; 2 | int p[N], vis[N]; 3 | int sz[N], M[N]; // subtree size of u and M(u) 4 | 5 | inline void maxify(int &x, int y) { x = max(x, y); } 6 | int centroidDecomp(int x) { 7 | vector q; 8 | { // bfs 9 | size_t pt = 0; 10 | q.push_back(x); 11 | p[x] = -1; 12 | while (pt < q.size()) { 13 | int now = q[pt++]; 14 | sz[now] = 1; 15 | M[now] = 0; 16 | for (auto &nxt : adj[now]) 17 | if (!vis[nxt] && nxt != p[now]) 18 | q.push_back(nxt), p[nxt] = now; 19 | } 20 | } 21 | 22 | // calculate subtree size in reverse order 23 | reverse(q.begin(), q.end()); 24 | for (int &nd : q) 25 | if (p[nd] != -1) { 26 | sz[p[nd]] += sz[nd]; 27 | maxify(M[p[nd]], sz[nd]); 28 | } 29 | for (int &nd : q) 30 | maxify(M[nd], (int)q.size() - sz[nd]); 31 | 32 | // find centroid 33 | int centroid = *min_element(q.begin(), q.end(), 34 | [&](int x, int y) { return M[x] < M[y]; }); 35 | 36 | vis[centroid] = 1; 37 | for (auto &nxt : adj[centroid]) if (!vis[nxt]) 38 | centroidDecomp(nxt); 39 | return centroid; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /graph/CentroidDecomposition2.cpp: -------------------------------------------------------------------------------- 1 | struct CentroidDecomposition { 2 | int n; 3 | vector> G, out; 4 | vector sz, v; 5 | CentroidDecomposition(int _n) : n(_n), G(_n), out(_n), sz(_n), v(_n) {} 6 | int dfs(int x, int par){ 7 | sz[x] = 1; 8 | for (auto &&i : G[x]) { 9 | if(i == par || v[i]) continue; 10 | sz[x] += dfs(i, x); 11 | } 12 | return sz[x]; 13 | } 14 | int search_centroid(int x, int p, const int mid){ 15 | for (auto &&i : G[x]) { 16 | if(i == p || v[i]) continue; 17 | if(sz[i] > mid) return search_centroid(i, x, mid); 18 | } 19 | return x; 20 | } 21 | void add_edge(int l, int r){ 22 | G[l].PB(r); G[r].PB(l); 23 | } 24 | int get(int x){ 25 | int centroid = search_centroid(x, -1, dfs(x, -1)/2); 26 | v[centroid] = true; 27 | for (auto &&i : G[centroid]) { 28 | if(!v[i]) out[centroid].PB(get(i)); 29 | } 30 | v[centroid] = false; 31 | return centroid; 32 | } }; -------------------------------------------------------------------------------- /graph/DominatorTree.cpp: -------------------------------------------------------------------------------- 1 | struct DominatorTree{ // O(N) 2 | #define REP(i,s,e) for(int i=(s);i<=(e);i++) 3 | #define REPD(i,s,e) for(int i=(s);i>=(e);i--) 4 | int n , s; 5 | vector< int > g[ MAXN ] , pred[ MAXN ]; 6 | vector< int > cov[ MAXN ]; 7 | int dfn[ MAXN ] , nfd[ MAXN ] , ts; 8 | int par[ MAXN ]; //idom[u] s到u的最後一個必經點 9 | int sdom[ MAXN ] , idom[ MAXN ]; 10 | int mom[ MAXN ] , mn[ MAXN ]; 11 | inline bool cmp( int u , int v ) 12 | { return dfn[ u ] < dfn[ v ]; } 13 | int eval( int u ){ 14 | if( mom[ u ] == u ) return u; 15 | int res = eval( mom[ u ] ); 16 | if(cmp( sdom[ mn[ mom[ u ] ] ] , sdom[ mn[ u ] ] )) 17 | mn[ u ] = mn[ mom[ u ] ]; 18 | return mom[ u ] = res; 19 | } 20 | void init( int _n , int _s ){ 21 | ts = 0; n = _n; s = _s; 22 | REP( i, 1, n ) g[ i ].clear(), pred[ i ].clear(); 23 | } 24 | void addEdge( int u , int v ){ 25 | g[ u ].push_back( v ); 26 | pred[ v ].push_back( u ); 27 | } 28 | void dfs( int u ){ 29 | ts++; 30 | dfn[ u ] = ts; 31 | nfd[ ts ] = u; 32 | for( int v : g[ u ] ) if( dfn[ v ] == 0 ){ 33 | par[ v ] = u; 34 | dfs( v ); 35 | } } 36 | void build(){ 37 | REP( i , 1 , n ){ 38 | dfn[ i ] = nfd[ i ] = 0; 39 | cov[ i ].clear(); 40 | mom[ i ] = mn[ i ] = sdom[ i ] = i; 41 | } 42 | dfs( s ); 43 | REPD( i , n , 2 ){ 44 | int u = nfd[ i ]; 45 | if( u == 0 ) continue ; 46 | for( int v : pred[ u ] ) if( dfn[ v ] ){ 47 | eval( v ); 48 | if( cmp( sdom[ mn[ v ] ] , sdom[ u ] ) ) 49 | sdom[ u ] = sdom[ mn[ v ] ]; 50 | } 51 | cov[ sdom[ u ] ].push_back( u ); 52 | mom[ u ] = par[ u ]; 53 | for( int w : cov[ par[ u ] ] ){ 54 | eval( w ); 55 | if( cmp( sdom[ mn[ w ] ] , par[ u ] ) ) 56 | idom[ w ] = mn[ w ]; 57 | else idom[ w ] = par[ u ]; 58 | } 59 | cov[ par[ u ] ].clear(); 60 | } 61 | REP( i , 2 , n ){ 62 | int u = nfd[ i ]; 63 | if( u == 0 ) continue ; 64 | if( idom[ u ] != sdom[ u ] ) 65 | idom[ u ] = idom[ idom[ u ] ]; 66 | } } }domT; 67 | -------------------------------------------------------------------------------- /graph/DynamicMST.cpp: -------------------------------------------------------------------------------- 1 | /* Dynamic MST O( Q lg^2 Q ) 2 | (qx[i], qy[i])->chg weight of edge No.qx[i] to qy[i] 3 | delete an edge: (i, \infty) 4 | add an edge: change from \infty to specific value */ 5 | const int SZ=M+3*MXQ; 6 | int a[N],*tz; 7 | int find(int xx){ 8 | int root=xx; while(a[root]) root=a[root]; 9 | int next; while((next=a[xx])){a[xx]=root; xx=next; } 10 | return root; 11 | } 12 | bool cmp(int aa,int bb){ return tz[aa]= (e); i--) 3 | const int MAXN = 100010; 4 | const int LOG = 19; 5 | struct HLD{ 6 | int n; 7 | vector g[MAXN]; 8 | int sz[MAXN], dep[MAXN]; 9 | int ts, tid[MAXN], tdi[MAXN], tl[MAXN], tr[MAXN]; 10 | // ts : timestamp , useless after yutruli 11 | // tid[ u ] : pos. of node u in the seq. 12 | // tdi[ i ] : node at pos i of the seq. 13 | // tl , tr[ u ] : subtree interval in the seq. of node u 14 | int prt[MAXN][LOG], head[MAXN]; 15 | // head[ u ] : head of the chain contains u 16 | void dfssz(int u, int p){ 17 | dep[u] = dep[p] + 1; 18 | prt[u][0] = p; sz[u] = 1; head[u] = u; 19 | for(int& v:g[u]) if(v != p){ 20 | dep[v] = dep[u] + 1; 21 | dfssz(v, u); 22 | sz[u] += sz[v]; 23 | } 24 | } 25 | void dfshl(int u){ 26 | ts++; 27 | tid[u] = tl[u] = tr[u] = ts; 28 | tdi[tid[u]] = u; 29 | sort(ALL(g[u]), 30 | [&](int a, int b){return sz[a] > sz[b];}); 31 | bool flag = 1; 32 | for(int& v:g[u]) if(v != prt[u][0]){ 33 | if(flag) head[v] = head[u], flag = 0; 34 | dfshl(v); 35 | tr[u] = tr[v]; 36 | } 37 | } 38 | inline int lca(int a, int b){ 39 | if(dep[a] > dep[b]) swap(a, b); 40 | int diff = dep[b] - dep[a]; 41 | REPD(k, LOG-1, 0) if(diff & (1< getPath( int u , int v ){ 65 | vector< PII > res; 66 | while( tid[ u ] < tid[ head[ v ] ] ){ 67 | res.push_back( PII(tid[ head[ v ] ] , tid[ v ]) ); 68 | v = prt[ head[ v ] ][ 0 ]; 69 | } 70 | res.push_back( PII( tid[ u ] , tid[ v ] ) ); 71 | reverse( ALL( res ) ); 72 | return res; 73 | /* res : list of intervals from u to v 74 | * u must be ancestor of v 75 | * usage : 76 | * vector< PII >& path = tree.getPath( u , v ) 77 | * for( PII tp : path ) { 78 | * int l , r;tie( l , r ) = tp; 79 | * upd( l , r ); 80 | * uu = tree.tdi[ l ] , vv = tree.tdi[ r ]; 81 | * uu ~> vv is a heavy path on tree 82 | * } 83 | */ 84 | } 85 | } tree; 86 | -------------------------------------------------------------------------------- /graph/MaxClique.cpp: -------------------------------------------------------------------------------- 1 | // max N = 64 2 | typedef unsigned long long ll; 3 | struct MaxClique{ 4 | ll nb[ N ] , n , ans; 5 | void init( ll _n ){ 6 | n = _n; 7 | for( int i = 0 ; i < n ; i ++ ) nb[ i ] = 0LLU; 8 | } 9 | void add_edge( ll _u , ll _v ){ 10 | nb[ _u ] |= ( 1LLU << _v ); 11 | nb[ _v ] |= ( 1LLU << _u ); 12 | } 13 | void B( ll r , ll p , ll x , ll cnt , ll res ){ 14 | if( cnt + res < ans ) return; 15 | if( p == 0LLU && x == 0LLU ){ 16 | if( cnt > ans ) ans = cnt; 17 | return; 18 | } 19 | ll y = p | x; y &= -y; 20 | ll q = p & ( ~nb[ int( log2( y ) ) ] ); 21 | while( q ){ 22 | ll i = int( log2( q & (-q) ) ); 23 | B( r | ( 1LLU << i ) , p & nb[ i ] , x & nb[ i ] 24 | , cnt + 1LLU , __builtin_popcountll( p & nb[ i ] ) ); 25 | q &= ~( 1LLU << i ); 26 | p &= ~( 1LLU << i ); 27 | x |= ( 1LLU << i ); 28 | } } 29 | int solve(){ 30 | ans = 0; 31 | ll _set = 0; 32 | if( n < 64 ) _set = ( 1LLU << n ) - 1; 33 | else{ 34 | for( ll i = 0 ; i < n ; i ++ ) _set |= ( 1LLU << i ); 35 | } 36 | B( 0LLU , _set , 0LLU , 0LLU , n ); 37 | return ans; 38 | } 39 | }maxClique; 40 | -------------------------------------------------------------------------------- /graph/MaximalClique.cpp: -------------------------------------------------------------------------------- 1 | #define N 80 2 | struct MaxClique{ // 0-base 3 | typedef bitset Int; 4 | Int lnk[N] , v[N]; 5 | int n; 6 | void init(int _n){ 7 | n = _n; 8 | for(int i = 0 ; i < n ; i ++){ 9 | lnk[i].reset(); v[i].reset(); 10 | } } 11 | void addEdge(int a , int b) 12 | { v[a][b] = v[b][a] = 1; } 13 | int ans , stk[N], id[N] , di[N] , deg[N]; 14 | Int cans; 15 | void dfs(int elem_num, Int candi, Int ex){ 16 | if(candi.none()&&ex.none()){ 17 | cans.reset(); 18 | for(int i = 0 ; i < elem_num ; i ++) 19 | cans[id[stk[i]]] = 1; 20 | ans = elem_num; // cans is a maximal clique 21 | return; 22 | } 23 | int pivot = (candi|ex)._Find_first(); 24 | Int smaller_candi = candi & (~lnk[pivot]); 25 | while(smaller_candi.count()){ 26 | int nxt = smaller_candi._Find_first(); 27 | candi[nxt] = smaller_candi[nxt] = 0; 28 | ex[nxt] = 1; 29 | stk[elem_num] = nxt; 30 | dfs(elem_num+1,candi&lnk[nxt],ex&lnk[nxt]); 31 | } } 32 | int solve(){ 33 | for(int i = 0 ; i < n ; i ++){ 34 | id[i] = i; deg[i] = v[i].count(); 35 | } 36 | sort(id , id + n , [&](int id1, int id2){ 37 | return deg[id1] > deg[id2]; }); 38 | for(int i = 0 ; i < n ; i ++) di[id[i]] = i; 39 | for(int i = 0 ; i < n ; i ++) 40 | for(int j = 0 ; j < n ; j ++) 41 | if(v[i][j]) lnk[di[i]][di[j]] = 1; 42 | ans = 1; cans.reset(); cans[0] = 1; 43 | dfs(0, Int(string(n,'1')), 0); 44 | return ans; 45 | } }solver; -------------------------------------------------------------------------------- /graph/MaximumClique.cpp: -------------------------------------------------------------------------------- 1 | #define N 111 2 | struct MaxClique{ // 0-base 3 | typedef bitset Int; 4 | Int linkto[N] , v[N]; 5 | int n; 6 | void init(int _n){ 7 | n = _n; 8 | for(int i = 0 ; i < n ; i ++){ 9 | linkto[i].reset(); v[i].reset(); 10 | } } 11 | void addEdge(int a , int b) 12 | { v[a][b] = v[b][a] = 1; } 13 | int popcount(const Int& val) 14 | { return val.count(); } 15 | int lowbit(const Int& val) 16 | { return val._Find_first(); } 17 | int ans , stk[N]; 18 | int id[N] , di[N] , deg[N]; 19 | Int cans; 20 | void maxclique(int elem_num, Int candi){ 21 | if(elem_num > ans){ 22 | ans = elem_num; cans.reset(); 23 | for(int i = 0 ; i < elem_num ; i ++) 24 | cans[id[stk[i]]] = 1; 25 | } 26 | int potential = elem_num + popcount(candi); 27 | if(potential <= ans) return; 28 | int pivot = lowbit(candi); 29 | Int smaller_candi = candi & (~linkto[pivot]); 30 | while(smaller_candi.count() && potential > ans){ 31 | int next = lowbit(smaller_candi); 32 | candi[next] = !candi[next]; 33 | smaller_candi[next] = !smaller_candi[next]; 34 | potential --; 35 | if(next == pivot || (smaller_candi & linkto[next]).count()){ 36 | stk[elem_num] = next; 37 | maxclique(elem_num + 1, candi & linkto[next]); 38 | } } } 39 | int solve(){ 40 | for(int i = 0 ; i < n ; i ++){ 41 | id[i] = i; deg[i] = v[i].count(); 42 | } 43 | sort(id , id + n , [&](int id1, int id2){ 44 | return deg[id1] > deg[id2]; }); 45 | for(int i = 0 ; i < n ; i ++) di[id[i]] = i; 46 | for(int i = 0 ; i < n ; i ++) 47 | for(int j = 0 ; j < n ; j ++) 48 | if(v[i][j]) linkto[di[i]][di[j]] = 1; 49 | Int cand; cand.reset(); 50 | for(int i = 0 ; i < n ; i ++) cand[i] = 1; 51 | ans = 1; 52 | cans.reset(); cans[0] = 1; 53 | maxclique(0, cand); 54 | return ans; 55 | } }solver; -------------------------------------------------------------------------------- /graph/MinMeanCycle.cpp: -------------------------------------------------------------------------------- 1 | /* minimum mean cycle O(VE) */ 2 | struct MMC{ 3 | #define E 101010 4 | #define V 1021 5 | #define inf 1e9 6 | #define eps 1e-6 7 | struct Edge { int v,u; double c; }; 8 | int n, m, prv[V][V], prve[V][V], vst[V]; 9 | Edge e[E]; 10 | vector edgeID, cycle, rho; 11 | double d[V][V]; 12 | void init( int _n ) 13 | { n = _n; m = 0; } 14 | // WARNING: TYPE matters 15 | void addEdge( int vi , int ui , double ci ) 16 | { e[ m ++ ] = { vi , ui , ci }; } 17 | void bellman_ford() { 18 | for(int i=0; id[i][v]+e[j].c) { 24 | d[i+1][u] = d[i][v]+e[j].c; 25 | prv[i+1][u] = v; 26 | prve[i+1][u] = j; 27 | } } } } 28 | double solve(){ 29 | // returns inf if no cycle, mmc otherwise 30 | double mmc=inf; 31 | int st = -1; 32 | bellman_ford(); 33 | for(int i=0; i& ter ){ 27 | int t = (int)ter.size(); 28 | for( int i = 0 ; i < ( 1 << t ) ; i ++ ) 29 | for( int j = 0 ; j < n ; j ++ ) 30 | dp[ i ][ j ] = INF; 31 | for( int i = 0 ; i < n ; i ++ ) 32 | dp[ 0 ][ i ] = 0; 33 | for( int msk = 1 ; msk < ( 1 << t ) ; msk ++ ){ 34 | if( msk == ( msk & (-msk) ) ){ 35 | int who = __lg( msk ); 36 | for( int i = 0 ; i < n ; i ++ ) 37 | dp[ msk ][ i ] = dst[ ter[ who ] ][ i ]; 38 | continue; 39 | } 40 | for( int i = 0 ; i < n ; i ++ ) 41 | for( int submsk = ( msk - 1 ) & msk ; submsk ; 42 | submsk = ( submsk - 1 ) & msk ) 43 | dp[ msk ][ i ] = min( dp[ msk ][ i ], 44 | dp[ submsk ][ i ] + 45 | dp[ msk ^ submsk ][ i ] ); 46 | for( int i = 0 ; i < n ; i ++ ){ 47 | tdst[ i ] = INF; 48 | for( int j = 0 ; j < n ; j ++ ) 49 | tdst[ i ] = min( tdst[ i ], 50 | dp[ msk ][ j ] + dst[ j ][ i ] ); 51 | } 52 | for( int i = 0 ; i < n ; i ++ ) 53 | dp[ msk ][ i ] = tdst[ i ]; 54 | } 55 | int ans = INF; 56 | for( int i = 0 ; i < n ; i ++ ) 57 | ans = min( ans , dp[ ( 1 << t ) - 1 ][ i ] ); 58 | return ans; 59 | } }solver; 60 | -------------------------------------------------------------------------------- /graph/Minimum_General_Weighted_Matching.cpp: -------------------------------------------------------------------------------- 1 | struct Graph { 2 | // Minimum General Weighted Matching (Perfect Match) 3 | static const int MXN = 105; 4 | int n, edge[MXN][MXN]; 5 | int match[MXN],dis[MXN],onstk[MXN]; 6 | vector stk; 7 | void init(int _n) { 8 | n = _n; 9 | for( int i = 0 ; i < n ; i ++ ) 10 | for( int j = 0 ; j < n ; j ++ ) 11 | edge[ i ][ j ] = 0; 12 | } 13 | void add_edge(int u, int v, int w) 14 | { edge[u][v] = edge[v][u] = w; } 15 | bool SPFA(int u){ 16 | if (onstk[u]) return true; 17 | stk.PB(u); 18 | onstk[u] = 1; 19 | for (int v=0; v dis[u] - edge[v][m] + edge[u][v]){ 23 | dis[m] = dis[u] - edge[v][m] + edge[u][v]; 24 | onstk[v] = 1; 25 | stk.PB(v); 26 | if (SPFA(m)) return true; 27 | stk.pop_back(); 28 | onstk[v] = 0; 29 | } } } 30 | onstk[u] = 0; 31 | stk.pop_back(); 32 | return false; 33 | } 34 | int solve() { 35 | // find a match 36 | for (int i=0; i=2){ 49 | int u = stk.back(); stk.pop_back(); 50 | int v = stk.back(); stk.pop_back(); 51 | match[u] = v; 52 | match[v] = u; 53 | } } } 54 | if (!found) break; 55 | } 56 | int ret = 0; 57 | for (int i=0; i0){ for (i=k; i<=ce[sz]; ++i) 12 | if (!g[lst[sz][t]][lst[sz][i]]) break; 13 | swap(lst[sz][k], lst[sz][i]); 14 | } i=lst[sz][k]; ne[sz+1]=ce[sz+1]=0; 15 | for (j=1; j E[MXN],sccv[MXN]; 4 | int top,stk[MXN]; 5 | void init(int _n) { 6 | n = _n; nScc = step = 0; 7 | for (int i=0; i= dfn[u]) { 20 | int z; 21 | sccv[nScc].clear(); 22 | do { 23 | z = stk[--top]; 24 | sccv[nScc].PB(z); 25 | } while (z != v); 26 | sccv[nScc++].PB(u); 27 | } 28 | }else 29 | low[u] = min(low[u],dfn[v]); 30 | } } 31 | vector> solve() { 32 | vector> res; 33 | for (int i=0; iG[1000050]; 5 | int cur[1000050]; 6 | int ind[1000050],out[1000050]; 7 | void dfs(int x){ 8 | FOR(i,1,n)sort(G[i].begin(),G[i].end()); 9 | dfs_st[++dfn]=x; 10 | memset(cur,-1,sizeof(cur)); 11 | while(dfn>0){ 12 | int u=dfs_st[dfn]; 13 | int complete=1; 14 | for(int i=cur[u]+1;i0){ 37 | start=i; 38 | break; 39 | } 40 | return true; 41 | } 42 | return false; 43 | } 44 | int main(){ 45 | cin>>n>>m; 46 | FOR(i,1,m){ 47 | int x,y;scanf("%d%d",&x,&y); 48 | G[x].push_back(y); 49 | ind[y]++,out[x]++; 50 | } 51 | int start=-1,ok=true; 52 | if(check(start)){ 53 | dfs(start); 54 | if(num!=m){ 55 | puts("What a shame!"); 56 | return 0; 57 | } 58 | for(int i=cnt;i>=1;i--) 59 | printf("%d ",ans[i]); 60 | puts(""); 61 | } 62 | else puts("What a shame!"); 63 | } -------------------------------------------------------------------------------- /graph/generalMatching.cpp: -------------------------------------------------------------------------------- 1 | // should shuffle vertices and edges 2 | const int N=100005,E=(2e5)*2+40; 3 | struct Graph{ // 1-based; match: i <-> lnk[i] 4 | int to[E],bro[E],head[N],e,lnk[N],vis[N],stp,n; 5 | void init(int _n){ 6 | stp=0; e=1; n=_n; 7 | for(int i=1;i<=n;i++) head[i]=lnk[i]=vis[i]=0; 8 | } 9 | void add_edge(int u,int v){ 10 | to[e]=v,bro[e]=head[u],head[u]=e++; 11 | to[e]=u,bro[e]=head[v],head[v]=e++; 12 | } 13 | bool dfs(int x){ 14 | vis[x]=stp; 15 | for(int i=head[x];i;i=bro[i]){ 16 | int v=to[i]; 17 | if(!lnk[v]){ lnk[x]=v,lnk[v]=x; return true; } 18 | } 19 | for(int i=head[x];i;i=bro[i]){ 20 | int v=to[i]; 21 | if(vis[lnk[v]] 3 | using namespace std; 4 | 5 | const int N = 514, E = (2e5) * 2; 6 | struct Graph{ 7 | int to[E],bro[E],head[N],e; 8 | int lnk[N],vis[N],stp,n; 9 | void init( int _n ){ 10 | stp = 0; e = 1; n = _n; 11 | for( int i = 1 ; i <= n ; i ++ ) 12 | lnk[i] = vis[i] = 0; 13 | } 14 | void add_edge(int u,int v){ 15 | to[e]=v,bro[e]=head[u],head[u]=e++; 16 | to[e]=u,bro[e]=head[v],head[v]=e++; 17 | } 18 | bool dfs(int x){ 19 | vis[x]=stp; 20 | for(int i=head[x];i;i=bro[i]){ 21 | int v=to[i]; 22 | if(!lnk[v]){ 23 | lnk[x]=v,lnk[v]=x; 24 | return true; 25 | }else if(vis[lnk[v]]> n >> m; 49 | graph.init( n ); 50 | while( m -- ){ 51 | int ui , vi; 52 | cin >> ui >> vi; 53 | graph.add_edge( ui , vi ); 54 | } 55 | printf( "%d\n" , graph.solve() ); 56 | for( int i = 1 ; i <= n ; i ++ ) 57 | printf( "%d%c" , graph.lnk[ i ] , " \n"[ i == n ] ); 58 | } 59 | -------------------------------------------------------------------------------- /graph/generalWeightedGraphMaxMatching.cpp: -------------------------------------------------------------------------------- 1 | #define N 110 2 | #define inf 0x3f3f3f3f 3 | int G[ N ][ N ] , ID[ N ]; 4 | int match[ N ] , stk[ N ]; 5 | int vis[ N ] , dis[ N ]; 6 | int n , m , k , top; 7 | bool SPFA( int u ){ 8 | stk[ top ++ ] = u; 9 | if( vis[ u ] ) return true; 10 | vis[ u ] = true; 11 | for( int i = 1 ; i <= k ; i ++ ){ 12 | if( i != u && i != match[ u ] && !vis[ i ] ){ 13 | int v = match[ i ]; 14 | if( dis[ v ] < dis[ u ] + G[ u ][ i ] - G[ i ][ v ] ){ 15 | dis[ v ] = dis[ u ] + G[ u ][ i ] - G[ i ][ v ]; 16 | if( SPFA( v ) ) return true; 17 | } } } 18 | top --; vis[ u ] = false; 19 | return false; 20 | } 21 | int MaxWeightMatch() { 22 | for( int i = 1 ; i <= k ; i ++ ) ID[ i ] = i; 23 | for( int i = 1 ; i <= k ; i += 2 ) match[ i ] = i + 1 , match[ i + 1 ] = i; 24 | for( int times = 0 , flag ; times < 3 ; ){ 25 | memset( dis , 0 , sizeof( dis ) ); 26 | memset( vis , 0 , sizeof( vis ) ); 27 | top = 0; flag = 0; 28 | for( int i = 1 ; i <= k ; i ++ ){ 29 | if( SPFA( ID[ i ] ) ){ 30 | flag = 1; 31 | int t = match[ stk[ top - 1 ] ] , j = top - 2; 32 | while( stk[ j ] != stk[ top - 1 ] ){ 33 | match[ t ] = stk[ j ]; 34 | swap( t , match[ stk[ j ] ] ); 35 | j --; 36 | } 37 | match[ t ] = stk[ j ]; match[ stk[ j ] ] = t; 38 | break; 39 | } } 40 | if( !flag ) times ++; 41 | if( !flag ) random_shuffle( ID + 1 , ID + k + 1 ); 42 | } 43 | int ret = 0; 44 | for( int i = 1 ; i <= k ; i ++ ) 45 | if( i < match[ i ] ) ret += G[ i ][ match[ i ] ]; 46 | return ret; 47 | } 48 | int main(){ 49 | int T; scanf("%d", &T); 50 | for ( int cs = 1 ; cs <= T ; cs ++ ){ 51 | scanf( "%d%d%d" , &n , &m , &k ); 52 | memset( G , 0x3f , sizeof( G ) ); 53 | for( int i = 1 ; i <= n ; i ++ ) G[ i ][ i ] = 0; 54 | for( int i = 0 ; i < m ; i ++ ){ 55 | int u, v, w; 56 | scanf( "%d%d%d" , &u , &v , &w ); 57 | G[ u ][ v ] = G[ v ][ u ] = w; 58 | } 59 | if( k & 1 ){ puts( "Impossible" ); continue; } 60 | for( int tk = 1; tk <= n ; tk ++ ) 61 | for( int i = 1 ; i <= n ; i ++ ) 62 | for( int j = 1 ; j <= n ; j ++ ) 63 | G[ i ][ j ] = min( G[ i ][ j ] , G[ i ][ tk ] + G[ tk ][ j ] ); 64 | for( int i = 1 ; i <= k ; i ++ ){ 65 | for( int j = 1 ; j <= k ; j ++ ) 66 | G[ i ][ j ] = -G[ i ][ j ]; 67 | G[ i ][ i ] = -inf; 68 | } 69 | printf( "%d\n" , -MaxWeightMatch() ); 70 | } } 71 | -------------------------------------------------------------------------------- /graph/graphHash.tex: -------------------------------------------------------------------------------- 1 | $$F_t(i) = 2 | (F_{t-1}(i) \times A + 3 | \sum_{i\rightarrow j} F_{t-1}(j) \times B + 4 | \sum_{j\rightarrow i} F_{t-1}(j) \times C + 5 | D \times (i = a))\ mod\ P 6 | $$ 7 | for each node i, iterate t times. 8 | t, A, B, C, D, P are hash parameter 9 | -------------------------------------------------------------------------------- /graph/kosaraju.cpp: -------------------------------------------------------------------------------- 1 | struct Scc{ 2 | int n, nScc, vst[MXN], bln[MXN]; 3 | vector E[MXN], rE[MXN], vec; 4 | void init(int _n){ 5 | n = _n; 6 | for (int i=0; i<= n; i++) 7 | E[i].clear(), rE[i].clear(); 8 | } 9 | void addEdge(int u, int v){ 10 | E[u].PB(v); rE[v].PB(u); 11 | } 12 | void DFS(int u){ 13 | vst[u]=1; 14 | for (auto v : E[u]) if (!vst[v]) DFS(v); 15 | vec.PB(u); 16 | } 17 | void rDFS(int u){ 18 | vst[u] = 1; bln[u] = nScc; 19 | for (auto v : rE[u]) if (!vst[v]) rDFS(v); 20 | } 21 | void solve(){ 22 | nScc = 0; 23 | vec.clear(); 24 | fill(vst, vst+n+1, 0); 25 | for (int i=0; i dis; 6 | vector> edge[MXN]; 7 | void init(int _n){ 8 | n = _n; 9 | dis.clear(); dis.resize(n, 1e18); 10 | for(int i = 0; i < n; i++){ 11 | edge[i].clear(); 12 | inq[i] = len[i] = 0; 13 | } } 14 | void addEdge(int u, int v, LL w){ 15 | edge[u].push_back({v, w}); 16 | } 17 | vector solve(int st = 0){ 18 | deque dq; //return {-1} if has negative cycle 19 | dq.push_back(st); //otherwise return dis from st 20 | inq[st] = 1; dis[st] = 0; 21 | while(!dq.empty()){ 22 | int u = dq.front(); dq.pop_front(); 23 | inq[u] = 0; 24 | for(auto [to, d] : edge[u]){ 25 | if(dis[to] > d+dis[u]){ 26 | dis[to] = d+dis[u]; 27 | len[to] = len[u]+1; 28 | if(len[to] > n) return {-1}; 29 | if(inq[to]) continue; 30 | (!dq.empty()&&dis[dq.front()] > dis[to]? 31 | dq.push_front(to) : dq.push_back(to)); 32 | inq[to] = 1; 33 | } } } 34 | return dis; 35 | } }spfa; -------------------------------------------------------------------------------- /math/DiscreteKthsqrt.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Solve x for x^P = A mod Q 3 | * https://arxiv.org/pdf/1111.4877.pdf 4 | * in O((lgQ)^2 + Q^0.25 (lgQ)^3) 5 | * Idea: 6 | * (P, Q-1) = 1 -> P^-1 mod (Q-1) exists 7 | * x has solution iff A^((Q-1) / P) = 1 mod Q 8 | * PP | (Q-1) -> P < sqrt(Q), solve lgQ rounds of discrete log 9 | * else -> find a s.t. s | (Pa - 1) -> ans = A^a 10 | */ 11 | void gcd(LL a, LL b, LL &x, LL &y, LL &g){ 12 | if (b == 0) { 13 | x = 1, y = 0, g = a; 14 | return; 15 | } 16 | LL tx, ty; 17 | gcd(b, a%b, tx, ty, g); 18 | x = ty; 19 | y = tx - ty * (a / b); 20 | return; 21 | } 22 | LL P, A, Q, g; 23 | // x^P = A mod Q 24 | 25 | const int X = 1e5; 26 | 27 | LL base; 28 | LL ae[X], aXe[X], iaXe[X]; 29 | unordered_map ht; 30 | 31 | void build(LL a) { // ord(a) = P < sqrt(Q) 32 | base = a; 33 | ht.clear(); 34 | ae[0] = 1; 35 | ae[1] = a; 36 | aXe[0] = 1; 37 | aXe[1] = pw(a, X, Q); 38 | iaXe[0] = 1; 39 | iaXe[1] = pw(aXe[1], Q-2, Q); 40 | REP(i, 2, X-1) { 41 | ae[i] = mul(ae[i-1], ae[1], Q); 42 | aXe[i] = mul(aXe[i-1], aXe[1], Q); 43 | iaXe[i] = mul(iaXe[i-1], iaXe[1], Q); 44 | } 45 | FOR(i, X) ht[ae[i]] = i; 46 | } 47 | 48 | LL dis_log(LL x) { 49 | FOR(i, X) { 50 | LL iaXi = iaXe[i]; 51 | LL rst = mul(x, iaXi, Q); 52 | if (ht.count(rst)) { 53 | LL res = i*X + ht[rst]; 54 | return res; 55 | } 56 | } 57 | } 58 | 59 | LL main2() { 60 | LL t = 0, s = Q-1; 61 | while (s % P == 0) { 62 | ++t; 63 | s /= P; 64 | } 65 | if (A == 0) return 0; 66 | 67 | if (t == 0) { 68 | // a^{P^-1 mod phi(Q)} 69 | LL x, y, _; 70 | gcd(P, Q-1, x, y, _); 71 | if (x < 0) { 72 | x = (x % (Q-1) + Q-1) % (Q-1); 73 | } 74 | LL ans = pw(A, x, Q); 75 | if (pw(ans, P, Q) != A) while(1); 76 | return ans; 77 | } 78 | 79 | // A is not P-residue 80 | if (pw(A, (Q-1) / P, Q) != 1) return -1; 81 | 82 | for (g = 2; g < Q; ++g) { 83 | if (pw(g, (Q-1) / P, Q) != 1) 84 | break; 85 | } 86 | LL alpha = 0; 87 | { 88 | LL y, _; 89 | gcd(P, s, alpha, y, _); 90 | if (alpha < 0) alpha = (alpha % (Q-1) + Q-1) % (Q-1); 91 | } 92 | 93 | if (t == 1) { 94 | LL ans = pw(A, alpha, Q); 95 | return ans; 96 | } 97 | 98 | LL a = pw(g, (Q-1) / P, Q); 99 | build(a); 100 | LL b = pw(A, add(mul(P%(Q-1), alpha, Q-1), Q-2, Q-1), Q); 101 | LL c = pw(g, s, Q); 102 | LL h = 1; 103 | 104 | LL e = (Q-1) / s / P; // r^{t-1} 105 | REP(i, 1, t-1) { 106 | e /= P; 107 | LL d = pw(b, e, Q); 108 | LL j = 0; 109 | if (d != 1) { 110 | j = -dis_log(d); 111 | if (j < 0) j = (j % (Q-1) + Q-1) % (Q-1); 112 | } 113 | b = mul(b, pw(c, mul(P%(Q-1), j, Q-1), Q), Q); 114 | h = mul(h, pw(c, j, Q), Q); 115 | c = pw(c, P, Q); 116 | } 117 | 118 | LL ans = mul(pw(A, alpha, Q), h, Q); 119 | 120 | return ans; 121 | } 122 | -------------------------------------------------------------------------------- /math/DiscreteSqrt.cpp: -------------------------------------------------------------------------------- 1 | void calcH(LL &t, LL &h, const LL p) { 2 | LL tmp=p-1; for(t=0;(tmp&1)==0;tmp/=2) t++; h=tmp; 3 | } 4 | // solve equation x^2 mod p = a 5 | bool solve(LL a, LL p, LL &x, LL &y) { 6 | if(p == 2) { x = y = 1; return true; } 7 | int p2 = p / 2, tmp = mypow(a, p2, p); 8 | if (tmp == p - 1) return false; 9 | if ((p + 1) % 4 == 0) { 10 | x=mypow(a,(p+1)/4,p); y=p-x; return true; 11 | } else { 12 | LL t, h, b, pb; calcH(t, h, p); 13 | if (t >= 2) { 14 | do {b = rand() % (p - 2) + 2; 15 | } while (mypow(b, p / 2, p) != p - 1); 16 | pb = mypow(b, h, p); 17 | } int s = mypow(a, h / 2, p); 18 | for (int step = 2; step <= t; step++) { 19 | int ss = (((LL)(s * s) % p) * a) % p; 20 | for(int i=0;i cplx; //real() ,imag() 6 | const ld PI = acosl(-1); 7 | const cplx I(0, 1); 8 | cplx omega[MAXN+1]; 9 | void pre_fft(){ 10 | for(int i=0; i<=MAXN; i++) 11 | omega[i] = exp(i * 2 * PI / MAXN * I); 12 | } 13 | // n must be 2^k 14 | void fft(int n, cplx a[], bool inv=false){ 15 | int basic = MAXN / n; 16 | int theta = basic; 17 | for (int m = n; m >= 2; m >>= 1) { 18 | int mh = m >> 1; 19 | for (int i = 0; i < mh; i++) { 20 | cplx w = omega[inv ? MAXN-(i*theta%MAXN) 21 | : i*theta%MAXN]; 22 | for (int j = i; j < n; j += m) { 23 | int k = j + mh; 24 | cplx x = a[j] - a[k]; 25 | a[j] += a[k]; 26 | a[k] = w * x; 27 | } } 28 | theta = (theta * 2) % MAXN; 29 | } 30 | int i = 0; 31 | for (int j = 1; j < n - 1; j++) { 32 | for (int k = n >> 1; k > (i ^= k); k >>= 1); 33 | if (j < i) swap(a[i], a[j]); 34 | } 35 | if(inv) for (i = 0; i < n; i++) a[i] /= n; 36 | } 37 | cplx arr[MAXN+1]; 38 | inline void mul(int _n,ll a[],int _m,ll b[],ll ans[]){ 39 | int n=1,sum=_n+_m-1; 40 | while(n(x+y,x-y); 45 | } 46 | fft(n,arr); 47 | for(int i=0;i 5 | * x' = ( x0+x1 , x0-x1 ) , y' = ( y0+y1 , y0-y1 ) 6 | * z' = ( ( x0+x1 )( y0+y1 ) , ( x0-x1 )( y0-y1 ) ) 7 | * z = (1/2) * z'' 8 | * or convolution: 9 | * x = (x0, x0+x1), inv = (x0, x1-x0) w/o final div 10 | * and convolution: 11 | * x = (x0+x1, x1), inv = (x0-x1, x1) w/o final div */ 12 | const int MAXN = (1<<20)+10; 13 | inline LL inv( LL x ) { 14 | return mypow( x , MOD-2 ); 15 | } 16 | inline void fwt( LL x[ MAXN ] , int N , bool inv=0 ) { 17 | for( int d = 1 ; d < N ; d <<= 1 ) { 18 | int d2 = d<<1; 19 | for( int s = 0 ; s < N ; s += d2 ) 20 | for( int i = s , j = s+d ; i < s+d ; i++, j++ ){ 21 | LL ta = x[ i ] , tb = x[ j ]; 22 | x[ i ] = ta+tb; 23 | x[ j ] = ta-tb; 24 | if( x[ i ] >= MOD ) x[ i ] -= MOD; 25 | if( x[ j ] < 0 ) x[ j ] += MOD; 26 | } } 27 | if( inv ) 28 | for( int i = 0 ; i < N ; i++ ) { 29 | x[ i ] *= inv( N ); 30 | x[ i ] %= MOD; 31 | } } 32 | -------------------------------------------------------------------------------- /math/Faulhaber.cpp: -------------------------------------------------------------------------------- 1 | /* faulhaber’s formula - 2 | * cal power sum formula of all p=1~k in O(k^2) */ 3 | #define MAXK 2500 4 | const int mod = 1000000007; 5 | int b[MAXK]; // bernoulli number 6 | int inv[MAXK+1]; // inverse 7 | int cm[MAXK+1][MAXK+1]; // combinactories 8 | int co[MAXK][MAXK+2]; // coeeficient of x^j when p=i 9 | inline int getinv(int x) { 10 | int a=x,b=mod,a0=1,a1=0,b0=0,b1=1; 11 | while(b) { 12 | int q,t; 13 | q=a/b; t=b; b=a-b*q; a=t; 14 | t=b0; b0=a0-b0*q; a0=t; 15 | t=b1; b1=a1-b1*q; a1=t; 16 | } 17 | return a0<0?a0+mod:a0; 18 | } 19 | inline void pre() { 20 | /* combinational */ 21 | for(int i=0;i<=MAXK;i++) { 22 | cm[i][0]=cm[i][i]=1; 23 | for(int j=1;j=a && x%m == r. 5 | /// _ct(a,b,m,r) |A| , A = { x : a<=x<=b && x%m == r }. 6 | int _fd(int a,int b){ return a<0?(-~a/b-1):a/b; } 7 | int _rd(int a,int m){ return a-_fd(a,m)*m; } 8 | int _pv(int a,int m,int r){ 9 | r=(r%m+m)%m; 10 | return _fd(a-r,m)*m+r; 11 | } 12 | int _nt(int a,int m,int r){ 13 | m=abs(m); 14 | r=(r%m+m)%m; 15 | return _fd(a-r-1,m)*m+r+m; 16 | } 17 | int _ct(int a,int b,int m,int r){ 18 | m=abs(m); 19 | a=_nt(a,m,r); 20 | b=_pv(b,m,r); 21 | return (a>b)?0:((b-a+m)/m); 22 | } 23 | -------------------------------------------------------------------------------- /math/Martix_fast_pow.cpp: -------------------------------------------------------------------------------- 1 | LL len,mod; 2 | vector> operator*(vector> x,vector> y){ 3 | vector> ret(len,vector(len,0)); 4 | for(int i=0;i> poly){ 16 | if(n> mar(len,vector(len,0)),x(len,vector(len,0)); 18 | for(int i=0;i>=1, x=x*x; 24 | } 25 | LL ans=0; 26 | for(int i=0;i>=1, t++; 27 | while(s--){ 28 | LL a=magic[s]%n; 29 | if(witness(a,n,u,t)) return 0; 30 | } 31 | return 1; 32 | } 33 | -------------------------------------------------------------------------------- /math/O(1)mul.cpp: -------------------------------------------------------------------------------- 1 | LL mul(LL x,LL y,LL mod){ 2 | LL ret=x*y-(LL)((long double)x/mod*y)*mod; 3 | // LL ret=x*y-(LL)((long double)x*y/mod+0.5)*mod; 4 | return ret<0?ret+mod:ret; 5 | } 6 | -------------------------------------------------------------------------------- /math/PolyGen.cpp: -------------------------------------------------------------------------------- 1 | struct PolyGen{ 2 | /* for a nth-order polynomial f(x), * 3 | * given f(0), f(1), ..., f(n) * 4 | * express f(x) as sigma_i{c_i*C(x,i)} */ 5 | int n; 6 | vector coef; 7 | // initialize and calculate f(x), vector _fx should 8 | // be filled with f(0) to f(n) 9 | PolyGen(int _n,vector _fx):n(_n),coef(_fx){ 10 | for(int i=0;ii;j--) 12 | coef[j]-=coef[j-1]; 13 | } 14 | // evaluate f(x), runs in O(n) 15 | LL eval(int x){ 16 | LL m=1, ret=0; 17 | for(int i=0;i<=n;i++){ 18 | ret+=coef[i]*m; 19 | m=m*(x-i)/(i+1); 20 | } 21 | return ret; 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /math/Romberg.cpp: -------------------------------------------------------------------------------- 1 | // Estimates the definite integral of 2 | // \int_a^b f(x) dx 3 | template 4 | double romberg( T& f, double a, double b, double eps=1e-8){ 5 | vectort; double h=b-a,last,curr; int k=1,i=1; 6 | t.push_back(h*(f(a)+f(b))/2); 7 | do{ last=t.back(); curr=0; double x=a+h/2; 8 | for(int j=0;j eps); 14 | return t.back(); 15 | } 16 | -------------------------------------------------------------------------------- /math/SSG.cpp: -------------------------------------------------------------------------------- 1 | SG value = N_1 ^ N_2 ^ N_3 ^ ... ^ N_n (每個N_i為獨立遊戲) 2 | if = 0 先手必敗 else 先手必勝 3 | 1.如果一個狀態是結束狀態(不能再動作),SG-value=0,該玩家輸 4 | 2.找出當前狀態所有可以轉移的子狀態,把他們的SG value收集起來,此集合的mex就是當前的SG value 5 | mex最小沒出現的非負整數 6 | EX : mex{0,1,3}=2, mex{1,2,5}=0, mex{0,1,2}=3 -------------------------------------------------------------------------------- /math/SchreierSims.cpp: -------------------------------------------------------------------------------- 1 | // time: O(n^2 lg^3 |G| + t n lg |G|) 2 | // mem : O(n^2 lg |G| + tn) 3 | // t : number of generator 4 | namespace SchreierSimsAlgorithm{ 5 | typedef vector Permu; 6 | Permu inv( const Permu& p ){ 7 | Permu ret( p.size() ); 8 | for( int i = 0; i < int(p.size()); i ++ ) 9 | ret[ p[ i ] ] = i; 10 | return ret; 11 | } 12 | Permu operator*( const Permu& a, const Permu& b ){ 13 | Permu ret( a.size() ); 14 | for( int i = 0 ; i < (int)a.size(); i ++ ) 15 | ret[ i ] = b[ a[ i ] ]; 16 | return ret; 17 | } 18 | typedef vector Bucket; 19 | typedef vector Table; 20 | typedef pair pii; 21 | int n, m; 22 | vector bkts, bktsInv; 23 | vector lookup; 24 | int fastFilter( const Permu &g, bool addToG = 1 ){ 25 | n = bkts.size(); 26 | Permu p; 27 | for( int i = 0 ; i < n ; i ++ ){ 28 | int res = lookup[ i ][ p[ i ] ]; 29 | if( res == -1 ){ 30 | if( addToG ){ 31 | bkts[ i ].push_back( p ); 32 | bktsInv[ i ].push_back( inv( p ) ); 33 | lookup[ i ][ p[i] ] = (int)bkts[i].size()-1; 34 | } 35 | return i; 36 | } 37 | p = p * bktsInv[i][res]; 38 | } 39 | return -1; 40 | } 41 | long long calcTotalSize(){ 42 | long long ret = 1; 43 | for( int i = 0 ; i < n ; i ++ ) 44 | ret *= bkts[i].size(); 45 | return ret; 46 | } 47 | bool inGroup( const Permu &g ){ 48 | return fastFilter( g, false ) == -1; 49 | } 50 | void solve( const Bucket &gen, int _n ){ 51 | n = _n, m = gen.size(); // m perm[0..n-1]s 52 | {//clear all 53 | bkts.clear(); 54 | bktsInv.clear(); 55 | lookup.clear(); 56 | } 57 | for(int i = 0 ; i < n ; i ++ ){ 58 | lookup[i].resize(n); 59 | fill(lookup[i].begin(), lookup[i].end(), -1); 60 | } 61 | Permu id( n ); 62 | for(int i = 0 ; i < n ; i ++ ) id[i] = i; 63 | for(int i = 0 ; i < n ; i ++ ){ 64 | bkts[i].push_back(id); 65 | bktsInv[i].push_back(id); 66 | lookup[i][i] = 0; 67 | } 68 | for(int i = 0 ; i < m ; i ++) 69 | fastFilter( gen[i] ); 70 | queue< pair > toUpd; 71 | for(int i = 0; i < n; i ++) 72 | for(int j = i; j < n; j ++) 73 | for(int k = 0; k < (int)bkts[i].size(); k ++) 74 | for(int l = 0; l < (int)bkts[j].size(); l ++) 75 | toUpd.push( {pii(i,k), pii(j,l)} ); 76 | while( !toUpd.empty() ){ 77 | pii a = toUpd.front().first; 78 | pii b = toUpd.front().second; 79 | toUpd.pop(); 80 | int res = fastFilter(bkts[a.first][a.second] * 81 | bkts[b.first][b.second]); 82 | if(res == -1) continue; 83 | pii newPair(res, (int)bkts[res].size() - 1); 84 | for(int i = 0; i < n; i ++) 85 | for(int j = 0; j < (int)bkts[i].size(); ++j){ 86 | if(i <= res) 87 | toUpd.push(make_pair(pii(i , j), newPair)); 88 | if(res <= i) 89 | toUpd.push(make_pair(newPair, pii(i, j))); 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /math/Simplex.cpp: -------------------------------------------------------------------------------- 1 | const int MAXN = 111; 2 | const int MAXM = 111; 3 | const double eps = 1E-10; 4 | double a[MAXN][MAXM], b[MAXN], c[MAXM], d[MAXN][MAXM]; 5 | double x[MAXM]; 6 | int ix[MAXN + MAXM]; // !!! array all indexed from 0 7 | // max{cx} subject to {Ax<=b,x>=0} 8 | // n: constraints, m: vars !!! 9 | // x[] is the optimal solution vector 10 | // usage : 11 | // value = simplex(a, b, c, N, M); 12 | double simplex(double a[MAXN][MAXM], double b[MAXN], 13 | double c[MAXM], int n, int m){ 14 | ++m; 15 | int r = n, s = m - 1; 16 | memset(d, 0, sizeof(d)); 17 | for (int i = 0; i < n + m; ++i) ix[i] = i; 18 | for (int i = 0; i < n; ++i) { 19 | for (int j = 0; j < m - 1; ++j) d[i][j] = -a[i][j]; 20 | d[i][m - 1] = 1; 21 | d[i][m] = b[i]; 22 | if (d[r][m] > d[i][m]) r = i; 23 | } 24 | for (int j = 0; j < m - 1; ++j) d[n][j] = c[j]; 25 | d[n + 1][m - 1] = -1; 26 | for (double dd;; ) { 27 | if (r < n) { 28 | int t = ix[s]; ix[s] = ix[r + m]; ix[r + m] = t; 29 | d[r][s] = 1.0 / d[r][s]; 30 | for (int j = 0; j <= m; ++j) 31 | if (j != s) d[r][j] *= -d[r][s]; 32 | for (int i = 0; i <= n + 1; ++i) if (i != r) { 33 | for (int j = 0; j <= m; ++j) if (j != s) 34 | d[i][j] += d[r][j] * d[i][s]; 35 | d[i][s] *= d[r][s]; 36 | } 37 | } 38 | r = -1; s = -1; 39 | for (int j = 0; j < m; ++j) 40 | if (s < 0 || ix[s] > ix[j]) { 41 | if (d[n + 1][j] > eps || 42 | (d[n + 1][j] > -eps && d[n][j] > eps)) 43 | s = j; 44 | } 45 | if (s < 0) break; 46 | for (int i = 0; i < n; ++i) if (d[i][s] < -eps) { 47 | if (r < 0 || 48 | (dd = d[r][m] / d[r][s] - d[i][m] / d[i][s]) < -eps || 49 | (dd < eps && ix[r + m] > ix[i + m])) 50 | r = i; 51 | } 52 | if (r < 0) return -1; // not bounded 53 | } 54 | if (d[n + 1][m] < -eps) return -1; // not executable 55 | double ans = 0; 56 | for(int i=0; i EPS ){ 9 | piv = j; 10 | break; 11 | } 12 | } 13 | if( piv == -1 ) continue; 14 | used[ i ] = true; 15 | swap( m.v[ piv ], m.v[ i ] ); 16 | swap( res.v[ piv ], res.v[ i ] ); 17 | LD rat = m.v[ i ][ i ]; 18 | for( int j = 0 ; j < W ; j ++ ){ 19 | m.v[ i ][ j ] /= rat; 20 | res.v[ i ][ j ] /= rat; 21 | } 22 | for( int j = 0 ; j < W ; j ++ ){ 23 | if( j == i ) continue; 24 | rat = m.v[ j ][ i ]; 25 | for( int k = 0 ; k < W ; k ++ ){ 26 | m.v[ j ][ k ] -= rat * m.v[ i ][ k ]; 27 | res.v[ j ][ k ] -= rat * res.v[ i ][ k ]; 28 | } 29 | } 30 | } 31 | for( int i = 0 ; i < W ; i ++ ){ 32 | if( used[ i ] ) continue; 33 | for( int j = 0 ; j < W ; j ++ ) 34 | res.v[ i ][ j ] = 0; 35 | } 36 | return res; 37 | } 38 | -------------------------------------------------------------------------------- /math/Stirling_approximation.tex: -------------------------------------------------------------------------------- 1 | \begin{large} 2 | $n!\approx\sqrt{ 2 \pi n}(\frac{n}{e})^{n}e^\frac{1}{12n}$ 3 | \end{large} -------------------------------------------------------------------------------- /math/ax+by=gcd.cpp: -------------------------------------------------------------------------------- 1 | PII gcd(int a, int b){ 2 | if(b == 0) return {1, 0}; 3 | PII q = gcd(b, a % b); 4 | return {q.second, q.first - q.second * (a / b)}; 5 | } 6 | -------------------------------------------------------------------------------- /math/chineseRemainder.cpp: -------------------------------------------------------------------------------- 1 | LL x[N],m[N]; 2 | LL CRT(LL x1, LL m1, LL x2, LL m2) { 3 | LL g = __gcd(m1, m2); 4 | if((x2 - x1) % g) return -1;// no sol 5 | m1 /= g; m2 /= g; 6 | pair p = gcd(m1, m2); 7 | LL lcm = m1 * m2 * g; 8 | LL res = p.first * (x2 - x1) * m1 + x1; 9 | return (res % lcm + lcm) % lcm; 10 | } 11 | LL solve(int n){ // n>=2,be careful with no solution 12 | LL res=CRT(x[0],m[0],x[1],m[1]),p=m[0]/__gcd(m[0],m[1])*m[1]; 13 | for(int i=2;i1) pf[pfn++]=t; 41 | } 42 | inline int chinese_remainder() { 43 | int i,m,s=0; 44 | for(i=0;i > 5 | void update_P_mtx(Matrix &P, int p, int q, double c, double s) { // O(N) 6 | int rows = P.getShape().first; 7 | vector Qp(rows, 0.0); 8 | vector Qq(rows, 0.0); 9 | for(int k = 0; k < rows; k++) { 10 | Qp[k] = c*P[k][p] + s*P[k][q]; 11 | Qq[k] = -s*P[k][p] + c*P[k][q]; 12 | } 13 | for(int k = 0; k < rows; k++) { 14 | P[k][p] = Qp[k]; 15 | P[k][q] = Qq[k]; 16 | } } 17 | void update_A_mtx(Matrix &A, int p, int q, double c, double s) { // O(N) 18 | int n = A.getShape().first; 19 | vector Bp(n, 0.0); 20 | vector Bq(n, 0.0); 21 | Bp[p] = c*c*A[p][p] + 2.0*s*c*A[p][q] + s*s*A[q][q]; 22 | Bq[q] = s*s*A[p][p] - 2.0*s*c*A[p][q] + c*c*A[q][q]; 23 | for(int r = 0; r < n; r++) { 24 | if (r != p && r != q) { 25 | Bp[r] = c*A[r][p] + s*A[r][q]; 26 | Bq[r] = -s*A[r][p] + c*A[r][q]; 27 | } } 28 | for(int k = 0; k < n; k++) { 29 | A[p][k] = A[k][p] = Bp[k]; 30 | A[q][k] = A[k][q] = Bq[k]; 31 | } 32 | A[p][q] = A[q][p] = 0.0; 33 | } 34 | double max_off_diag_entry(Matrix &A, int &p, int &q) { // (O(N^2) 35 | // Suppose A is a symmetric matrix 36 | int rows = A.getShape().first, cols = A.getShape().second; 37 | double max_value = -__DBL_MAX__; 38 | 39 | for(int i = 0; i < rows; i++) { 40 | for(int j = 0; j < cols; j++) { 41 | if (i != j && fabs(A[i][j]) > max_value) { 42 | max_value = fabs(A[i][j]); 43 | p = i; 44 | q = j; 45 | }}} 46 | return max_value; 47 | } 48 | pair jacobian(Matrix m) { // O(k*(2N + N^2)) 49 | Matrix A(m); 50 | int rows = A.getShape().first, cols = A.getShape().first, p, q, iterations = 0; 51 | Matrix P = Matrix::identity(rows, cols); 52 | double Apq = max_off_diag_entry(A, p, q); 53 | 54 | while(fabs(Apq) > _EPSILON){ 55 | iterations++; 56 | double theta = atan2((A[p][q] * 2.0), (A[p][p] - A[q][q]))/2.0; 57 | double c = cos(theta); 58 | double s = sin(theta); 59 | update_P_mtx(P, p, q, c, s); // P = P*R; 60 | update_A_mtx(A, p, q, c, s); // B = R.T()*A*R; 61 | Apq = max_off_diag_entry(A, p, q); 62 | } 63 | return make_pair(A, P); 64 | } 65 | -------------------------------------------------------------------------------- /math/gauss.cpp: -------------------------------------------------------------------------------- 1 | const int GAUSS_MOD = 100000007LL; 2 | struct GAUSS{ 3 | int n; 4 | vector> v; 5 | int ppow(int a , int k){ 6 | if(k == 0) return 1; 7 | if(k % 2 == 0) return ppow(a * a % GAUSS_MOD , k >> 1); 8 | if(k % 2 == 1) return ppow(a * a % GAUSS_MOD , k >> 1) * a % GAUSS_MOD; 9 | } 10 | vector solve(){ 11 | vector ans(n); 12 | REP(now , 0 , n){ 13 | REP(i , now , n) if(v[now][now] == 0 && v[i][now] != 0) 14 | swap(v[i] , v[now]); // det = -det; 15 | if(v[now][now] == 0) return ans; 16 | int inv = ppow(v[now][now] , GAUSS_MOD - 2); 17 | REP(i , 0 , n) if(i != now){ 18 | int tmp = v[i][now] * inv % GAUSS_MOD; 19 | REP(j , now , n + 1) (v[i][j] += GAUSS_MOD - tmp * v[now][j] % GAUSS_MOD) %= GAUSS_MOD; 20 | } 21 | } 22 | REP(i , 0 , n) ans[i] = v[i][n + 1] * ppow(v[i][i] , GAUSS_MOD - 2) % GAUSS_MOD; 23 | return ans; 24 | } 25 | // gs.v.clear() , gs.v.resize(n , vector(n + 1 , 0)); 26 | } gs; -------------------------------------------------------------------------------- /math/heapSubtreeCount.cpp: -------------------------------------------------------------------------------- 1 | pair heapSubtreeCount(ll x) { 2 | if (x == 1) return {0, 0}; 3 | ll h = __lg(x); 4 | ll fill = (1LL << (h + 1)) - 1; 5 | ll l = (1LL << h) - 1 - max(0LL, fill - x - (1LL << (h - 1))); 6 | ll r = x - 1 - l; 7 | return {l, r}; 8 | }; -------------------------------------------------------------------------------- /math/inverse.cpp: -------------------------------------------------------------------------------- 1 | f[0]=1; //f[x]=x! 2 | for(ll i=1;i Poly; 3 | //S:前i項的值,tr:遞迴系數,k:求第k項 4 | ll linearRec(Poly& S, Poly& tr, ll k) { 5 | int n = tr.size(); 6 | auto combine = [&](Poly& a, Poly& b) { 7 | Poly res(n * 2 + 1); 8 | rep(i,0,n+1) rep(j,0,n+1) 9 | res[i+j]=(res[i+j] + a[i]*b[j])%mod; 10 | for(int i = 2*n; i > n; --i) rep(j,0,n) 11 | res[i-1-j]=(res[i-1-j] + res[i]*tr[j])%mod; 12 | res.resize(n + 1); 13 | return res; 14 | }; 15 | Poly pol(n + 1), e(pol); 16 | pol[0] = e[1] = 1; 17 | for (++k; k; k /= 2) { 18 | if (k % 2) pol = combine(pol, e); 19 | e = combine(e, e); 20 | } 21 | ll res = 0; 22 | rep(i,0,n) res=(res + pol[i+1]*S[i])%mod; 23 | return res; 24 | } -------------------------------------------------------------------------------- /math/ntt.cpp: -------------------------------------------------------------------------------- 1 | // Remember coefficient are mod P 2 | /* p=a*2^n+1 3 | n 2^n p a root 4 | 16 65536 65537 1 3 5 | 20 1048576 7340033 7 3 */ 6 | // (must be 2^k) 7 | template 8 | struct NTT{ 9 | static LL bigmod(LL a, LL b) { 10 | LL res = 1; 11 | for (LL bs = a; b; b >>= 1, bs = (bs * bs) % P) 12 | if(b&1) res=(res*bs)%P; 13 | return res; 14 | } 15 | static LL inv(LL a, LL b) { 16 | if(a==1)return 1; 17 | return (((LL)(a-inv(b%a,a))*b+1)/a)%b; 18 | } 19 | LL omega[MAXN+1]; 20 | NTT() { 21 | omega[0] = 1; 22 | LL r = bigmod(root, (P-1)/MAXN); 23 | for (int i=1; i<=MAXN; i++) 24 | omega[i] = (omega[i-1]*r)%P; 25 | } 26 | // n must be 2^k 27 | void tran(int n, LL a[], bool inv_ntt=false){ 28 | int basic = MAXN / n , theta = basic; 29 | for (int m = n; m >= 2; m >>= 1) { 30 | int mh = m >> 1; 31 | for (int i = 0; i < mh; i++) { 32 | LL w = omega[i*theta%MAXN]; 33 | for (int j = i; j < n; j += m) { 34 | int k = j + mh; 35 | LL x = a[j] - a[k]; 36 | if (x < 0) x += P; 37 | a[j] += a[k]; 38 | if (a[j] > P) a[j] -= P; 39 | a[k] = (w * x) % P; 40 | } 41 | } 42 | theta = (theta * 2) % MAXN; 43 | } 44 | int i = 0; 45 | for (int j = 1; j < n - 1; j++) { 46 | for (int k = n >> 1; k > (i ^= k); k >>= 1); 47 | if (j < i) swap(a[i], a[j]); 48 | } 49 | if (inv_ntt) { 50 | LL ni = inv(n,P); 51 | reverse( a+1 , a+n ); 52 | for (i = 0; i < n; i++) 53 | a[i] = (a[i] * ni) % P; 54 | } } }; 55 | const LL P=2013265921,root=31; 56 | const int MAXN=4194304; 57 | NTT ntt; 58 | -------------------------------------------------------------------------------- /math/phi.cpp: -------------------------------------------------------------------------------- 1 | ll phi(ll n){ // 計算小於n的數中與n互質的有幾個 2 | ll res = n, a=n; // O(sqrtN) 3 | for(ll i=2;i*i<=a;i++){ 4 | if(a%i==0){ 5 | res = res/i*(i-1); 6 | while(a%i==0) a/=i; 7 | } } 8 | if(a>1) res = res/a*(a-1); 9 | return res; 10 | } -------------------------------------------------------------------------------- /math/pollardRho.cpp: -------------------------------------------------------------------------------- 1 | // does not work when n is prime O(n^(1/4)) 2 | LL f(LL x, LL c, LL mod){ return add(mul(x,x,mod),c,mod); } 3 | LL pollard_rho(LL n) { 4 | LL c = 1, x = 0, y = 0, p = 2, q, t = 0; 5 | while (t++ % 128 or gcd(p, n) == 1) { 6 | if (x == y) c++, y = f(x = 2, c, n); 7 | if (q = mul(p, abs(x-y), n)) p = q; 8 | x = f(x, c, n); y = f(f(y, c, n), c, n); 9 | } 10 | return gcd(p, n); 11 | } -------------------------------------------------------------------------------- /math/polyop.cpp: -------------------------------------------------------------------------------- 1 | struct PolyOp { 2 | #define FOR(i, c) for (int i = 0; i < (c); ++i) 3 | NTT ntt; 4 | static int nxt2k(int x) { 5 | int i = 1; for (; i < x; i <<= 1); return i; 6 | } 7 | void Mul(int n, LL a[], int m, LL b[], LL c[]) { 8 | static LL aa[MAXN], bb[MAXN]; 9 | int N = nxt2k(n+m); 10 | copy(a, a+n, aa); fill(aa+n, aa+N, 0); 11 | copy(b, b+m, bb); fill(bb+m, bb+N, 0); 12 | ntt(N, aa); ntt(N, bb); 13 | FOR(i, N) c[i] = aa[i] * bb[i] % P; 14 | ntt(N, c, 1); 15 | } 16 | void Inv(int n, LL a[], LL b[]) { 17 | // ab = aa^-1 = 1 mod x^(n/2) 18 | // (b - a^-1)^2 = 0 mod x^n 19 | // bb - a^-2 + 2 ba^-1 = 0 20 | // bba - a^-1 + 2b = 0 21 | // bba + 2b = a^-1 22 | static LL tmp[MAXN]; 23 | if (n == 1) {b[0] = ntt.inv(a[0], P); return;} 24 | Inv((n+1)/2, a, b); 25 | int N = nxt2k(n*2); 26 | copy(a, a+n, tmp); 27 | fill(tmp+n, tmp+N, 0); 28 | fill(b+n, b+N, 0); 29 | ntt(N, tmp); ntt(N, b); 30 | FOR(i, N) { 31 | LL t1 = (2 - b[i] * tmp[i]) % P; 32 | if (t1 < 0) t1 += P; 33 | b[i] = b[i] * t1 % P; 34 | } 35 | ntt(N, b, 1); 36 | fill(b+n, b+N, 0); 37 | } 38 | void Div(int n, LL a[], int m, LL b[], LL d[], LL r[]) { 39 | // Ra = Rb * Rd mod x^(n-m+1) 40 | // Rd = Ra * Rb^-1 mod 41 | static LL aa[MAXN], bb[MAXN], ta[MAXN], tb[MAXN]; 42 | if (n < m) {copy(a, a+n, r); fill(r+n, r+m, 0); return;} 43 | // d: n-1 - (m-1) = n-m (n-m+1 terms) 44 | copy(a, a+n, aa); copy(b, b+m, bb); 45 | reverse(aa, aa+n); reverse(bb, bb+m); 46 | Inv(n-m+1, bb, tb); 47 | Mul(n-m+1, ta, n-m+1, tb, d); 48 | fill(d+n-m+1, d+n, 0); reverse(d, d+n-m+1); 49 | // r: m-1 - 1 = m-2 (m-1 terms) 50 | Mul(m, b, n-m+1, d, ta); 51 | FOR(i, n) { r[i] = a[i] - ta[i]; if (r[i] < 0) r[i] += P; } 52 | } 53 | void dx(int n, LL a[], LL b[]) { REP(i, 1, n-1) b[i-1] = i * a[i] % P; } 54 | void Sx(int n, LL a[], LL b[]) { 55 | b[0] = 0; 56 | FOR(i, n) b[i+1] = a[i] * ntt.iv[i+1] % P; 57 | } 58 | void Ln(int n, LL a[], LL b[]) { 59 | // Integral a' a^-1 dx 60 | static LL a1[MAXN], a2[MAXN], b1[MAXN]; 61 | int N = nxt2k(n*2); 62 | dx(n, a, a1); Inv(n, a, a2); 63 | Mul(n-1, a1, n, a2, b1); 64 | Sx(n+n-1-1, b1, b); 65 | fill(b+n, b+N, 0); 66 | } 67 | void Exp(int n, LL a[], LL b[]) { 68 | // Newton method to solve g(a(x)) = ln b(x) - a(x) = 0 69 | // b' = b - g(b(x)) / g'(b(x)) 70 | // b' = b (1 - lnb + a) 71 | static LL lnb[MAXN], c[MAXN], tmp[MAXN]; 72 | assert(a[0] == 0); // dont know exp(a[0]) mod P 73 | if (n == 1) {b[0] = 1; return;} 74 | Exp((n+1)/2, a, b); 75 | fill(b+(n+1)/2, b+n, 0); 76 | Ln(n, b, lnb); 77 | fill(c, c+n, 0); c[0] = 1; 78 | FOR(i, n) { 79 | c[i] += a[i] - lnb[i]; 80 | if (c[i] < 0) c[i] += P; 81 | if (c[i] >= P) c[i] -= P; 82 | } 83 | Mul(n, b, n, c, tmp); 84 | copy(tmp, tmp+n, b); 85 | } 86 | } polyop; 87 | -------------------------------------------------------------------------------- /math/prefixInv.cpp: -------------------------------------------------------------------------------- 1 | void solve( int m ){ 2 | inv[ 1 ] = 1; 3 | for( int i = 2 ; i < m ; i ++ ) 4 | inv[ i ] = ((LL)(m - m / i) * inv[m % i]) % m; 5 | } 6 | -------------------------------------------------------------------------------- /math/primes.cpp: -------------------------------------------------------------------------------- 1 | /* 12721, 13331, 14341, 75577, 123457, 222557, 556679 2 | * 999983, 1097774749, 1076767633, 100102021, 999997771 3 | * 1001010013, 1000512343, 987654361, 999991231 4 | * 999888733, 98789101, 987777733, 999991921, 1010101333 5 | * 1010102101, 1000000000039, 1000000000000037 6 | * 2305843009213693951, 4611686018427387847 7 | * 9223372036854775783, 18446744073709551557 */ 8 | int mu[ N ] , p_tbl[ N ]; 9 | vector primes; 10 | void sieve() { 11 | mu[ 1 ] = p_tbl[ 1 ] = 1; 12 | for( int i = 2 ; i < N ; i ++ ){ 13 | if( !p_tbl[ i ] ){ 14 | p_tbl[ i ] = i; 15 | primes.push_back( i ); 16 | mu[ i ] = -1; 17 | } 18 | for( int p : primes ){ 19 | int x = i * p; 20 | if( x >= M ) break; 21 | p_tbl[ x ] = p; 22 | mu[ x ] = -mu[ i ]; 23 | if( i % p == 0 ){ 24 | mu[ x ] = 0; 25 | break; 26 | } } } } 27 | vector factor( int x ){ 28 | vector fac{ 1 }; 29 | while( x > 1 ){ 30 | int fn = SZ(fac), p = p_tbl[ x ], pos = 0; 31 | while( x % p == 0 ){ 32 | x /= p; 33 | for( int i = 0 ; i < fn ; i ++ ) 34 | fac.PB( fac[ pos ++ ] * p ); 35 | } } 36 | return fac; 37 | } 38 | -------------------------------------------------------------------------------- /math/rootsOfPolynomial.cpp: -------------------------------------------------------------------------------- 1 | const double eps = 1e-12; 2 | const double inf = 1e+12; 3 | double a[ 10 ], x[ 10 ]; // a[0..n](coef) must be filled 4 | int n; // degree of polynomial must be filled 5 | int sign( double x ){return (x < -eps)?(-1):(x>eps);} 6 | double f(double a[], int n, double x){ 7 | double tmp=1,sum=0; 8 | for(int i=0;i<=n;i++) 9 | { sum=sum+a[i]*tmp; tmp=tmp*x; } 10 | return sum; 11 | } 12 | double binary(double l,double r,double a[],int n){ 13 | int sl=sign(f(a,n,l)),sr=sign(f(a,n,r)); 14 | if(sl==0) return l; if(sr==0) return r; 15 | if(sl*sr>0) return inf; 16 | while(r-l>eps){ 17 | double mid=(l+r)/2; 18 | int ss=sign(f(a,n,mid)); 19 | if(ss==0) return mid; 20 | if(ss*sl>0) l=mid; else r=mid; 21 | } 22 | return l; 23 | } 24 | void solve(int n,double a[],double x[],int &nx){ 25 | if(n==1){ x[1]=-a[0]/a[1]; nx=1; return; } 26 | double da[10], dx[10]; int ndx; 27 | for(int i=n;i>=1;i--) da[i-1]=a[i]*i; 28 | solve(n-1,da,dx,ndx); 29 | nx=0; 30 | if(ndx==0){ 31 | double tmp=binary(-inf,inf,a,n); 32 | if (tmp <-mod 4 = 3 prime-> 18 | then D1 - D3 = (e1+1)(e2+1)...(er+1) if fi all even 19 | 0 if any fi is odd 20 | -- 21 | Pick’s Theorem 22 | A = i + b/2 - 1 23 | */ 24 | -------------------------------------------------------------------------------- /other-codebook/ICPC-Cheat-sheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/other-codebook/ICPC-Cheat-sheet.pdf -------------------------------------------------------------------------------- /other-codebook/mycodebook .docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/other-codebook/mycodebook .docx -------------------------------------------------------------------------------- /other-codebook/notebook.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/other-codebook/notebook.pdf -------------------------------------------------------------------------------- /others/DeBrujin.cpp: -------------------------------------------------------------------------------- 1 | // return cyclic array of length k^n such that every 2 | // array of length n using 0~k-1 appears as a subarray. 3 | vector DeBruijn(int k,int n){ 4 | if(k==1) return {0}; 5 | vector aux(k*n),res; 6 | function f=[&](int t,int p)->void{ 7 | if(t>n){ if(n%p==0) 8 | for(int i=1;i<=p;++i) res.push_back(aux[i]); 9 | }else{ 10 | aux[t]=aux[t-p]; f(t+1,p); 11 | for(aux[t]=aux[t-p]+1;aux[t]>=1){ 4 | int rx=(x&s)>0,ry=(y&s)>0; res+=s*1ll*s*((3*rx)^ry); 5 | if(ry==0){ if(rx==1) x=s-1-x,y=s-1-y; swap(x,y); } 6 | } 7 | return res; 8 | } -------------------------------------------------------------------------------- /others/QQ.cpp: -------------------------------------------------------------------------------- 1 | ,▄∞w▄, ,╓∞═*═╖ 2 | 3 | ,M` ,▄▄▄, ⁿw, æⁿ▄▄▄████▄`▄ 4 | 5 | Æ`,▄████▀▀▀ⁿ ▀w ▄╜─"██████████▐ 6 | 7 | ▐ ▄████▀▀▀═ ▀▓▒▒▒▒▒▒▒▒▒▒BBN╦▄,▄ "▀▀▀███████ ▌ 8 | 9 | ▌]██████▄ ,▄▓▒▒▒▒▒╨▒▒▒▒▒▒▒▒▒▒▒▒Nw, ``▀██████ C 10 | 11 | ▐ ▐█████▀` ,╥$▒▒╝╨╜╜╜╨╝╝╣▒▒▒▒▒▒▒▒▒▒╢╢▒▒▒▒N▄ ▐▀███▌▐ 12 | 13 | ▐ ▓████▄ ,m╜" ╙╝▒██▒▒╝╜╙"``"╙╙╨N▐███"║ 14 | 15 | ▄▒⌐▐████▄",╝ ,,,,, ███ ▀██ 16 | 17 | ▄▀▒▒▌ ████▌╛ ╓▄▄███████████▄▄ ▐███▌ ,,,▄,,, *▌ 18 | 19 | ,█▒▒▒▒▒ ▐███" ▄█████████▓██████████▄ █████▄▄███████████▄▄ ╗ 20 | 21 | ▄▀▒▒▒▒▒▒▓ ▀▓▌▄████████████████████████████████████▓████████▄▄ 22 | 23 | ▐▌▒▒▒▒▒▒▒▒▀Ç██████████████▒█████████████████████████▐▓████████ 24 | 25 | ▌▒▒▒▒▒▒▒▒▒▒▓█████████████▌╢ ██▌███████▀ `█▓█▓████╜▒█████████▌ 26 | 27 | █▒▒▒▒▒▒▒▒▒╫╣▓█████████████▒ '█▌ ███▒▌ ,▀██▀▐█` ║▐████████▌ 28 | 29 | ▌▒▒▒▒▒▒▒▒▓╢▒█████████████▌` ,▄▄█▌ ▀█▌▒▄ ╓`█▀╓▄█, ║▒████████▌ 30 | 31 | ▐▒▒▒▒▒▒▒╫╣╢╢███▓██████████▄██▀▀` ▀ ╙▀, ▄ ▀█▄]▒████████ 32 | 33 | █▒▒▒▒▒▒╬╣╢╢▓████▓███████████▓▓▄ ⁿ ,▓▓██▄███████ 34 | 35 | █▒▒▒▒▒▓╢╢╢╢██████████▓████▓▓▓▓▓ ▓▓▓▓▓█▌█████ 36 | 37 | █▒▒▒▒▓╢╢╢╢╫▓█████████▒▒██ ▓▓▓▓▓▌ ▓▓▓▓▌███████⌐ 38 | 39 | █▒▒▒▓╢╢╢╢╢▐██████████▒ ` ▓▓▓▓▓` ▓▓▓▓▌▐▌▀ ███▌ 40 | 41 | █▒▒▓╢╢╢╢╢╢███████████▒ ▓▓▓▓▓ ▓▓▓▓ ████ 42 | 43 | █▒▓╢╢╢╢╢╢▓███████████▌U ▀▀▀ ▀▀ ▐████ 44 | 45 | ▌╫╢╢╢╢╢╢╫▌▐██████████▌[ █████ 46 | 47 | ▌▒▌╢╢╢╢╢╢▌▐███████████▒ ▀█▓██ 48 | 49 | ▐▀ ▌╢╢╢╢╢╢▒████████████▒U \ ▀╜ ██ 50 | 51 | '▌╢╢╢╢╢█╣▒███████████▒╢ ,██ 52 | 53 | ▐╢╢╢▓▀▐▒████████████▒▒╖ ,▄█▓██ 54 | 55 | █▓▀ ▐█ ███████████▒░░▒"*═∞w▄▄,, ,,,▄▄∞▐██▓██████ 56 | 57 | ▀ ██▓███████▌░░░, `- - ,╓▌ ▓███████▌ 58 | 59 | █▀█████░█▌░░░░░▒, ., ,, , ╓∩▒▒░░▌ ████████ 60 | 61 | ████▓▌░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓█ ▀█▀ 62 | 63 | ▐╢▓▓▓▓▓╢▓▓▄░▄▄▐▓▓▓▓█▓▄░░░▄█▓▓▓█▓▓╣╣▓╢█ 64 | 65 | ╒▌▒▒▓▓▓▓▓▓▓╢╢▓╢█▓▓▓█████████▓▓▓▓▌▓▓▓▓▓▓▌ 66 | 67 | █▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓████████▓███████▌▓▓▓▓▓▓█ 68 | 69 | ]▌▒▒▒▒▒▓▓▓▓▓▓▓▓▓▓████████▓███████▓▓▓▓▓▓▓█ 70 | 71 | ▐▒▒▒▒▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓████▌▓█████▓▓▓▓▓▓▓▓▓▓▌ -------------------------------------------------------------------------------- /others/SOS_dp.cpp: -------------------------------------------------------------------------------- 1 | for(int i = 0; i<(1< 4 | using namespace std; 5 | #define N 1024 //row 6 | #define M 1024 //column 7 | #define NM ((N+2)*(M+2)) 8 | char A[N][M]; //n*m 0-1 matrix 9 | int used[N]; //answer: the row used 10 | int id[N][M],L[NM],R[NM],D[NM],U[NM],C[NM],S[NM],ROW[NM]; 11 | void remove(int c){ 12 | L[R[c]]=L[c]; R[L[c]]=R[c]; 13 | for( int i=D[c]; i!=c; i=D[i] ) 14 | for( int j=R[i]; j!=i; j=R[j] ){ 15 | U[D[j]]=U[j]; D[U[j]]=D[j]; S[C[j]]--; } 16 | } 17 | void resume(int c){ 18 | for( int i=D[c]; i!=c; i=D[i] ) 19 | for( int j=L[i]; j!=i; j=L[j] ){ 20 | U[D[j]]=D[U[j]]=j; S[C[j]]++; } 21 | L[R[c]]=R[L[c]]=c; 22 | } 23 | int dfs(){ 24 | if(R[0]==0) return 1; 25 | int md=100000000,c; 26 | for( int i=R[0]; i!=0; i=R[i] ) 27 | if(S[i] v; 74 | for( int i = 0 ; i < n ; i ++ ) 75 | if( used[ i ] ) 76 | v.push_back( i + 1 ); 77 | printf( "%d" , (int)v.size() ); 78 | for( size_t i = 0 ; i < v.size() ; i ++ ) 79 | printf( " %d" , v[ i ] ); 80 | puts( "" ); 81 | }else puts( "NO" ); 82 | } } 83 | -------------------------------------------------------------------------------- /others/funny.cpp: -------------------------------------------------------------------------------- 1 | @ 2 | (__) (__) ____/ Hong~Long~Long~Long~ 3 | /| (oo) _ (oo)/----/_____ * 4 | _o\______/_|\_\/_/_|__\/|____|//////== *- * * - 5 | /__________ \ AC | AC | NO BUG /== -* 6 | [_____/^^\_____\_____|_____/^^\_____] *- * - 7 | \__/ \__/ Chong~Chong~Chong~ -------------------------------------------------------------------------------- /others/maxtan.cpp: -------------------------------------------------------------------------------- 1 | const int MAXN = 100010; 2 | Pt sum[MAXN], pnt[MAXN], ans, calc; 3 | inline bool cross(Pt a, Pt b, Pt c){ 4 | return (c.y-a.y)*(c.x-b.x) > (c.x-a.x)*(c.y-b.y); 5 | }//pt[0]=(0,0);pt[i]=(i,pt[i-1].y+dy[i-1]),i=1~n;dx>=l 6 | double find_max_tan(int n,int l,LL dy[]){ 7 | int np, st, ed, now; 8 | sum[0].x = sum[0].y = np = st = ed = 0; 9 | for (int i = 1, v; i <= n; i++) 10 | sum[i].x=i,sum[i].y=sum[i-1].y+dy[i-1]; 11 | ans.x = now = 1,ans.y = -1; 12 | for (int i = 0; i <= n - l; i++){ 13 | while(np>1&&cross(pnt[np-2],pnt[np-1],sum[i])) 14 | np--; 15 | if (np < now && np != 0) now = np; 16 | pnt[np++] = sum[i]; 17 | while(now>2)-(c<<1)+y+(y>>2)+(13*(m+1)/5)+d-1)%7; 6 | if (w<0) w+=7; return(w); 7 | } 8 | -------------------------------------------------------------------------------- /scoreboard/NCPCfinal2018.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/NCPCfinal2018.pdf -------------------------------------------------------------------------------- /scoreboard/NCPCfinal2019.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/NCPCfinal2019.pdf -------------------------------------------------------------------------------- /scoreboard/NCPCfinal2020.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/NCPCfinal2020.jpg -------------------------------------------------------------------------------- /scoreboard/NCPCfinal2021.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/NCPCfinal2021.png -------------------------------------------------------------------------------- /scoreboard/NCPCfinal2022.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/NCPCfinal2022.pdf -------------------------------------------------------------------------------- /scoreboard/NCPCfinal2023.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/NCPCfinal2023.png -------------------------------------------------------------------------------- /scoreboard/NCPCfinal2024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/NCPCfinal2024.png -------------------------------------------------------------------------------- /scoreboard/NCPCpreliminary2019.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/NCPCpreliminary2019.pdf -------------------------------------------------------------------------------- /scoreboard/NCPCpreliminary2020.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/NCPCpreliminary2020.pdf -------------------------------------------------------------------------------- /scoreboard/NCPCpreliminary2021.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/NCPCpreliminary2021.png -------------------------------------------------------------------------------- /scoreboard/NCPCpreliminary2022.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/NCPCpreliminary2022.pdf -------------------------------------------------------------------------------- /scoreboard/NCPCpreliminary2023.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/NCPCpreliminary2023.png -------------------------------------------------------------------------------- /scoreboard/NCPCpreliminary2024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/NCPCpreliminary2024.png -------------------------------------------------------------------------------- /scoreboard/icpc2018.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/icpc2018.jpg -------------------------------------------------------------------------------- /scoreboard/icpc2020.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/icpc2020.pdf -------------------------------------------------------------------------------- /scoreboard/icpc2020.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/icpc2020.png -------------------------------------------------------------------------------- /scoreboard/icpc2021.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/icpc2021.png -------------------------------------------------------------------------------- /scoreboard/icpc2022.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/icpc2022.jpg -------------------------------------------------------------------------------- /scoreboard/icpc2023.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/icpc2023.jpeg -------------------------------------------------------------------------------- /scoreboard/icpc2024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/icpc2024.png -------------------------------------------------------------------------------- /scoreboard/topc2018.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/topc2018.jpg -------------------------------------------------------------------------------- /scoreboard/topc2020.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/topc2020.pdf -------------------------------------------------------------------------------- /scoreboard/topc2021.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/topc2021.png -------------------------------------------------------------------------------- /scoreboard/topc2022.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/topc2022.png -------------------------------------------------------------------------------- /scoreboard/topc2023.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/topc2023.png -------------------------------------------------------------------------------- /scoreboard/topc2024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakao0907/CompetitiveProgrammingCodebook/aa677ed2429aa764f1b2ccd29a6afb5182866382/scoreboard/topc2024.png -------------------------------------------------------------------------------- /string/Aho-Corasick.cpp: -------------------------------------------------------------------------------- 1 | struct ACautomata{ 2 | struct Node{ 3 | int cnt,i; 4 | Node *go[26], *fail, *dic; 5 | Node (){ 6 | cnt = 0; fail = 0; dic = 0; i = 0; 7 | memset(go,0,sizeof(go)); 8 | } 9 | }pool[1048576],*root; 10 | int nMem,n_pattern; 11 | Node* new_Node(){ 12 | pool[nMem] = Node(); 13 | return &pool[nMem++]; 14 | } 15 | void init() { 16 | nMem=0;root=new_Node();n_pattern=0; 17 | add(""); 18 | } 19 | void add(const string &str) { insert(root,str,0); } 20 | void insert(Node *cur, const string &str, int pos){ 21 | for(int i=pos;igo[str[i]-'a']) 23 | cur->go[str[i]-'a'] = new_Node(); 24 | cur=cur->go[str[i]-'a']; 25 | } 26 | cur->cnt++; cur->i=n_pattern++; 27 | } 28 | void make_fail(){ 29 | queue que; 30 | que.push(root); 31 | while (!que.empty()){ 32 | Node* fr=que.front(); que.pop(); 33 | for (int i=0; i<26; i++){ 34 | if (fr->go[i]){ 35 | Node *ptr = fr->fail; 36 | while (ptr && !ptr->go[i]) ptr = ptr->fail; 37 | fr->go[i]->fail=ptr=(ptr?ptr->go[i]:root); 38 | fr->go[i]->dic=(ptr->cnt?ptr:ptr->dic); 39 | que.push(fr->go[i]); 40 | } } } } 41 | void query(string s){ 42 | Node *cur=root; 43 | for(int i=0;i<(int)s.size();i++){ 44 | while(cur&&!cur->go[s[i]-'a']) cur=cur->fail; 45 | cur=(cur?cur->go[s[i]-'a']:root); 46 | if(cur->i>=0) ans[cur->i]++; 47 | for(Node *tmp=cur->dic;tmp;tmp=tmp->dic) 48 | ans[tmp->i]++; 49 | } }// ans[i] : number of occurrence of pattern i 50 | }AC; 51 | -------------------------------------------------------------------------------- /string/BWT.cpp: -------------------------------------------------------------------------------- 1 | struct BurrowsWheeler{ 2 | #define SIGMA 26 3 | #define BASE 'a' 4 | vector v[ SIGMA ]; 5 | void BWT(char* ori, char* res){ 6 | // make ori -> ori + ori 7 | // then build suffix array 8 | } 9 | void iBWT(char* ori, char* res){ 10 | for( int i = 0 ; i < SIGMA ; i ++ ) 11 | v[ i ].clear(); 12 | int len = strlen( ori ); 13 | for( int i = 0 ; i < len ; i ++ ) 14 | v[ ori[i] - BASE ].push_back( i ); 15 | vector a; 16 | for( int i = 0 , ptr = 0 ; i < SIGMA ; i ++ ) 17 | for( auto j : v[ i ] ){ 18 | a.push_back( j ); 19 | ori[ ptr ++ ] = BASE + i; 20 | } 21 | for( int i = 0 , ptr = 0 ; i < len ; i ++ ){ 22 | res[ i ] = ori[ a[ ptr ] ]; 23 | ptr = a[ ptr ]; 24 | } 25 | res[ len ] = 0; 26 | } 27 | } bwt; 28 | -------------------------------------------------------------------------------- /string/KMP.cpp: -------------------------------------------------------------------------------- 1 | /* len-failure[k]: 2 | 在k結尾的情況下,這個子字串可以由開頭 3 | 長度為(len-failure[k])的部分重複出現來表達 4 | 5 | failure[k]為次長相同前綴後綴 6 | 如果我們不只想求最多,而且以0-base做為考量 7 | ,那可能的長度由大到小會是 8 | failuer[k]、failure[failuer[k]-1] 9 | 、failure[failure[failuer[k]-1]-1].. 10 | 直到有值為0為止 */ 11 | int failure[MXN]; 12 | vector KMP(string& t, string& p){ 13 | vector ret; 14 | if (p.size() > t.size()) return {}; 15 | for (int i=1, j=failure[0]=-1; i= 0 && p[j+1] != p[i]) 17 | j = failure[j]; 18 | if (p[j+1] == p[i]) j++; 19 | failure[i] = j; 20 | } 21 | for (int i=0, j=-1; i= 0 && p[j+1] != t[i]) 23 | j = failure[j]; 24 | if (p[j+1] == t[i]) j++; 25 | if (j == p.size()-1){ 26 | ret.push_back( i - p.size() + 1 ); 27 | j = failure[j]; 28 | }} 29 | return ret; 30 | } -------------------------------------------------------------------------------- /string/PalTree.cpp: -------------------------------------------------------------------------------- 1 | // sfail: compressed fail links with same diff 2 | // O(lgn): length of sfail link path 3 | const int MAXN = 1e6+10; 4 | struct PalT{ 5 | int tot,lst; 6 | int nxt[MAXN][26], len[MAXN]; 7 | int fail[MAXN], diff[MAXN], sfail[MAXN]; 8 | char* s; 9 | int newNode(int l, int _fail) { 10 | int res = ++tot; 11 | fill(nxt[res], nxt[res]+26, 0); 12 | len[res] = l, fail[res] = _fail; 13 | diff[res] = l - len[_fail]; 14 | if (diff[res] == diff[_fail]) 15 | sfail[res] = sfail[_fail]; 16 | else 17 | sfail[res] = _fail; 18 | return res; 19 | } 20 | void push(int p) { 21 | int np = lst; 22 | int c = s[p]-'a'; 23 | while (p-len[np]-1 < 0 || s[p] != s[p-len[np]-1]) 24 | np = fail[np]; 25 | if ((lst=nxt[np][c])) return; 26 | int nq_f = 0; 27 | if (len[np]+2 == 1) nq_f = 2; 28 | else { 29 | int tf = fail[np]; 30 | while (p-len[tf]-1 < 0 || s[p] != s[p-len[tf]-1]) 31 | tf = fail[tf]; 32 | nq_f = nxt[tf][c]; 33 | } 34 | int nq = newNode(len[np]+2, nq_f); 35 | nxt[np][c] = nq; 36 | lst=nq; 37 | } 38 | void init(char* _s){ 39 | s = _s; 40 | tot = 0; 41 | newNode(-1, 1); 42 | newNode(0, 1); 43 | diff[2] = 0; 44 | lst = 2; 45 | } 46 | } palt; 47 | -------------------------------------------------------------------------------- /string/PalTree1.cpp: -------------------------------------------------------------------------------- 1 | const int MXN = 1000010; 2 | struct PalT{ 3 | int nxt[MXN][26],fail[MXN],len[MXN]; 4 | int tot,lst,n,state[MXN],cnt[MXN],num[MXN]; 5 | char s[MXN]={-1}; 6 | int newNode(int l,int f){ 7 | len[tot]=l,fail[tot]=f,cnt[tot]=num[tot]=0; 8 | memset(nxt[tot],0,sizeof(nxt[tot])); 9 | return tot++; 10 | } 11 | int getfail(int x){ 12 | while(s[n-len[x]-1]!=s[n]) x=fail[x]; 13 | return x; 14 | } 15 | int push(){ 16 | int c=s[n]-'a',np=getfail(lst); 17 | if(!(lst=nxt[np][c])){ 18 | lst=newNode(len[np]+2,nxt[getfail(fail[np])][c]); 19 | nxt[np][c]=lst; 20 | num[lst]=num[fail[lst]]+1; 21 | } 22 | return ++cnt[lst],lst; 23 | } 24 | void init(const char *_s){ 25 | tot=lst=n=0; 26 | newNode(0,1),newNode(-1,0); 27 | for(;_s[n];) s[n+1]=_s[n],++n,state[n-1]=push(); 28 | for(int i=tot-1;i>1;i--) cnt[fail[i]]+=cnt[i]; 29 | } 30 | }palt; 31 | -------------------------------------------------------------------------------- /string/PalTree2.cpp: -------------------------------------------------------------------------------- 1 | // len[s]是對應的回文長度 2 | // num[s]是有幾個回文後綴 3 | // cnt[s]是這個回文子字串在整個字串中的出現次數 4 | // fail[s]是他長度次長的回文後綴,aba的fail是a 5 | const int MXN = 1000010; 6 | struct PalT{ 7 | int nxt[MXN][26],fail[MXN],len[MXN]; 8 | int tot,lst,n,state[MXN],cnt[MXN],num[MXN]; 9 | int diff[MXN],sfail[MXN],fac[MXN],dp[MXN]; 10 | char s[MXN]={-1}; 11 | int newNode(int l,int f){ 12 | len[tot]=l,fail[tot]=f,cnt[tot]=num[tot]=0; 13 | memset(nxt[tot],0,sizeof(nxt[tot])); 14 | diff[tot]=(l>0?l-len[f]:0); 15 | sfail[tot]=(l>0&&diff[tot]==diff[f]?sfail[f]:f); 16 | return tot++; 17 | } 18 | int getfail(int x){ 19 | while(s[n-len[x]-1]!=s[n]) x=fail[x]; 20 | return x; 21 | } 22 | int getmin(int v){ 23 | dp[v]=fac[n-len[sfail[v]]-diff[v]]; 24 | if(diff[v]==diff[fail[v]]) 25 | dp[v]=min(dp[v],dp[fail[v]]); 26 | return dp[v]+1; 27 | } 28 | int push(){ 29 | int c=s[n]-'a',np=getfail(lst); 30 | if(!(lst=nxt[np][c])){ 31 | lst=newNode(len[np]+2,nxt[getfail(fail[np])][c]); 32 | nxt[np][c]=lst; num[lst]=num[fail[lst]]+1; 33 | } 34 | fac[n]=n; 35 | for(int v=lst;len[v]>0;v=sfail[v]) 36 | fac[n]=min(fac[n],getmin(v)); 37 | return ++cnt[lst],lst; 38 | } 39 | void init(const char *_s){ 40 | tot=lst=n=0; 41 | newNode(0,1),newNode(-1,1); 42 | for(;_s[n];) s[n+1]=_s[n],++n,state[n-1]=push(); 43 | for(int i=tot-1;i>1;i--) cnt[fail[i]]+=cnt[i]; 44 | } 45 | }palt; -------------------------------------------------------------------------------- /string/RollingHash.cpp: -------------------------------------------------------------------------------- 1 | struct RollingHash{ 2 | #define psz 2 3 | vector primes={17, 75577}; 4 | vector MOD={998244353, 1000000007}; 5 | vector> hash, base; 6 | void init(const string &s){ 7 | hash.clear(); hash.resize(s.size()); 8 | base.clear(); base.resize(s.size()); 9 | for(int i=0;i getHash(int l,int r){ 21 | if(l == 0) return hash[r]; 22 | array ret = hash[r]; 23 | for(int i=0;i0 ? max(hei[r[i-1]] - 1, 0) : 0; 18 | while(_s[i+ans] == _s[_sa[r[i]-1]+ans]) ans++; 19 | hei[r[i]] = ans; 20 | } 21 | } 22 | void sais(int *s, int *sa, int *p, int *q, bool *t, int *c, int n, int z){ 23 | bool uniq = t[n-1] = true, neq; 24 | int nn = 0, nmxz = -1, *nsa = sa + n, *ns = s + n, lst = -1; 25 | #define MS0(x,n) memset((x),0,n*sizeof(*(x))) 26 | #define MAGIC(XD) MS0(sa, n); \ 27 | memcpy(x, c, sizeof(int) * z); \ 28 | XD; \ 29 | memcpy(x + 1, c, sizeof(int) * (z - 1)); \ 30 | REP(i,n) if(sa[i] && !t[sa[i]-1]) sa[x[s[sa[i]-1]]++] = sa[i]-1; \ 31 | memcpy(x, c, sizeof(int) * z); \ 32 | for(int i = n - 1; i >= 0; i--) if(sa[i] && t[sa[i]-1]) sa[--x[s[sa[i]-1]]] = sa[i]-1; 33 | MS0(c, z); 34 | REP(i,n) uniq &= ++c[s[i]] < 2; 35 | REP(i,z-1) c[i+1] += c[i]; 36 | if (uniq) { REP(i,n) sa[--c[s[i]]] = i; return; } 37 | for(int i = n - 2; i >= 0; i--) t[i] = (s[i]==s[i+1] ? t[i+1] : s[i]= 0; i--) sa[--x[s[p[nsa[i]]]]] = p[nsa[i]]); 45 | } 46 | }sa; 47 | int H[ N ], SA[ N ]; 48 | void suffix_array(int* ip, int len) { 49 | // should padding a zero in the back 50 | // ip is int array, len is array length 51 | // ip[0..n-1] != 0, and ip[len] = 0 52 | ip[len++] = 0; 53 | sa.build(ip, len, 128); 54 | for (int i=0; i=0;i--)sa[--qe[s[p[i]]]]=p[i]; 17 | qe[0]=0; for(i=1;i0&&!iss[sa[i]-1])sa[qe[s[sa[i]-1]]++]=sa[i]-1; 19 | qe[0]=cnt[0]; for(i=1;i=0;i--)if(sa[i]>0&&iss[sa[i]-1])sa[--qe[s[sa[i]-1]]]=sa[i]-1; 21 | } 22 | inline bool eq(int *s,bool *iss,int *pp,int *pb,int pc,int x,int p){ 23 | if(pb[p]==pc-1 || pb[x]==pc-1 || pp[pb[p]+1]-p!=pp[pb[x]+1]-x)return 0; 24 | for(int j=0;j<=pp[pb[p]+1]-p;j++)if(s[j+p]!=s[j+x]||iss[j+p]!=iss[j+x]) return 0; 25 | return 1; 26 | } 27 | void suffixArray(int n,int a1=0){ 28 | int i; 29 | int *s=S+a1,*sa=SA+a1,*pp=_p+a1,*pb=_pb+a1; 30 | bool *iss=_iss+a1; 31 | iss[n-1]=1; 32 | for(i=n-2;i>=0;i--)iss[i]=s[i]=0;i--) 54 | cnt[mom[ind[i]]]+=cnt[ind[i]]; 55 | } 56 | void calc(int x){ 57 | v[x]=ds[x]=1;dsl[x]=0; //rmom[mom[x]].push_back(x); 58 | for(int i=1;i<=26;i++){ 59 | if(nxt[x][i]){ 60 | if(!v[nxt[x][i]]) calc(nxt[x][i]); 61 | ds[x]+=ds[nxt[x][i]]; 62 | dsl[x]+=ds[nxt[x][i]]+dsl[nxt[x][i]]; 63 | } } } 64 | void push(const string& str){ 65 | for(int i = 0; i < str.size() ; i++) 66 | push(str[i]-'a'+1); 67 | } 68 | } sam; -------------------------------------------------------------------------------- /string/SAM_test.cpp: -------------------------------------------------------------------------------- 1 | const int MAXM = 1000010; 2 | struct SAM{ 3 | int tot, root, lst, mom[MAXM], mx[MAXM]; 4 | int acc[MAXM], nxt[MAXM][33]; 5 | int newNode(){ 6 | int res = ++tot; 7 | fill(nxt[res], nxt[res]+33, 0); 8 | mom[res] = mx[res] = acc[res] = 0; 9 | return res; 10 | } 11 | void init(){ 12 | tot = 0; 13 | root = newNode(); 14 | mom[root] = 0, mx[root] = 0; 15 | lst = root; 16 | } 17 | void push(int c){ 18 | int p = lst; 19 | int np = newNode(); 20 | mx[np] = mx[p]+1; 21 | for(; p && nxt[p][c] == 0; p = mom[p]) 22 | nxt[p][c] = np; 23 | if(p == 0) mom[np] = root; 24 | else{ 25 | int q = nxt[p][c]; 26 | if(mx[p]+1 == mx[q]) mom[np] = q; 27 | else{ 28 | int nq = newNode(); 29 | mx[nq] = mx[p]+1; 30 | for(int i = 0; i < 33; i++) 31 | nxt[nq][i] = nxt[q][i]; 32 | mom[nq] = mom[q]; 33 | mom[q] = nq; 34 | mom[np] = nq; 35 | for(; p && nxt[p][c] == q; p = mom[p]) 36 | nxt[p][c] = nq; 37 | } 38 | } 39 | lst = np; 40 | } 41 | void print(){ 42 | REP(i, 1, tot){ 43 | printf("node %d :\n", i); 44 | printf("mx %d, mom %d\n", mx[i], mom[i]); 45 | REP(j, 1, 26) if(nxt[i][j]) 46 | printf("nxt %c %d\n", 'a'+j-1, nxt[i][j]); 47 | puts("---------------------------"); 48 | } 49 | } 50 | void push(char *str){ 51 | for(int i = 0; str[i]; i++) 52 | push(str[i]-'a'+1); 53 | } 54 | } sam; 55 | -------------------------------------------------------------------------------- /string/Suffix_Array.cpp: -------------------------------------------------------------------------------- 1 | const int MAX = 1020304; 2 | int ct[MAX], he[MAX], rk[MAX]; 3 | int sa[MAX], tsa[MAX], tp[MAX][2]; 4 | void suffix_array(char *ip){ 5 | int len = strlen(ip); 6 | int alp = 256; 7 | memset(ct, 0, sizeof(ct)); 8 | for(int i=0;i=len) tp[j][1]=0; 14 | else tp[j][1]=rk[j+i]+1; 15 | tp[j][0]=rk[j]; 16 | } 17 | memset(ct, 0, sizeof(ct)); 18 | for(int j=0;jsz++; 15 | if(now->nxt[i-'a'] == NULL){ 16 | now->nxt[i-'a'] = new node(); 17 | } 18 | now = now->nxt[i-'a']; 19 | } 20 | now->cnt++; 21 | now->sz++; 22 | } 23 | }; -------------------------------------------------------------------------------- /string/cyclicLCS.cpp: -------------------------------------------------------------------------------- 1 | #define L 0 2 | #define LU 1 3 | #define U 2 4 | const int mov[3][2]={0,-1, -1,-1, -1,0}; 5 | int al,bl; 6 | char a[MAXL*2],b[MAXL*2]; // 0-indexed 7 | int dp[MAXL*2][MAXL]; 8 | char pred[MAXL*2][MAXL]; 9 | inline int lcs_length(int r) { 10 | int i=r+al,j=bl,l=0; 11 | while(i>r) { 12 | char dir=pred[i][j]; 13 | if(dir==LU) l++; 14 | i+=mov[dir][0]; 15 | j+=mov[dir][1]; 16 | } 17 | return l; 18 | } 19 | inline void reroot(int r) { // r = new base row 20 | int i=r,j=1; 21 | while(j<=bl&&pred[i][j]!=LU) j++; 22 | if(j>bl) return; 23 | pred[i][j]=L; 24 | while(i<2*al&&j<=bl) { 25 | if(pred[i+1][j]==U) { 26 | i++; 27 | pred[i][j]=L; 28 | } else if(jbl) { 41 | swap(al,bl); 42 | strcpy(tmp,a); 43 | strcpy(a,b); 44 | strcpy(b,tmp); 45 | } 46 | strcpy(tmp,a); 47 | strcat(a,tmp); 48 | // basic lcs 49 | for(int i=0;i<=2*al;i++) { 50 | dp[i][0]=0; 51 | pred[i][0]=U; 52 | } 53 | for(int j=0;j<=bl;j++) { 54 | dp[0][j]=0; 55 | pred[0][j]=L; 56 | } 57 | for(int i=1;i<=2*al;i++) { 58 | for(int j=1;j<=bl;j++) { 59 | if(a[i-1]==b[j-1]) dp[i][j]=dp[i-1][j-1]+1; 60 | else dp[i][j]=max(dp[i-1][j],dp[i][j-1]); 61 | if(dp[i][j-1]==dp[i][j]) pred[i][j]=L; 62 | else if(a[i-1]==b[j-1]) pred[i][j]=LU; 63 | else pred[i][j]=U; 64 | } } 65 | // do cyclic lcs 66 | int clcs=0; 67 | for(int i=0;i s[b+k]) {a = b; break;} 8 | } return a; 9 | } -------------------------------------------------------------------------------- /string/sa.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define N 100010 4 | char T[ N ]; 5 | int n , RA[ N ], tempRA[ N ] , SA[ N ], tempSA[ N ] , c[ N ]; 6 | void countingSort( int k ){ 7 | int i , sum , maxi = max( 300 , n ) ; 8 | memset( c , 0 , sizeof c ) ; 9 | for ( i = 0 ; i < n ; i ++ ) c[ ( i + k < n ) ? RA[i + k] : 0 ] ++ ; 10 | for ( i = sum = 0 ; i < maxi ; i ++ ) { int t = c[i] ; c[i] = sum ; sum += t ; } 11 | for ( i = 0 ; i < n ; i ++ ) 12 | tempSA[ c[ ( SA[ i ] + k < n ) ? RA[ SA[ i ] + k ] : 0 ] ++ ] = SA[ i ] ; 13 | for ( i = 0 ; i < n ; i ++ ) SA[ i ] = tempSA[ i ] ; 14 | } 15 | void constructSA(){ 16 | int r; 17 | for ( int i = 0 ; i < n ; i ++ ) RA[ i ] = T[ i ] - '.' ; 18 | for ( int i = 0 ; i < n ; i ++ ) SA[ i ] = i ; 19 | for ( int k = 1 ; k < n ; k <<= 1 ) { 20 | countingSort( k ) ; countingSort( 0 ) ; 21 | tempRA[ SA[ 0 ] ] = r = 0; 22 | for ( int i = 1 ; i < n ; i ++ ) 23 | tempRA[ SA[ i ] ] = ( RA[ SA[ i ] ] == RA[ SA[ i - 1 ] ] && RA[ SA[ i ] + k ] == RA[ SA[ i - 1 ] + k ] ) ? r : ++ r ; 24 | for ( int i = 0 ; i < n ; i ++ ) RA[ i ] = tempRA[ i ] ; 25 | } 26 | } 27 | int main() { 28 | n = (int)strlen( gets( T ) ) ; 29 | T[ n ++ ] = '.' ; // important bug fix! 30 | constructSA() ; 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /string/smallest_rotation.cpp: -------------------------------------------------------------------------------- 1 | string mcp(string s){ 2 | int n = s.length(); 3 | s += s; 4 | int i=0, j=1; 5 | while (iright) { 10 | right=i+z[i]; 11 | left=i; 12 | } } } 13 | -------------------------------------------------------------------------------- /string/zvalue_palindrome.cpp: -------------------------------------------------------------------------------- 1 | void z_value_pal(char *s,int len,int *z){ 2 | len=(len<<1)+1; 3 | for(int i=len-1;i>=0;i--) 4 | s[i]=i&1?s[i>>1]:'@'; 5 | z[0]=1; 6 | for(int i=1,l=0,r=0;i=0&&i+z[i]r) l=i,r=i+z[i]; 10 | } } --------------------------------------------------------------------------------