├── .gitattributes ├── Algorithms ├── Centroid Decomposition ├── Convex Hull ├── Dijkstra O(Elog V) ├── Dijkstra O(V^2) ├── FFT ├── LCA ├── LCA (RMQ) ├── Lowlink ├── NTT └── Rabin-Karp ├── C++ Template ├── Data Structures ├── 2D DSU ├── 2D RMQ ├── 2D Sum Segment Tree ├── BIT ├── BIT of Sparse Sumtrees ├── Bitset Trie ├── Circle ├── DSU ├── Fraction ├── Lazy Max Segment Tree ├── Lazy Min Segment Tree ├── Lazy Sparse Segtree ├── Lazy Sum Segment Tree ├── Matrix ├── Max Queue ├── Max Segment Tree ├── Merge Sort Tree ├── Min Segment Tree ├── Modular ├── Node (to be used with the segment trees) ├── RMQ ├── Ranged BIT ├── STL.md ├── Segtree ├── Sparse Segtree ├── Square Root Decomposition ├── Suffix Array ├── Sum Segment Tree ├── Treap └── Trie ├── Debugging Tips ├── README.md ├── Solution Ideas ├── Template for Non-XCode ├── USACO ├── Contests │ ├── 2012-2013 │ │ ├── December │ │ │ └── Gold │ │ │ │ ├── first.cpp │ │ │ │ └── runaway.cpp │ │ └── January │ │ │ └── Gold │ │ │ └── lineup.cpp │ ├── 2013-2014 │ │ ├── December │ │ │ └── Gold │ │ │ │ └── optmilk.cpp │ │ ├── February │ │ │ └── Gold │ │ │ │ ├── dec.cpp │ │ │ │ └── rblock.cpp │ │ ├── January │ │ │ └── Gold │ │ │ │ ├── curling.cpp │ │ │ │ ├── skicourse.cpp │ │ │ │ └── skilevel.cpp │ │ ├── March │ │ │ └── Gold │ │ │ │ ├── fcount.cpp │ │ │ │ ├── lazy.cpp │ │ │ │ └── sabotage.cpp │ │ └── November │ │ │ └── Gold │ │ │ ├── empty.cpp │ │ │ ├── nochange.cpp │ │ │ └── nochange_mock.cpp │ ├── 2014-2015 │ │ ├── December │ │ │ └── Gold │ │ │ │ ├── cowjog.cpp │ │ │ │ ├── guard.cpp │ │ │ │ └── marathon.cpp │ │ ├── February │ │ │ └── Gold │ │ │ │ └── hopscotch.cpp │ │ ├── January │ │ │ └── Gold │ │ │ │ ├── cowrect.cpp │ │ │ │ ├── grass.cpp │ │ │ │ └── movie.cpp │ │ └── US Open │ │ │ └── Gold │ │ │ └── palpath.cpp │ ├── 2015-2016 │ │ ├── December │ │ │ ├── Gold │ │ │ │ ├── cardgame.cpp │ │ │ │ ├── dream.cpp │ │ │ │ ├── dream_bfs.cpp │ │ │ │ └── feast.cpp │ │ │ └── Platinum │ │ │ │ ├── cardgame.cpp │ │ │ │ ├── haybales.cpp │ │ │ │ └── maxflow.cpp │ │ ├── February │ │ │ ├── Gold │ │ │ │ ├── cbarn.cpp │ │ │ │ ├── cbarn2.cpp │ │ │ │ └── fencedin.cpp │ │ │ └── Platinum │ │ │ │ ├── balancing.cpp │ │ │ │ ├── cbarn_plat.cpp │ │ │ │ └── fencedin.cpp │ │ ├── January │ │ │ ├── Gold │ │ │ │ ├── angry.cpp │ │ │ │ ├── lightsout.cpp │ │ │ │ └── radio.cpp │ │ │ └── Platinum │ │ │ │ ├── fortmoo.cpp │ │ │ │ └── mowing.cpp │ │ └── US Open │ │ │ ├── Gold │ │ │ ├── 248.cpp │ │ │ ├── closing.cpp │ │ │ └── split.cpp │ │ │ └── Platinum │ │ │ └── 262144.cpp │ ├── 2016-2017 │ │ ├── December │ │ │ ├── Gold │ │ │ │ ├── checklist.cpp │ │ │ │ ├── lasers.cpp │ │ │ │ └── moocast.cpp │ │ │ └── Platinum │ │ │ │ ├── roboherd.cpp │ │ │ │ ├── team.cpp │ │ │ │ └── triangles.cpp │ │ ├── February │ │ │ ├── Gold │ │ │ │ ├── circlecross.cpp │ │ │ │ ├── nocross.cpp │ │ │ │ └── visitfj.cpp │ │ │ └── Platinum │ │ │ │ ├── friendcross.cpp │ │ │ │ ├── mincross.cpp │ │ │ │ └── nocross.cpp │ │ ├── January │ │ │ ├── Gold │ │ │ │ ├── bphoto.cpp │ │ │ │ ├── cownav.cpp │ │ │ │ └── hps.cpp │ │ │ └── Platinum │ │ │ │ ├── promote.cpp │ │ │ │ ├── subrev.cpp │ │ │ │ └── tallbarn.cpp │ │ └── US Open │ │ │ ├── Gold │ │ │ ├── art2.cpp │ │ │ └── cownomics.cpp │ │ │ └── Platinum │ │ │ ├── art.cpp │ │ │ ├── cowbasic.cpp │ │ │ └── grass.cpp │ ├── 2017-2018 │ │ ├── December │ │ │ ├── Gold │ │ │ │ ├── barnpainting.cpp │ │ │ │ └── hayfeast.cpp │ │ │ └── Platinum │ │ │ │ ├── greedy.cpp │ │ │ │ ├── pushabox.cpp │ │ │ │ └── standingout.cpp │ │ ├── February │ │ │ └── Platinum │ │ │ │ ├── gymnasts.cpp │ │ │ │ ├── newbarn.cpp │ │ │ │ └── slingshot.cpp │ │ └── January │ │ │ ├── Gold │ │ │ └── atlarge.cpp │ │ │ └── Platinum │ │ │ ├── atlarge_plat.cpp │ │ │ ├── lifeguards.cpp │ │ │ └── sprinklers.cpp │ └── 2018-2019 │ │ └── December │ │ └── Platinum │ │ ├── balance.cpp │ │ ├── gathering.cpp │ │ └── itout.cpp └── Training │ ├── 2.4 │ ├── cowtour.cpp │ ├── fracdec.cpp │ ├── maze1.cpp │ └── ttwo.cpp │ ├── 3.1 │ ├── agrinet.cpp │ ├── contact.cpp │ ├── humble.cpp │ ├── inflate.cpp │ └── stamps.cpp │ ├── 3.2 │ ├── butter.cpp │ ├── fact4.cpp │ ├── msquare.cpp │ ├── ratios.cpp │ ├── spin.cpp │ └── stringsobits.cpp │ ├── 3.3 │ ├── camelot.cpp │ ├── fence.cpp │ ├── game1.cpp │ ├── range.cpp │ └── shopping.cpp │ ├── 3.4 │ ├── fence9.cpp │ ├── heritage.cpp │ └── rockers.cpp │ └── 4.1 │ └── nuggets.cpp └── referencepdf ├── Makefile ├── build ├── kactl.aux ├── kactl.log ├── kactl.out ├── kactl.pdf ├── kactl.ptc └── kactl.toc ├── content ├── combinatorial (11.2) │ ├── IntPerm.h │ ├── MatroidIntersect.h │ ├── PermGroup.h │ ├── README.md │ └── chapter.tex ├── contest │ ├── .bashrc │ ├── .vimrc │ ├── CppIO.h │ ├── FastScanner.java │ ├── README.md │ ├── chapter.tex │ ├── cppreference.txt │ ├── hash.sh │ ├── kactlTemplate.cpp │ ├── stress.sh │ ├── template.cpp │ ├── templateShort.cpp │ ├── troubleshoot.tex │ └── troubleshoot.txt ├── data-structures │ ├── 1D Range Queries (9.2) │ │ ├── BIT (9.2).h │ │ ├── BITrange.h │ │ ├── Lazy SegTree (15.2).h │ │ ├── MaxQueue.h │ │ ├── Mo (15.1).h │ │ ├── Node.h │ │ ├── PersSegTree (15.2).h │ │ ├── Rectangle Union (15.2).h │ │ ├── SegTree (9.2).h │ │ ├── SegTreeBeats.h │ │ ├── Sparse SegTree (9.2).h │ │ ├── SqrtDecomp.h │ │ ├── Treap (15.3).h │ │ └── Wavelet Tree.h │ ├── 2D Range Queries (15.2) │ │ ├── 2D Offline BIT (15.2).h │ │ ├── 2D SegBIT (15.2).h │ │ ├── 2D SegTree (15.2).h │ │ ├── 2D Sumtree.h │ │ └── Merge-Sort Tree (15.2).h │ ├── BBST.md │ ├── LichaoSegTree.h │ ├── LineContainer.h │ ├── LineContainerDeque.h │ ├── Range Queries.md │ ├── STL (5) │ │ ├── CustomHash.h │ │ ├── MapComparator (5.2).h │ │ ├── OrderStatisticTree.h │ │ └── Rope.h │ ├── STL.md │ ├── Static Range Queries (9.1) │ │ ├── Prefix Sums (9.1).h │ │ ├── RMQ (9.1).h │ │ └── Static Range Queries (9.1).h │ └── chapter.tex ├── geometry (13) │ ├── 3D │ │ ├── Hull3D.h │ │ └── Point3D.h │ ├── Circles │ │ ├── Circles.h │ │ ├── Circumcenter.h │ │ └── MinEnclosingCircle.h │ ├── Misc │ │ ├── ClosestPair (13.2).h │ │ ├── DelaunayFast.h │ │ ├── DelaunaySlow.h │ │ └── MaxCollinear.h │ ├── Polygons │ │ ├── Area.h │ │ ├── ConvexHull (13.2).h │ │ ├── InPoly.h │ │ └── PolyDiameter.h │ ├── Primitives │ │ ├── AngleCmp.h │ │ ├── HowardGeo.h │ │ ├── LineDist.h │ │ ├── LineIntersect.h │ │ ├── Point.h │ │ ├── SegDist.h │ │ └── SegIntersect.h │ ├── README.md │ └── chapter.tex ├── graphs (12) │ ├── DFS │ │ ├── 2SAT (12.1).h │ │ ├── BCC (12.4).h │ │ ├── EulerPath (12.2).h │ │ ├── SCC (12.1).h │ │ └── TopoSort.h │ ├── Flows (12.3) │ │ ├── Dinic.h │ │ ├── Flows.md │ │ ├── GomoryHu.h │ │ ├── HLPP.h │ │ └── MCMF.h │ ├── Fundamentals │ │ ├── DSU (7.6).h │ │ ├── DSUrb (15.5).h │ │ ├── Dijkstra.h │ │ ├── DijkstraV2.h │ │ ├── DynaCon.h │ │ ├── FloydWarshall.h │ │ ├── MST (7.6).h │ │ └── ManhattanMST.h │ ├── Matching │ │ ├── DFSmatch.h │ │ ├── Hungarian.h │ │ └── UnweightedMatch.h │ ├── Misc │ │ ├── DirectedMST.h │ │ ├── DirectedMstKACTL.h │ │ ├── DominatorTree.h │ │ ├── EdgeColor.h │ │ ├── LCT.h │ │ └── MaximalCliques.h │ ├── README.md │ ├── Trees (10) │ │ ├── CentroidDecomp (10.3).h │ │ ├── HLD (10.3).h │ │ ├── LCAjumps (10.2).h │ │ ├── LCArmq (10.2).h │ │ ├── README.md │ │ ├── SmallToLarge (10.2).h │ │ └── TreeDiameter (10.1).h │ └── chapter.tex ├── math │ ├── chapter.tex │ └── sphericalCoordinates.pdf ├── number-theory (11.1) │ ├── DiscreteLog.h │ ├── Divisibility │ │ ├── CRT.h │ │ └── Euclid.h │ ├── Modular Arithmetic │ │ ├── ModFact.h │ │ ├── ModMulLL.h │ │ ├── ModSqrt.h │ │ ├── ModSum Explanation.tex │ │ ├── ModSum.h │ │ ├── Modular.h │ │ └── Order.h │ ├── Primality │ │ ├── FactorBasic.h │ │ ├── FactorFast.h │ │ ├── PrimeSieve.h │ │ └── PrimeSieveLinear.h │ ├── README.md │ └── chapter.tex ├── numerical │ ├── Arithmetic │ │ ├── BigInt.h │ │ ├── ExprParse.h │ │ └── Fraction.h │ ├── Matrix (11.3) │ │ ├── Matrix.h │ │ ├── MatrixInv.h │ │ └── MatrixTree.h │ ├── Misc │ │ ├── Integrate.h │ │ ├── IntegrateAdaptive.h │ │ ├── LinRec.h │ │ └── Simplex.h │ ├── Polynomials │ │ ├── FFT.h │ │ ├── FFTmod.h │ │ ├── Karatsuba.h │ │ ├── PolyConv.h │ │ ├── PolyDiv.h │ │ ├── PolyInv.h │ │ ├── PolyRoots.h │ │ ├── PolySqrt.h │ │ └── VecOp.h │ ├── README.md │ └── chapter.tex ├── strings (14) │ ├── Lightweight │ │ ├── Bitset Trie (14.1).h │ │ ├── KMP.h │ │ ├── LyndonFactorization.h │ │ ├── Manacher.h │ │ ├── MinRotation.h │ │ ├── RabinKarp.h │ │ ├── Trie.h │ │ └── Z (14.3).h │ ├── Misc │ │ ├── Hashing (14.2).h │ │ └── TandemRepeats.h │ ├── README.md │ ├── Suffix Structures │ │ ├── ACfixed.h │ │ ├── ACunfixed.h │ │ ├── PalTree.h │ │ ├── ReverseBW (14.4).h │ │ ├── SuffixArray (14.4).h │ │ ├── SuffixAutomaton.h │ │ ├── SuffixTree.h │ │ └── SuffixTree_KACTL.h │ └── chapter.tex └── tex │ ├── cmu.png │ ├── kactl.tex │ ├── kactlpkg.sty │ ├── preprocessor.py │ └── texput.log ├── header.tmp └── kactl.pdf /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /Algorithms/Centroid Decomposition: -------------------------------------------------------------------------------- 1 | template struct centroidDecomp { 2 | vi neighbor[SZ]; 3 | int subsize[SZ]; 4 | bool vis[SZ]; 5 | int p[SZ]; 6 | int par[SZ]; 7 | vi child[SZ]; 8 | int numNodes; 9 | 10 | centroidDecomp(int num) { 11 | this->numNodes = num; 12 | } 13 | void addEdge(int u, int v) { 14 | neighbor[u].PB(v); 15 | neighbor[v].PB(u); 16 | } 17 | void build() { 18 | M00(i, numNodes) vis[i] = 0, par[i] = -1; 19 | solve(0); 20 | M00(i, numNodes) if(par[i] != -1) child[par[i]].PB(i); 21 | } 22 | void getSizes(int node) { 23 | subsize[node] = 1; 24 | for(int ch: neighbor[node]) if(!vis[ch] && ch != p[node]) { 25 | p[ch] = node; 26 | getSizes(ch); 27 | subsize[node] += subsize[ch]; 28 | } 29 | } 30 | int getCentroid(int root) { 31 | p[root] = -1; 32 | getSizes(root); 33 | int cur = root; 34 | while(1) { 35 | pi hi = MP(subsize[root]-subsize[cur], cur); 36 | for(int v: neighbor[cur]) if(!vis[v] && v != p[cur]) hi = max(hi, MP(subsize[v], v)); 37 | if(hi.F <= subsize[root]/2) return cur; 38 | cur = hi.S; 39 | } 40 | } 41 | int solve(int node) { 42 | node = getCentroid(node); 43 | vis[node] = 1; 44 | for(int ch: neighbor[node]) if(!vis[ch]) par[solve(ch)] = node; 45 | return node; 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /Algorithms/Convex Hull: -------------------------------------------------------------------------------- 1 | struct convexHull { 2 | set> dupChecker; 3 | vector> points; 4 | vector> dn, up, hull; 5 | 6 | convexHull() {} 7 | bool cw(pd o, pd a, pd b) { 8 | return ((a.f-o.f)*(b.s-o.s)-(a.s-o.s)*(b.f-o.f) <= 0); 9 | } 10 | void addPoint(pair p) { 11 | if(dupChecker.count(p)) return; 12 | points.pb(p); 13 | dupChecker.insert(p); 14 | } 15 | void addPoint(ld x, ld y) { 16 | addPoint(mp(x,y)); 17 | } 18 | void build() { 19 | sort(points.begin(), points.end()); 20 | if(sz(points) < 3) { 21 | for(pair p: points) { 22 | dn.pb(p); 23 | hull.pb(p); 24 | } 25 | M00d(i, sz(points)) { 26 | up.pb(points[i]); 27 | } 28 | } else { 29 | for(int i = 0; i < (int)points.size(); i++) { 30 | while(dn.size() >= 2 && cw(dn[dn.size()-2], dn[dn.size()-1], points[i])) { 31 | dn.erase(dn.end()-1); 32 | } 33 | dn.push_back(points[i]); 34 | } 35 | for(int i = (int)points.size()-1; i >= 0; i--) { 36 | while(up.size() >= 2 && cw(up[up.size()-2], up[up.size()-1], points[i])) { 37 | up.erase(up.end()-1); 38 | } 39 | up.push_back(points[i]); 40 | } 41 | sort(dn.begin(), dn.end()); 42 | sort(up.begin(), up.end()); 43 | 44 | for(int i = 0; i < up.size()-1; i++) hull.pb(up[i]); 45 | for(int i = sz(dn)-1; i > 0; i--) hull.pb(dn[i]); 46 | } 47 | } 48 | }; 49 | -------------------------------------------------------------------------------- /Algorithms/Dijkstra O(Elog V): -------------------------------------------------------------------------------- 1 | template struct dijkstra { 2 | const int inf = 1e8; 3 | vector adj[SZ]; 4 | bool vis[SZ]; 5 | int d[SZ]; 6 | 7 | void addEdge(int u, int v, int l) { 8 | adj[u].pb(mp(v, l)); 9 | } 10 | int dist(int v) { 11 | return d[v]; 12 | } 13 | void build(int u) { 14 | priority_queue, greater> pq; 15 | M00(i, SZ) d[i] = inf; 16 | d[u] = 0; 17 | pq.push(mp(0, u)); 18 | while(!pq.empty()) { 19 | pi t = pq.top(); pq.pop(); 20 | if(vis[t.s]) continue; 21 | vis[t.s] = 1; 22 | 23 | for(auto v: adj[t.s]) { 24 | if(d[v.f] > d[t.s] + v.s) { 25 | d[v.f] = d[t.s] + v.s; 26 | pq.push(mp(d[t.s]+v.s, v.f)); 27 | } 28 | } 29 | } 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /Algorithms/Dijkstra O(V^2): -------------------------------------------------------------------------------- 1 | template struct dijkstra { 2 | vector> adj[SZ]; 3 | bool vis[SZ]; 4 | ll d[SZ]; 5 | 6 | void addEdge(int u, int v, ll l) { 7 | adj[u].pb(mp(v, l)); 8 | } 9 | ll dist(int v) { 10 | return d[v]; 11 | } 12 | void build(int u) { 13 | M00(i, SZ) vis[i] = 0; 14 | M00(i, SZ) d[i] = 1e17; 15 | d[u] = 0; 16 | while(1) { 17 | pair t = mp(1e17, -1); 18 | M00(i, SZ) if(!vis[i]) ckmin(t, mp(d[i], i)); 19 | if(t.s == -1 || vis[t.s]) return; 20 | vis[t.s] = 1; 21 | 22 | for(auto& v: adj[t.s]) if(!vis[v.f]) { 23 | ckmin(d[v.f], d[t.s] + v.s); 24 | } 25 | } 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /Algorithms/LCA: -------------------------------------------------------------------------------- 1 | template struct tree { 2 | vector> adj[SZ]; 3 | const static int LGSZ = 32-__builtin_clz(SZ-1); 4 | pair ppar[SZ][LGSZ]; 5 | int depth[SZ]; 6 | ll distfromroot[SZ]; 7 | 8 | void addEdge(int u, int v, int d) { 9 | adj[u].pb(mp(v, d)); 10 | adj[v].pb(mp(u, d)); 11 | } 12 | void dfs(int u, int dep, ll dis) { 13 | depth[u] = dep; 14 | distfromroot[u] = dis; 15 | for(auto& v: adj[u]) if(ppar[u][0].f != v.f) { 16 | ppar[v.f][0] = mp(u, v.s); 17 | dfs(v.f, dep + 1, dis + v.s); 18 | } 19 | } 20 | void build() { 21 | ppar[0][0] = mp(0, 0); 22 | M00(i, SZ) depth[i] = 0; 23 | dfs(0, 0, 0); 24 | MOO(i, 1, LGSZ) M00(j, SZ) { 25 | ppar[j][i].f = ppar[ppar[j][i-1].f][i-1].f; 26 | ppar[j][i].s = ppar[j][i-1].s + ppar[ppar[j][i-1].f][i-1].s; 27 | } 28 | } 29 | int lca(int u, int v) { 30 | if(depth[u] < depth[v]) swap(u, v); 31 | M00d(i, LGSZ) if(depth[ppar[u][i].f] >= depth[v]) u = ppar[u][i].f; 32 | if(u == v) return u; 33 | M00d(i, LGSZ) { 34 | if(ppar[u][i].f != ppar[v][i].f) { 35 | u = ppar[u][i].f; 36 | v = ppar[v][i].f; 37 | } 38 | } 39 | return ppar[u][0].f; 40 | } 41 | ll dist(int u, int v) { 42 | return distfromroot[u] + distfromroot[v] - 2*distfromroot[lca(u, v)]; 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /Algorithms/Lowlink: -------------------------------------------------------------------------------- 1 | template struct cutNodes { 2 | vi adj[SZ]; 3 | int depth[SZ]; 4 | int highest[SZ]; 5 | unordered_set art; 6 | void build() { 7 | M00(i, SZ) depth[i] = -1; 8 | M00(i, SZ) if(depth[i] == -1) dfs(i, i, 0); 9 | } 10 | void addEdge(int u, int v) { 11 | adj[u].PB(v); 12 | adj[v].PB(u); 13 | } 14 | bool dfs(int u, int p, int d) { 15 | if(depth[u] != -1) { 16 | highest[p] = min(highest[p], depth[u]); 17 | return 0; 18 | } 19 | bool hasMult = 0; 20 | depth[u] = d; 21 | highest[u] = depth[u]; 22 | for(int v: adj[u]) if(v != p && dfs(v, u, d+1)) { 23 | highest[u] = min(highest[u], highest[v]); 24 | if(u == p) { 25 | if(hasMult) art.insert(u); 26 | } else if(highest[v] >= depth[u]) art.insert(u); 27 | hasMult = 1; 28 | } 29 | return 1; 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /Algorithms/Rabin-Karp: -------------------------------------------------------------------------------- 1 | template struct rabinKarp { 2 | const ll mods[3] = {1000000007, 999119999, 1000992299}; 3 | ll p[3][SZ]; 4 | ll h[3][SZ]; 5 | const ll base = 1000696969; 6 | rabinKarp() {} 7 | void build(string a) { 8 | M00(i, 3) { 9 | p[i][0] = 1; 10 | h[i][0] = (int)a[0]; 11 | MOO(j, 1, (int)a.length()) { 12 | p[i][j] = (p[i][j-1] * mods[i]) % base; 13 | h[i][j] = (h[i][j-1] * mods[i] + (int)a[j]) % base; 14 | } 15 | } 16 | } 17 | tuple hsh(int a, int b) { 18 | if(a == 0) return make_tuple(h[0][b], h[1][b], h[2][b]); 19 | tuple ans; 20 | get<0>(ans) = (((h[0][b] - h[0][a-1]*p[0][b-a+1]) % base) + base) % base; 21 | get<1>(ans) = (((h[1][b] - h[1][a-1]*p[1][b-a+1]) % base) + base) % base; 22 | get<2>(ans) = (((h[2][b] - h[2][a-1]*p[2][b-a+1]) % base) + base) % base; 23 | return ans; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /C++ Template: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | #define f first 6 | #define s second 7 | #define pb push_back 8 | #define mp make_pair 9 | #define all(v) v.begin(), v.end() 10 | #define sz(v) (int)v.size() 11 | 12 | #define MOO(i, a, b) for(int i=a; i= a; i--) 15 | #define M00d(i,a) for(int i = (a)-1; i>=0; i--) 16 | 17 | #define FAST ios::sync_with_stdio(0); cin.tie(0); 18 | #define finish(x) return cout << x << '\n', 0; 19 | #define dbg(x) cerr << ">>> " << #x << " = " << x << "\n"; 20 | #define _ << " _ " << 21 | 22 | typedef long long ll; 23 | typedef long double ld; 24 | typedef vector vi; 25 | typedef pair pi; 26 | typedef pair pd; 27 | typedef complex cd; 28 | 29 | int main() { FAST 30 | 31 | } 32 | -------------------------------------------------------------------------------- /Data Structures/2D DSU: -------------------------------------------------------------------------------- 1 | template struct DSU { 2 | pair e[w][h]; 3 | DSU() { 4 | M00(i, w) M00(j, h) { 5 | e[i][j] = MP(1, MP(i, j)); 6 | } 7 | } 8 | void clear() { 9 | M00(i, w) M00(j, h) { 10 | e[i][j] = MP(1, MP(i, j)); 11 | } 12 | } 13 | pi get(pi x) { 14 | int i = x.F; 15 | int j = x.S; 16 | if(e[i][j].S != MP(i, j)) { 17 | e[i][j].S = get(e[i][j].S); 18 | } 19 | return e[i][j].S; 20 | } 21 | void unite(pi x, pi y) { 22 | x = get(x); 23 | y = get(y); 24 | if(x == y) return; 25 | pair& xp = e[x.F][x.S]; 26 | pair& yp = e[y.F][y.S]; 27 | if(xp.F < yp.F) swap(xp, yp), swap(x, y); 28 | xp.F += yp.F, yp.S = x; 29 | } 30 | bool connected(pi x, pi y) { 31 | x = get(x); 32 | y = get(y); 33 | return (x == y); 34 | } 35 | int s(pi x) { //size of component containing x 36 | x = get(x); 37 | return e[x.F][x.S].F; 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /Data Structures/2D RMQ: -------------------------------------------------------------------------------- 1 | template struct RMQ { 2 | const static int LGSZ = 33-__builtin_clz(SZ-1); 3 | int rmq[SZ][LGSZ]; 4 | void upd(int idx, int val) { 5 | rmq[idx][0] = val; 6 | } 7 | void build(int n) { 8 | int lgn = 33 - __builtin_clz(n-1); 9 | MOO(i, 1, lgn) { 10 | M00(j, n) if(j+(1< struct RMQ2D { 24 | const static int LGW = 33-__builtin_clz(W-1); 25 | RMQ rmq2d[W][LGW]; 26 | void upd(int i, int j, int val) { 27 | rmq2d[i][0].upd(j, val); 28 | } 29 | void build(int n, int m) { 30 | M00(i, n) rmq2d[i][0].build(m); 31 | int lgn = 33 - __builtin_clz(n-1); 32 | int lgm = 33 - __builtin_clz(m-1); 33 | MOO(i, 1, lgn) { 34 | M00(j, n) if(j+(1< struct BIT { 2 | T b[sz+1]; 3 | BIT() { 4 | M00(i, sz+1) b[i] = 0; 5 | } 6 | void add(int k, T val) { 7 | k++; 8 | for(; k <= sz; k+=(k&-k)) b[k] += val; 9 | } 10 | T psum(int ind) { 11 | T ans = 0; 12 | ind++; 13 | for(; ind>0; ind-=(ind&-ind)) ans+=b[ind]; 14 | return ans; 15 | } 16 | T sum(int l, int r) { 17 | return psum(r) - psum(l-1); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /Data Structures/BIT of Sparse Sumtrees: -------------------------------------------------------------------------------- 1 | struct st{ 2 | node* root; 3 | st(int SZ) { 4 | int ub = 1; 5 | while(ub < SZ) ub *= 2; 6 | root = new node(0, ub-1); 7 | } 8 | void addN(node* n, int pos, int val) { 9 | if(pos < n->l || pos > n->r) return; 10 | n->val += val; 11 | if(n->l == n->r) { 12 | return; 13 | } 14 | 15 | int mid = (n->l + n->r)/2; 16 | if(pos > mid) { 17 | if(n->right == nullptr) n->right = new node(mid+1, n->r); 18 | addN(n->right, pos, val); 19 | } 20 | else { 21 | if(n->left == nullptr) n->left = new node(n->l, mid); 22 | addN(n->left, pos, val); 23 | } 24 | } 25 | void add(int pos, int val) { 26 | addN(root, pos, val); 27 | } 28 | int queryN(node* n, int i1, int i2) { 29 | if(i2 < n->l || i1 > n->r) return 0; 30 | if(n->l == n->r) return n->val; 31 | if(n->l >= i1 && n->r <= i2) return n->val; 32 | 33 | int ans = 0; 34 | if(n->left != nullptr) ans += queryN(n->left, i1, i2); 35 | if(n->right != nullptr) ans += queryN(n->right, i1, i2); 36 | 37 | return ans; 38 | } 39 | int query(int i1, int i2) { 40 | return queryN(root, i1, i2); 41 | } 42 | }; 43 | 44 | template struct segbit { 45 | st* b[w+1]; 46 | segbit() { 47 | M00(i, w+1) b[i] = new st(l); 48 | } 49 | void add(int x, int y, int val) { 50 | x++; 51 | for(; x <= w; x+=(x&-x)) b[x]->add(y, val); 52 | } 53 | int psum(int x, int y1, int y2) { 54 | int ret = 0; 55 | x++; 56 | for(; x>0; x-=(x&-x)) ret+=b[x]->query(y1, y2); 57 | return ret; 58 | } 59 | int sum(int x1, int y1, int x2, int y2) { 60 | return psum(x2, y1, y2) - psum(x1-1, y1, y2); 61 | } 62 | }; 63 | -------------------------------------------------------------------------------- /Data Structures/Bitset Trie: -------------------------------------------------------------------------------- 1 | template struct bitTrie { 2 | int trie[SZ][2]; 3 | int cursz; 4 | bitTrie() { 5 | M00(i, SZ) M00(j, 2) trie[i][j] = -1; 6 | cursz = 1; 7 | } 8 | void insert(int k) { 9 | int cur = 0; 10 | M00d(i, 32) { 11 | int b = k&(1< operator & (const Circle &c1,const Circle &c2) 49 | { 50 | ld d=(c1.o-c2.o).len(); 51 | if(d>c1.r+c2.r+eps || d(); 53 | ld dt=(c1.r*c1.r-c2.r*c2.r)/d,d1=(d+dt)/2; 54 | Point dir=(c2.o-c1.o)/d,pcrs=c1.o+dir*d1; 55 | dt=sqrt(max(0.0L,c1.r*c1.r-d1*d1)),dir=dir.rot90(); 56 | return vector{pcrs+dir*dt,pcrs-dir*dt}; 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /Data Structures/DSU: -------------------------------------------------------------------------------- 1 | template struct DSU { 2 | int par[SZ]; 3 | int size[SZ]; 4 | DSU() { 5 | M00(i, SZ) par[i] = i, size[i] = 1; 6 | } 7 | int get(int node) { 8 | if(par[node] != node) par[node] = get(par[node]); 9 | return par[node]; 10 | } 11 | bool connected(int n1, int n2) { 12 | return (get(n1) == get(n2)); 13 | } 14 | int sz(int node) { 15 | return size[get(node)]; 16 | } 17 | void unite(int n1, int n2) { 18 | n1 = get(n1); 19 | n2 = get(n2); 20 | if(n1 == n2) return; 21 | if(rand()%2) { 22 | par[n1] = n2; 23 | size[n2] += size[n1]; 24 | } else { 25 | par[n2] = n1; 26 | size[n1] += size[n2]; 27 | } 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /Data Structures/Lazy Sum Segment Tree: -------------------------------------------------------------------------------- 1 | template struct lazysumtree { 2 | node* root; 3 | lazysumtree() { 4 | int ub = 1; 5 | while(ub < SZ) ub *= 2; 6 | root = new node(0, ub-1); 7 | } 8 | void propagate(node* n) { 9 | if(n->l != n->r) { 10 | int mid = ((n->l) + (n->r))/2; 11 | if(n->left == nullptr) n->left = new node(n->l, mid); 12 | if(n->right == nullptr) n->right = new node(mid+1, n->r); 13 | } 14 | if(n->lazy != 0) { 15 | n->val += ((n->r) - (n->l) + 1) * n->lazy; 16 | if(n->l != n->r) { 17 | n->left->lazy += n->lazy; 18 | n->right->lazy += n->lazy; 19 | } 20 | n->lazy = 0; 21 | } 22 | } 23 | void addN(node* n, int i1, int i2, int val) { 24 | propagate(n); 25 | if(i2 < n->l || i1 > n->r) return; 26 | if(n->l == n->r) { 27 | n->val += val; 28 | return; 29 | } 30 | if(i1 <= n->l && i2 >= n->r) { 31 | n->val += ((n->r) - (n->l) + 1)*val; 32 | n->left->lazy += val; 33 | n->right->lazy += val; 34 | return; 35 | } 36 | 37 | addN(n->left, i1, i2, val); 38 | addN(n->right, i1, i2, val); 39 | n->val = n->left->val + n->right->val; 40 | } 41 | void add(int i1, int i2, int val) { 42 | addN(root, i1, i2, val); 43 | } 44 | int queryN(node* n, int i1, int i2) { 45 | propagate(n); 46 | if(i2 < n->l || i1 > n->r) return 0; 47 | if(n->l == n->r) { 48 | return n->val; 49 | } 50 | if(i1 <= n->l && i2 >= n->r) { 51 | return n->val; 52 | } 53 | 54 | return queryN(n->left, i1, i2) + queryN(n->right, i1, i2); 55 | } 56 | int query(int i1, int i2) { 57 | return queryN(root, i1, i2); 58 | } 59 | }; 60 | -------------------------------------------------------------------------------- /Data Structures/Matrix: -------------------------------------------------------------------------------- 1 | template struct matrix { //SZ should be max(N, M) 2 | int mat[SZ][SZ]; 3 | int N, M; 4 | matrix(int n, int m) { //identity 5 | this->N = n; this->M = m; 6 | M00(i, N) M00(j, M) { 7 | if(i == j) mat[i][j] = 1; 8 | else mat[i][j] = 0; 9 | } 10 | } 11 | matrix operator*(const matrix& other) { 12 | if(M != other.N) throw "Dimensions don't match up"; 13 | matrix ans = matrix(N, other.M); 14 | M00(i, N) M00(j, other.M) { 15 | ans.mat[i][j] = 0; 16 | M00(k, M) ans.mat[i][j] += mat[i][k] * other.mat[k][j]; 17 | } 18 | return ans; 19 | } 20 | matrix operator+(const matrix& other) { 21 | if(N != other.N || M != other.M) throw "Dimensions don't match up"; 22 | matrix ans = matrix(N, other.M); 23 | M00(i, N) M00(j, other.M) { 24 | ans.mat[i][j] = mat[i][j] + other.mat[i][j]; 25 | } 26 | return ans; 27 | } 28 | matrix operator^(int p) { 29 | if(N != M) throw "Not a square matrix"; 30 | matrix ans = matrix(N, N); 31 | matrix temp = matrix(N, M); 32 | M00(i, N) M00(j, M) temp.mat[i][j] = mat[i][j]; 33 | while(p > 0) { 34 | if(p % 2) ans = ans*temp; 35 | temp = temp*temp; 36 | p /= 2; 37 | } 38 | return ans; 39 | } 40 | void print() { 41 | M00(i, N) { 42 | M00(j, M) { 43 | if(j != 0) cout << " "; 44 | cout << mat[i][j]; 45 | } 46 | cout << "\n"; 47 | } 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /Data Structures/Max Queue: -------------------------------------------------------------------------------- 1 | struct maxQueue { 2 | queue q; 3 | deque dq; 4 | void push(int v) { 5 | q.push(v); 6 | if(q.empty()) {dq.push_back(v); return;} 7 | while(!dq.empty() && dq.back() < v) dq.pop_back(); 8 | dq.push_back(v); 9 | } 10 | void pop() { 11 | if(q.front() == dq.front()) dq.pop_front(); 12 | q.pop(); 13 | } 14 | int get() {return dq.front();} 15 | int size() {return (int)q.size();} 16 | }; 17 | -------------------------------------------------------------------------------- /Data Structures/Max Segment Tree: -------------------------------------------------------------------------------- 1 | template struct maxtree{ 2 | node* root; 3 | maxtree() { 4 | int ub = 1; 5 | while(ub < SZ) ub *= 2; 6 | root = new node(0, ub-1); 7 | root -> val = (-(1<<30)+1)-(1<<30); 8 | } 9 | void updN(node* n, int pos, int val) { 10 | if(pos < n->l || pos > n->r) return; 11 | if(n->l == n->r) { 12 | n->val = val; 13 | return; 14 | } 15 | 16 | int mid = (n->l + n->r)/2; 17 | if(pos > mid) { 18 | if(n->right == nullptr) n->right = new node(mid+1, n->r), n->right->val = (-(1<<30)+1)-(1<<30); 19 | updN(n->right, pos, val); 20 | } 21 | else { 22 | if(n->left == nullptr) n->left = new node(n->l, mid), n->left->val = (-(1<<30)+1)-(1<<30); 23 | updN(n->left, pos, val); 24 | } 25 | 26 | int s = (-(1<<30)+1)-(1<<30); 27 | if(n->left != nullptr) s = max(s, n->left->val); 28 | if(n->right != nullptr) s = max(s, n->right->val); 29 | 30 | n->val = s; 31 | } 32 | void upd(int pos, int val) { 33 | updN(root, pos, val); 34 | } 35 | int queryN(node* n, int i1, int i2) { 36 | if(i2 < n->l || i1 > n->r) return (-(1<<30)+1)-(1<<30); 37 | if(n->l == n->r) return n->val; 38 | if(n->l >= i1 && n->r <= i2) return n->val; 39 | 40 | int s = (-(1<<30)+1)-(1<<30); 41 | if(n->left != nullptr) s = max(s, queryN(n->left, i1, i2)); 42 | if(n->right != nullptr) s = max(s, queryN(n->right, i1, i2)); 43 | 44 | return s; 45 | } 46 | int query(int i1, int i2) { 47 | return queryN(root, i1, i2); 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /Data Structures/Merge Sort Tree: -------------------------------------------------------------------------------- 1 | template struct mstree { 2 | Tree val[SZ+1]; // for offline queries use vector instead 3 | 4 | void upd(int x, int y) { // x-coordinate between 1 and SZ inclusive 5 | x++; 6 | for (;x <= SZ; x += (x&-x)) val[x].insert(y); 7 | } 8 | 9 | int query(int x, int y) { 10 | x++; 11 | int t = 0; 12 | for (;x > 0; x -= (x&-x)) t += val[x].order_of_key(y+1); 13 | return t; 14 | } 15 | 16 | int query(int lox, int hix, int loy, int hiy) { // query number of elements within a rectangle 17 | return query(hix,hiy)-query(lox-1,hiy)-query(hix,loy-1)+query(lox-1,loy-1); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /Data Structures/Min Segment Tree: -------------------------------------------------------------------------------- 1 | template struct mintree{ 2 | node* root; 3 | mintree() { 4 | int ub = 1; 5 | while(ub < SZ) ub *= 2; 6 | root = new node(0, ub-1); 7 | root -> val = ((1<<30)-1)+(1<<30); 8 | } 9 | void updN(node* n, int pos, int val) { 10 | if(pos < n->l || pos > n->r) return; 11 | if(n->l == n->r) { 12 | n->val = val; 13 | return; 14 | } 15 | 16 | int mid = (n->l + n->r)/2; 17 | if(pos > mid) { 18 | if(n->right == nullptr) n->right = new node(mid+1, n->r), n->right->val = (1<<30)-1+(1<<30); 19 | updN(n->right, pos, val); 20 | } 21 | else { 22 | if(n->left == nullptr) n->left = new node(n->l, mid), n->left->val = (1<<30)-1+(1<<30); 23 | updN(n->left, pos, val); 24 | } 25 | 26 | int s = (1<<30)-1+(1<<30); 27 | if(n->left != nullptr) s = min(s, n->left->val); 28 | if(n->right != nullptr) s = min(s, n->right->val); 29 | 30 | n->val = s; 31 | } 32 | void upd(int pos, int val) { 33 | updN(root, pos, val); 34 | } 35 | int queryN(node* n, int i1, int i2) { 36 | if(i2 < n->l || i1 > n->r) return (1<<30)-1+(1<<30); 37 | if(n->l == n->r) return n->val; 38 | if(n->l >= i1 && n->r <= i2) return n->val; 39 | 40 | int s = (1<<30)-1+(1<<30); 41 | if(n->left != nullptr) s = min(s, queryN(n->left, i1, i2)); 42 | if(n->right != nullptr) s = min(s, queryN(n->right, i1, i2)); 43 | 44 | return s; 45 | } 46 | int query(int i1, int i2) { 47 | return queryN(root, i1, i2); 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /Data Structures/Node (to be used with the segment trees): -------------------------------------------------------------------------------- 1 | struct node { 2 | int val; 3 | int lazy; 4 | int l, r; 5 | node* left; 6 | node* right; 7 | node(int l, int r) { 8 | this -> val = 0; 9 | this -> lazy = 0; 10 | this -> l = l; 11 | this -> r = r; 12 | this -> left = nullptr; 13 | this -> right = nullptr; 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /Data Structures/RMQ: -------------------------------------------------------------------------------- 1 | template struct RMQ { 2 | const static int LGSZ = 33-__builtin_clz(SZ-1); 3 | int rmq[SZ][LGSZ]; 4 | void upd(int idx, int val) { 5 | rmq[idx][0] = val; 6 | } 7 | void build(int n) { 8 | int lgn = 33 - __builtin_clz(n-1); 9 | MOO(i, 1, lgn) { 10 | M00(j, n) if(j+(1< struct BIT { 2 | T b[sz+1]; 3 | BIT() { 4 | M00(i, sz+1) b[i] = 0; 5 | } 6 | void add(int k, T val) { 7 | k++; 8 | for(; k <= sz; k+=(k&-k)) b[k] += val; 9 | } 10 | T psum(int ind) { 11 | T ans = 0; 12 | ind++; 13 | for(; ind>0; ind-=(ind&-ind)) ans+=b[ind]; 14 | return ans; 15 | } 16 | T sum(int l, int r) { 17 | return psum(r) - psum(l-1); 18 | } 19 | }; 20 | 21 | template struct BITR { 22 | BIT b1; 23 | BIT b2; 24 | void add(int l, int r, T val) { 25 | b1.add(l, val); 26 | b2.add(l, val*(l-1)); 27 | if(r+1 < sz) { 28 | b1.add(r+1, -val); 29 | b2.add(r+1, -val*r); 30 | } 31 | } 32 | T psum(int ind) { 33 | return b1.psum(ind) * ind - b2.psum(ind); 34 | } 35 | T sum(int l, int r) { 36 | if(l == 0) return psum(r); 37 | return psum(r) - psum(l-1); 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /Data Structures/STL.md: -------------------------------------------------------------------------------- 1 | * priority_queue: push, pop, top, O(log n) 2 | * set: priority_queue but can delete, O(log n) 3 | * unordered_set: insert and erase elements, count and find, O(1) 4 | * map: key and value, can iterate through in increasing order, O(log n) 5 | * unordered_map: map but iteration does not give predictable order, O(1) 6 | -------------------------------------------------------------------------------- /Data Structures/Segtree: -------------------------------------------------------------------------------- 1 | template struct segtree { 2 | // modify these 3 | T identity = 0; 4 | T comb(T l, T r) { 5 | return l + r; 6 | } 7 | void updLeaf(T& l, T val) { 8 | l = val; 9 | } 10 | 11 | T tree[2*SZ+1]; 12 | segtree() { 13 | M00(i, 2*SZ+1) tree[i] = identity; 14 | } 15 | void upd(int pos, T val) { 16 | pos += SZ+1; 17 | updLeaf(tree[pos], val); 18 | for(pos >>= 1; pos >= 1; pos >>= 1) { 19 | tree[pos] = comb(tree[2*pos], tree[2*pos+1]); 20 | } 21 | } 22 | T query(int l, int r) { 23 | l += SZ+1; 24 | r += SZ+1; 25 | T resleft = identity; 26 | T resright = identity; 27 | while(l <= r) { 28 | if(l&1) resleft = comb(resleft, tree[l++]); 29 | if(!(r&1)) resright = comb(tree[r--], resright); 30 | l >>= 1; r >>= 1; 31 | } 32 | return comb(resleft, resright); 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /Data Structures/Square Root Decomposition: -------------------------------------------------------------------------------- 1 | struct sqrtDecomp { 2 | const static int blockSZ = 10; //change this 3 | int val[blockSZ*blockSZ]; 4 | int lazy[blockSZ]; 5 | 6 | sqrtDecomp() { 7 | M00(i, blockSZ*blockSZ) val[i] = 0; 8 | M00(i, blockSZ) lazy[i] = 0; 9 | } 10 | void upd(int l, int r, int v) { 11 | int ind = l; 12 | while(ind%blockSZ && ind <= r) { 13 | val[ind] += v; 14 | lazy[ind/blockSZ] += v; 15 | ind++; 16 | } 17 | while(ind + blockSZ <= r) { 18 | lazy[ind/blockSZ] += v*blockSZ; 19 | ind += blockSZ; 20 | } 21 | while(ind <= r) { 22 | val[ind] += v; 23 | lazy[ind/blockSZ] += v; 24 | ind++; 25 | } 26 | } 27 | int query(int l, int r) { 28 | int res = 0; 29 | int ind = l; 30 | while(ind%blockSZ && ind <= r) { 31 | res += val[ind]; 32 | ind++; 33 | } 34 | while(ind + blockSZ <= r) { 35 | res += lazy[ind/blockSZ]; 36 | ind += blockSZ; 37 | } 38 | while(ind <= r) { 39 | res += val[ind]; 40 | ind++; 41 | } 42 | return res; 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /Data Structures/Suffix Array: -------------------------------------------------------------------------------- 1 | template struct suffixArray { 2 | const static int LGSZ = 33-__builtin_clz(SZ-1); 3 | pair tup[SZ]; 4 | int sortIndex[LGSZ][SZ]; 5 | int res[SZ]; 6 | int len; 7 | string ss; 8 | void build(string s) { 9 | this->ss = s; 10 | this->len = sz(s); 11 | M00(i, len) tup[i] = mp(mp((int)s[i], -1), i); 12 | sort(tup, tup+len); 13 | int temp = 0; 14 | tup[0].f.f = 0; 15 | MOO(i, 1, len) { 16 | if(s[tup[i].s] != s[tup[i-1].s]) temp++; 17 | tup[i].f.f = temp; 18 | } 19 | M00(i, len) sortIndex[0][tup[i].s] = tup[i].f.f; 20 | MOO(i, 1, LGSZ) { 21 | M00(j, len) tup[j] = mp(mp(sortIndex[i-1][j], (j+(1<<(i-1))= len || y >= len) break; 37 | if(sortIndex[i][x] == sortIndex[i][y]) { 38 | x += (1< struct sumtree{ 2 | node* root; 3 | sumtree() { 4 | int ub = 1; 5 | while(ub < SZ) ub *= 2; 6 | root = new node(0, ub-1); 7 | } 8 | void updN(node* n, int pos, int val) { 9 | if(pos < n->l || pos > n->r) return; 10 | if(n->l == n->r) { 11 | n->val = val; 12 | return; 13 | } 14 | 15 | int mid = (n->l + n->r)/2; 16 | if(pos > mid) { 17 | if(n->right == nullptr) n->right = new node(mid+1, n->r); 18 | updN(n->right, pos, val); 19 | } 20 | else { 21 | if(n->left == nullptr) n->left = new node(n->l, mid); 22 | updN(n->left, pos, val); 23 | } 24 | 25 | int s = 0; 26 | if(n->right != nullptr) s += n->right->val; 27 | if(n->left != nullptr) s += n->left->val; 28 | 29 | n->val = s; 30 | } 31 | void upd(int pos, int val) { 32 | updN(root, pos, val); 33 | } 34 | int queryN(node* n, int i1, int i2) { 35 | if(i2 < n->l || i1 > n->r) return 0; 36 | if(n->l == n->r) return n->val; 37 | if(n->l >= i1 && n->r <= i2) return n->val; 38 | 39 | int s = 0; 40 | if(n->left != nullptr) s += queryN(n->left, i1, i2); 41 | if(n->right != nullptr) s += queryN(n->right, i1, i2); 42 | 43 | return s; 44 | } 45 | int query(int i1, int i2) { 46 | return queryN(root, i1, i2); 47 | } 48 | }; 49 | -------------------------------------------------------------------------------- /Data Structures/Trie: -------------------------------------------------------------------------------- 1 | template struct trie { 2 | int t[SZ][26]; 3 | bool mark[SZ][26]; 4 | int cursz; 5 | trie() { 6 | M00(i, SZ) M00(j, 26) t[i][j] = -1; 7 | M00(i, SZ) M00(j, 26) mark[i][j] = 0; 8 | cursz = 1; 9 | } 10 | void insert(string k) { 11 | int cur = 0; 12 | M00(i, k.length()) { 13 | int v = k[i] - 'a'; 14 | if(t[cur][v] == -1) t[cur][v] = cursz++; 15 | if(i == k.length()-1) mark[cur][v] = 1; 16 | cur = t[cur][v]; 17 | } 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /Debugging Tips: -------------------------------------------------------------------------------- 1 | - works for n = 1? 2 | - are loop bounds correct? (n vs 26) 3 | - int overflow? 4 | - ll overflow? 5 | - printed the answer twice? 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Progress (Platinum) 2 | ## 32/39 done 3 | ### 2015-2016 4 | * December: 111 5 | * January: 110 6 | * February: 111 7 | * US Open: 100 8 | 9 | ### 2016-2017 10 | * December: 111 11 | * January: 111 12 | * February: 111 13 | * US Open: 111 14 | 15 | ### 2017-2018 16 | * December: 111 17 | * January: 101 18 | * February: 111 19 | * US Open: 000 20 | 21 | ### 2018-2019 22 | * December: 111 23 | -------------------------------------------------------------------------------- /Solution Ideas: -------------------------------------------------------------------------------- 1 | - Graphs 2 | - SCC 3 | - topo sort 4 | - dfs tree 5 | - Trees 6 | - how to find diameter? 7 | - euler tour 8 | - HLD 9 | - centroid decomp 10 | - binary lifting 11 | - Array updates/queries 12 | - Mo's algorithm 13 | - Segment tree 14 | - DP 15 | - how many distinct values for the states? 16 | - how to optimize transitions? 17 | - how many states need to be stored at once? 18 | -------------------------------------------------------------------------------- /Template for Non-XCode: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | using namespace __gnu_pbds; 7 | 8 | template using Tree = tree, rb_tree_tag,tree_order_statistics_node_update>; 9 | 10 | #define F first 11 | #define S second 12 | #define PB push_back 13 | #define MP make_pair 14 | #define SQ(a) (a)*(a) 15 | #define all(v) v.begin(), v.end() 16 | #define sz(v) (int)v.size() 17 | 18 | #define MOO(i, a, b) for (int i=a; i= a; i--) 21 | #define M00d(i,a) for (int i = (a)-1; i >= 0; i--) 22 | 23 | #define FAST ios::sync_with_stdio(0); cin.tie(0); 24 | #define finish(x) return cout << x << '\n', 0; 25 | 26 | typedef long long ll; 27 | typedef long double ld; 28 | typedef vector vi; 29 | typedef pair pi; 30 | 31 | int main() { FAST 32 | 33 | } 34 | -------------------------------------------------------------------------------- /USACO/Contests/2012-2013/January/Gold/lineup.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define F first 18 | #define S second 19 | #define PB push_back 20 | #define MP make_pair 21 | #define SQ(a) (a)*(a) 22 | 23 | #define MOO(i, a, b) for (int i=a; i= a; i--) 26 | #define M00d(i,a) for (int i = (a)-1; i >= 0; i--) 27 | 28 | #define FAST ios::sync_with_stdio(0); cin.tie(0); 29 | 30 | using namespace std; 31 | 32 | typedef long long ll; 33 | typedef long double ld; 34 | typedef vector vi; 35 | typedef pair pi; 36 | 37 | const ll MOD = 1000000007; 38 | 39 | int n, k; 40 | int arr[100000]; 41 | multiset window; 42 | 43 | int main() { FAST 44 | ofstream fout("lineup.out"); 45 | ifstream fin("lineup.in"); 46 | fin >> n >> k; 47 | M00(i, n) fin >> arr[i]; 48 | int l = 0; 49 | int hi = 1; 50 | int sz = 0; 51 | M00(r, n) { 52 | window.insert(arr[r]); if(window.count(arr[r]) == 1) sz++; 53 | while(l < r && sz > k+1) { 54 | window.erase(window.find(arr[l])); 55 | if(window.count(arr[l++]) == 0) sz--; 56 | } 57 | hi = max(hi, (int)window.count(arr[r])); 58 | } 59 | fout << hi << "\n"; 60 | } 61 | -------------------------------------------------------------------------------- /USACO/Contests/2013-2014/March/Gold/fcount.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define F first 16 | #define S second 17 | #define PB push_back 18 | #define MP make_pair 19 | #define SQ(a) (a)*(a) 20 | #define PMOD(a, b) (((a)+(b))%(b)) 21 | 22 | #define MOO(i, a, b) for (int i=a; i= a; i--) 25 | #define M00d(i,a) for (int i = (a)-1; i >= 0; i--) 26 | 27 | #define FAST ios::sync_with_stdio(0); cin.tie(0); 28 | 29 | using namespace std; 30 | 31 | typedef long long ll; 32 | typedef vector vi; 33 | typedef pair pii; 34 | 35 | const int MAX_N = 500; 36 | int n; 37 | pii arr[MAX_N+5]; 38 | 39 | bool poss(int ind) { //every vertex except i 40 | int par = 0; 41 | M00(i, n) if(i != ind) par += arr[i].F % 2; 42 | if(par%2 == 1) return 0; 43 | M00(i, n) if(i != ind) { 44 | int lhs = 0; 45 | int rhs = 0; 46 | M00(j, i+1) if(j != ind) lhs += arr[j].F; 47 | int k = (i > ind) ? i-1 : i; 48 | rhs += (k+1)*k; 49 | MOO(j, i+1, n) if(j != ind) { 50 | rhs += min(k+1, arr[j].F); 51 | } 52 | if(lhs > rhs) return 0; 53 | } 54 | return 1; 55 | } 56 | 57 | int main() { FAST 58 | ofstream fout("fcount.out"); 59 | ifstream fin("fcount.in"); 60 | fin >> n; n++; 61 | M00(i, n) fin >> arr[i].F; 62 | M00(i, n) arr[i].S = i+1; 63 | sort(arr, arr+n); 64 | reverse(arr, arr+n); 65 | vi b; 66 | M00(i, n) { 67 | if(poss(i)) b.PB(arr[i].S); 68 | } 69 | sort(b.begin(), b.end()); 70 | fout << b.size() << "\n"; 71 | M00(i, b.size()) fout << b.at(i) << "\n"; 72 | } 73 | -------------------------------------------------------------------------------- /USACO/Contests/2013-2014/March/Gold/sabotage.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define F first 16 | #define S second 17 | #define PB push_back 18 | #define MP make_pair 19 | #define SQ(a) (a)*(a) 20 | #define PMOD(a, b) (((a)+(b))%(b)) 21 | 22 | #define MOO(i, a, b) for (int i=a; i= a; i--) 25 | #define M00d(i,a) for (int i = (a)-1; i >= 0; i--) 26 | 27 | #define FAST ios::sync_with_stdio(0); cin.tie(0); 28 | 29 | using namespace std; 30 | 31 | typedef long long ll; 32 | typedef vector vi; 33 | typedef pair pii; 34 | 35 | const int MAX_N = 100000; 36 | int n; 37 | int arr[MAX_N]; 38 | 39 | bool possible(double k) { //can you achieve an average <= k 40 | double narr[MAX_N]; 41 | double total = 0; 42 | M00(i, n) narr[i] = arr[i] - k; 43 | M00(i, n) total += narr[i]; 44 | //sum of the rest <= 0 45 | double hi = -10000; 46 | double curr = 0; 47 | MOO(i, 1, n-1) { 48 | curr = max(narr[i], curr + narr[i]); 49 | hi = max(hi, curr); 50 | } 51 | return (total-hi <= 0); 52 | } 53 | 54 | int main() { FAST 55 | ofstream fout("sabotage.out"); 56 | ifstream fin("sabotage.in"); 57 | fin >> n; 58 | M00(i, n) fin >> arr[i]; 59 | double hi = 10000; 60 | double lo = 0; 61 | double mid = (hi+lo)/2; 62 | while(lo + 0.0001 < hi) { 63 | if(possible(mid)) hi = mid; 64 | else lo = mid; 65 | mid = (hi+lo)/2; 66 | } 67 | fout << fixed << setprecision(3) << mid << "\n"; 68 | } 69 | -------------------------------------------------------------------------------- /USACO/Contests/2013-2014/November/Gold/empty.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define F first 16 | #define S second 17 | #define PB push_back 18 | #define MP make_pair 19 | #define SQ(a) (a)*(a) 20 | #define PMOD(a, b) (((a)+(b))%(b)) 21 | 22 | #define MOO(i, a, b) for (int i=a; i= a; i--) 25 | #define M00d(i,a) for (int i = (a)-1; i >= 0; i--) 26 | 27 | #define FAST ios::sync_with_stdio(0); cin.tie(0); 28 | 29 | using namespace std; 30 | 31 | typedef long long ll; 32 | typedef vector vi; 33 | typedef pair pii; 34 | 35 | const int MAX_N = 3000000; 36 | int n, k; 37 | int num[MAX_N]; 38 | bool occ[MAX_N]; 39 | 40 | int main() { FAST 41 | ofstream fout("empty.out"); 42 | ifstream fin("empty.in"); 43 | fin >> n >> k; 44 | int total = 0; 45 | M00(i, k) { 46 | int x, y; 47 | ll a, b; 48 | fin >> x >> y >> a >> b; 49 | MOO(i, 1, y+1) { 50 | total += x; 51 | num[(i*a+b)%n] += x; 52 | } 53 | } 54 | int done = 0; 55 | int holding = 0; 56 | int currInd = 0; 57 | while(done < total) { 58 | holding += num[currInd]; 59 | num[currInd] = 0; 60 | if(holding > 0 && !occ[currInd]) { 61 | occ[currInd] = 1; 62 | holding--; 63 | done++; 64 | } 65 | currInd++; 66 | currInd %= n; 67 | } 68 | M00(i, n) if(!occ[i]) { 69 | fout << i << "\n"; 70 | return 0; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /USACO/Contests/2014-2015/December/Gold/cowjog.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define F first 16 | #define S second 17 | #define PB push_back 18 | #define MP make_pair 19 | #define SQ(a) (a)*(a) 20 | #define PMOD(a, b) (((a)+(b))%(b)) 21 | 22 | #define MOO(i, a, b) for (int i=a; i= a; i--) 25 | #define M00d(i,a) for (int i = (a)-1; i >= 0; i--) 26 | 27 | using namespace std; 28 | 29 | typedef long long ll; 30 | typedef vector vi; 31 | typedef pair pii; 32 | 33 | int n; 34 | ll t; 35 | const int MAX_N = 100000; 36 | pair seg[MAX_N]; 37 | ll tail[MAX_N]; 38 | const ll inf = 1000000002000000000; 39 | 40 | int main() { 41 | ios::sync_with_stdio(0); 42 | cin.tie(0); 43 | ofstream fout("cowjog.out"); 44 | ifstream fin("cowjog.in"); 45 | fin >> n >> t; 46 | M00(i, n) { 47 | fin >> seg[i].F; 48 | ll b; fin >> b; 49 | seg[i].S = seg[i].F + b*t; 50 | } 51 | sort(begin(seg), begin(seg) + n); 52 | reverse(begin(seg), begin(seg)+n); 53 | 54 | ll v[MAX_N]; M00(i, MAX_N) v[i] = inf; 55 | int ans = 1; 56 | MOO(i, 1, n+1) { 57 | int j = (int)(upper_bound(begin(v), begin(v)+n, seg[i-1].S) - begin(v)); 58 | v[j] = seg[i-1].S; 59 | ans = max(ans, j+1); 60 | } 61 | fout << ans << "\n"; 62 | } 63 | -------------------------------------------------------------------------------- /USACO/Contests/2014-2015/December/Gold/guard.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define F first 16 | #define S second 17 | #define PB push_back 18 | #define MP make_pair 19 | #define SQ(a) (a)*(a) 20 | #define PMOD(a, b) (((a)+(b))%(b)) 21 | 22 | #define MOO(i, a, b) for (int i=a; i= a; i--) 25 | #define M00d(i,a) for (int i = (a)-1; i >= 0; i--) 26 | 27 | using namespace std; 28 | 29 | typedef long long ll; 30 | typedef vector vi; 31 | typedef pair pii; 32 | 33 | const ll INF = 1000000000000000; 34 | const int MAX_N = 20; 35 | int n; 36 | ll h; 37 | pair dp[1 << MAX_N]; //height, strength 38 | ll height[MAX_N]; 39 | ll weight[MAX_N]; 40 | ll strength[MAX_N]; 41 | 42 | int main() { 43 | ios::sync_with_stdio(0); 44 | cin.tie(0); 45 | ofstream fout("guard.out"); 46 | ifstream fin("guard.in"); 47 | fin >> n >> h; 48 | M00(i, n) fin >> height[i] >> weight[i] >> strength[i]; 49 | dp[0] = MP(0, INF); 50 | ll ans = -1; 51 | MOO(i, 1, 1 << n) { 52 | ll hi = -INF; 53 | M00(j, n) if(i & (1 << j)) { 54 | dp[i].F = dp[i-(1<= h) ans = max(ans, dp[i].S); 59 | } 60 | if(ans != -1) fout << ans << "\n"; 61 | else fout << "Mark is too tall\n"; 62 | } 63 | -------------------------------------------------------------------------------- /USACO/Contests/2015-2016/December/Gold/feast.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ID: ldorian1 3 | LANG: C++11 4 | TASK: 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define FOR(i, a, b) for (int i=a; i= a; i--) 22 | #define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--) 23 | #define INT_MAX 2147483647 24 | #define MAX_T 5000000 25 | 26 | using namespace std; 27 | 28 | int dp[MAX_T+1]; //0 is not drunk, 1 is drunk already, 2 is impossible 29 | int T, A, B; 30 | 31 | int main() 32 | { 33 | ofstream fout("feast.out"); 34 | ifstream fin("feast.in"); 35 | fin >> T; 36 | fin >> A >> B; 37 | F0R(i, T+1) dp[i]=2; 38 | dp[0]=0; 39 | int currMax=0; 40 | F0R(i, T+1) 41 | { 42 | if(dp[i]==0) 43 | { 44 | currMax=i; 45 | if(i+A<=T) { 46 | dp[i+A]=0; 47 | dp[(i+A)/2]=1; 48 | } 49 | if(i+B<=T) { 50 | dp[i+B]=0; 51 | dp[(i+B)/2]=1; 52 | } 53 | } 54 | else if(dp[i]==1) 55 | { 56 | currMax=i; 57 | if(i+A<=T) dp[i+A]=1; 58 | if(i+B<=T) dp[i+B]=1; 59 | } 60 | } 61 | //F0R(i, T+1) cout << dp[i] << " "; cout << endl; 62 | fout << currMax << endl; 63 | } 64 | -------------------------------------------------------------------------------- /USACO/Contests/2015-2016/February/Gold/cbarn.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ID: ldorian1 3 | LANG: C++11 4 | TASK: cbarn 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define FOR(i, a, b) for (int i=a; i= a; i--) 22 | #define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--) 23 | #define INT_MAX 2147483647 24 | #define MAX_N 100000 25 | 26 | using namespace std; 27 | 28 | int arr[MAX_N]; 29 | bool taken[MAX_N]; 30 | int N; 31 | 32 | int main() 33 | { 34 | ofstream fout("cbarn.out"); 35 | ifstream fin("cbarn.in"); 36 | fin >> N; F0R(i, N) fin >> arr[i]; 37 | int start = 0; 38 | int maxCows = 0; 39 | int currCows = 0; 40 | F0Rd(i, N) 41 | { 42 | currCows+=arr[i]; 43 | currCows--; 44 | if(currCows>maxCows) { 45 | maxCows=currCows; 46 | start=i; 47 | } 48 | } 49 | long long total = 0; 50 | long long currTime = 0; 51 | long long currPos = start; 52 | long long numCowsLeft=N; 53 | F0R(i, N) taken[i]=false; 54 | queue cows; //contains the times when the cows were picked up 55 | while(numCowsLeft>0) 56 | { 57 | F0R(i, arr[currPos]) cows.push(currTime); 58 | if(!cows.empty()&&!taken[currPos]) 59 | { 60 | int t = cows.front(); 61 | cows.pop(); 62 | total+=pow(currTime-t,2); 63 | numCowsLeft--; 64 | taken[currPos]=true; 65 | } 66 | currTime++; 67 | currPos++; currPos=currPos%N; 68 | } 69 | fout << total << endl; 70 | } 71 | -------------------------------------------------------------------------------- /USACO/Contests/2015-2016/February/Gold/cbarn2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ID: ldorian1 3 | LANG: C++11 4 | TASK: cbarn2 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #define F first 19 | #define S second 20 | #define PB push_back 21 | #define MP make_pair 22 | #define SQ(a) (a)*(a) 23 | 24 | 25 | #define FOR(i, a, b) for (int i=a; i= a; i--) 28 | #define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--) 29 | 30 | #define MAX_N 100 31 | #define MAX_K 7 32 | 33 | using namespace std; 34 | 35 | typedef long long ll; 36 | typedef vector vi; 37 | typedef pair pi; 38 | 39 | int n, k; 40 | ll dp[MAX_N][MAX_K]; 41 | ll value[MAX_N+1][MAX_N+1]; 42 | int arr[MAX_N]; 43 | 44 | ll v(int a, int b, int st) { 45 | if(value[a][b]!=-1) return value[a][b]; 46 | ll s = 0; 47 | FOR(i, a, b) s+=arr[(i+st)%n]*(i-a); 48 | value[a][b]=s; 49 | return s; 50 | } 51 | 52 | ll solve(int a, int b, int st) { 53 | if(dp[a][b]!=-1) return dp[a][b]; 54 | ll m = 10000000000; 55 | FOR(i, a+1, n) { 56 | m = min(m, v(a, i, st)+solve(i, b-1, st)); 57 | } 58 | dp[a][b]=m; 59 | return m; 60 | } 61 | 62 | int main() { 63 | ios::sync_with_stdio(0); 64 | cin.tie(0); 65 | ofstream fout("cbarn2.out"); 66 | ifstream fin("cbarn2.in"); 67 | fin >> n >> k; 68 | F0R(j, n+1) F0R(l, n+1) value[j][l]=-1; 69 | F0R(i, n) fin >> arr[i]; 70 | ll m = 10000000000; 71 | F0R(i, n) { 72 | F0R(j, n+1) F0R(l, n+1) value[j][l]=-1; 73 | F0R(j, n) F0R(l, k) dp[j][l]=-1; 74 | F0R(j, k) dp[n-1][j]=0; 75 | F0R(j, n) dp[j][0]=v(j, n, i); 76 | m=min(m,solve(0, k-1, i)); 77 | } 78 | fout << m << endl; 79 | } 80 | -------------------------------------------------------------------------------- /USACO/Contests/2015-2016/US Open/Gold/248.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ID: ldorian1 3 | LANG: C++11 4 | TASK: 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define FOR(i, a, b) for (int i=a; i= a; i--) 22 | #define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--) 23 | #define INT_MAX 2147483647 24 | 25 | using namespace std; 26 | 27 | int dp[248][248]; //dp[i][j] is number if [i,j] can be combined, -1 otherwise 28 | int n; 29 | int nums[248]; 30 | 31 | int f(int start, int end) 32 | { 33 | if(dp[start][end]!=-2) return dp[start][end]; 34 | FOR(i, start, end) 35 | { 36 | if(f(start,i)!=-1 && f(i+1,end)!=-1 && dp[start][i]==dp[i+1][end]) 37 | { 38 | dp[start][end]=dp[start][i]+1; 39 | return dp[start][end]; 40 | } 41 | } 42 | dp[start][end]=-1; 43 | return -1; 44 | } 45 | 46 | int main() 47 | { 48 | ofstream fout("248.out"); 49 | ifstream fin("248.in"); 50 | fin >> n; 51 | F0R(i, n) fin >> nums[i]; 52 | F0R(i, n) F0R(j, n) dp[i][j]=-2; 53 | F0R(i, n) dp[i][i]=nums[i]; 54 | int currMax=0; 55 | f(0, n-1); 56 | F0R(i, n) 57 | { 58 | F0R(j, n) 59 | { 60 | if(dp[i][j]>currMax) currMax=dp[i][j]; 61 | //cout< 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #define F first 21 | #define S second 22 | #define PB push_back 23 | #define MP make_pair 24 | #define SQ(a) (a)*(a) 25 | #define PMOD(a, b) (((a)+(b))%(b)) 26 | 27 | #define FOR(i, a, b) for (int i=a; i= a; i--) 30 | #define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--) 31 | 32 | #define MAX_N 262144 33 | 34 | using namespace std; 35 | 36 | typedef long long ll; 37 | typedef vector vi; 38 | typedef pair pi; 39 | 40 | int n; 41 | pair dp[MAX_N][60]; //is possible? if so, index 42 | int arr[MAX_N]; 43 | 44 | int main() { 45 | ios::sync_with_stdio(0); 46 | cin.tie(0); 47 | ofstream fout("262144.out"); 48 | ifstream fin("262144.in"); 49 | fin >> n; 50 | F0R(i, n) { 51 | fin >> arr[i]; 52 | arr[i]--; 53 | } 54 | int hi = 0; 55 | F0R(i, n) { 56 | dp[i][arr[i]].F = 1; 57 | hi = max(hi, arr[i]); 58 | dp[i][arr[i]].S = i; 59 | } 60 | FOR(i, 1, 60) { 61 | F0R(j, n) { 62 | int s2 = dp[j][i-1].S+1; 63 | if(dp[j][i-1].F && s2 < n && dp[s2][i-1].F) { 64 | dp[j][i].F = 1; 65 | dp[j][i].S = dp[dp[j][i-1].S+1][i-1].S; 66 | hi = max(hi, i); 67 | } 68 | } 69 | } 70 | fout << hi+1 << "\n"; 71 | } 72 | -------------------------------------------------------------------------------- /USACO/Contests/2016-2017/December/Platinum/team.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ID: ldorian1 3 | LANG: C++11 4 | TASK: team 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define F first 20 | #define S second 21 | #define PB push_back 22 | #define MP make_pair 23 | #define SQ(a) (a)*(a) 24 | 25 | #define FOR(i, a, b) for (int i=a; i= a; i--) 28 | #define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--) 29 | #define MAX_N 1000 30 | #define MAX_K 10 31 | #define MOD 1000000009 32 | 33 | using namespace std; 34 | 35 | typedef long long ll; 36 | typedef vector vi; 37 | typedef pair pi; 38 | 39 | ll arr0[MAX_N]; 40 | ll arr1[MAX_N]; 41 | 42 | int n, m, k; 43 | 44 | ll dp[MAX_N+1][MAX_N+1][MAX_K+1]; 45 | 46 | ll f(int a, int b, int c) { 47 | if(arr0[a]<=arr1[b]) return 0; 48 | return dp[a][b][c]; 49 | } 50 | 51 | int main() { 52 | ios::sync_with_stdio(0); 53 | cin.tie(0); 54 | ofstream fout("team.out"); 55 | ifstream fin("team.in"); 56 | fin >> n >> m >> k; 57 | F0R(i, n) fin >> arr0[i]; 58 | F0R(i, m) fin >> arr1[i]; 59 | 60 | sort(begin(arr0), begin(arr0)+n); 61 | sort(begin(arr1), begin(arr1)+m); 62 | 63 | F0R(i, m+1) F0R(j, k+1) dp[0][i][j]=0; 64 | F0R(i, n+1) F0R(j, k+1) dp[i][0][j]=0; 65 | F0R(i, n+1) F0R(j, m+1) dp[i][j][0]=1; 66 | FOR(c, 1, k+1) { 67 | FOR(a, 1, n+1) { 68 | FOR(b, 1, m+1) { 69 | dp[a][b][c]=(dp[a-1][b][c]+dp[a][b-1][c]+f(a-1,b-1,c-1)-dp[a-1][b-1][c]+MOD)%MOD; 70 | } 71 | } 72 | } 73 | fout << dp[n][m][k] << endl; 74 | } 75 | -------------------------------------------------------------------------------- /USACO/Contests/2016-2017/February/Gold/circlecross.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ID: ldorian1 3 | LANG: C++11 4 | TASK: circlecross 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define FOR(i, a, b) for (int i=a; i= a; i--) 22 | #define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--) 23 | #define INT_MAX 2147483647 24 | #define MAX_N 50000 25 | 26 | using namespace std; 27 | 28 | int n; 29 | int BIT[2*MAX_N]; 30 | pair ranges[MAX_N]; 31 | 32 | void update(int i, int v) { 33 | while(i<=2*n) { 34 | BIT[i]+=v; 35 | i += (i & -i); 36 | } 37 | } 38 | 39 | int sum(int s) { 40 | int total = 0; 41 | while(s>0) { 42 | total+=BIT[s]; 43 | s -= (s & -s); 44 | } 45 | return total; 46 | } 47 | 48 | int rangeSum(int s, int e) { 49 | return sum(e)-sum(s); 50 | } 51 | 52 | int main() { 53 | ofstream fout("circlecross.out"); 54 | ifstream fin("circlecross.in"); 55 | fin >> n; 56 | F0R(i, n) { 57 | ranges[i].first = -1; ranges[i].second = -1; 58 | } 59 | F0R(i, 2*n) { 60 | int k; fin >> k; k--; 61 | if(ranges[k].first==-1) ranges[k].first=i; 62 | else ranges[k].second=i; 63 | } 64 | sort(begin(ranges), begin(ranges)+n); 65 | int total = 0; 66 | F0R(i, 2*n) { 67 | BIT[i]=0; 68 | } 69 | F0R(i, n) { 70 | total+=rangeSum(ranges[i].first, ranges[i].second); 71 | update(ranges[i].second,1); 72 | } 73 | fout << total << endl; 74 | } 75 | -------------------------------------------------------------------------------- /USACO/Contests/2016-2017/January/Gold/bphoto.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ID: ldorian1 3 | LANG: C++11 4 | TASK: bphoto 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define FOR(i, a, b) for (int i=a; i= a; i--) 22 | #define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--) 23 | #define MAX_N 100000 24 | 25 | using namespace std; 26 | 27 | int n; 28 | pair nums[MAX_N]; 29 | int BIT[MAX_N+1], numInBIT; 30 | 31 | void update(int i, int v) { 32 | numInBIT++; 33 | i++; 34 | while(i<=n) { 35 | BIT[i]+=v; 36 | i += (i&-i); 37 | } 38 | } 39 | int preSum(int k) { 40 | k++; 41 | int s = 0; 42 | while(k>0) { 43 | s+=BIT[k]; 44 | k -= (k&-k); 45 | } 46 | return s; 47 | } 48 | bool unbal(int a, int b) { 49 | return(max(a,b)>2*min(a,b)); 50 | } 51 | 52 | int main() { 53 | ofstream fout("bphoto.out"); 54 | ifstream fin("bphoto.in"); 55 | fin >> n; 56 | F0R(i, n) fin >> nums[i].first; 57 | F0R(i, n) nums[i].second=i; 58 | sort(nums, nums+n); 59 | int total = 0; 60 | F0Rd(i, n) { 61 | int left = preSum(nums[i].second - 1); 62 | int right = numInBIT - left; 63 | if(unbal(left,right)) { 64 | total++; 65 | } 66 | update(nums[i].second, 1); 67 | } 68 | fout << total << endl; 69 | } 70 | -------------------------------------------------------------------------------- /USACO/Contests/2016-2017/January/Platinum/tallbarn.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define F first 15 | #define S second 16 | #define PB push_back 17 | #define MP make_pair 18 | #define SQ(a) (a)*(a) 19 | #define PMOD(a, b) (((a)+(b))%(b)) 20 | 21 | #define MOO(i, a, b) for (int i=a; i= a; i--) 24 | #define M00d(i,a) for (int i = (a)-1; i >= 0; i--) 25 | 26 | #define MAX_N 100000 27 | 28 | using namespace std; 29 | 30 | typedef long long ll; 31 | typedef vector vi; 32 | typedef pair pi; 33 | typedef long double ld; 34 | 35 | int n; 36 | ll k; 37 | ll arr[MAX_N]; 38 | 39 | ld cost(ll a, ll b) { 40 | return ((ld)(a))/((ld)(b) * (ld)(b+1)); 41 | } 42 | 43 | ll cowsNeeded(ld c) { //for each floor, add cows until the profit is less than cost 44 | ll ans = 0; 45 | M00(i, n) { 46 | ld d = ((ld)(arr[i]))/c; 47 | int k = floor(sqrt(1.0+4*d)-1)/2.0; 48 | ans += k; 49 | } 50 | return ans; 51 | } 52 | 53 | int main() { 54 | ios::sync_with_stdio(0); 55 | cin.tie(0); 56 | ofstream fout("tallbarn.out"); 57 | ifstream fin("tallbarn.in"); 58 | fin >> n >> k; 59 | k-=n; 60 | M00(i, n) fin >> arr[i]; 61 | ld hi = 1e18; 62 | ld lo = 0; 63 | ld mid = 0; 64 | M00(i, 300) { 65 | mid = (lo+hi)/2; 66 | if(cowsNeeded(mid) >= k) lo = mid; 67 | else hi = mid; 68 | } 69 | ld ans = 0.0; 70 | ll tot = 0; 71 | M00(i, n) { 72 | ld d = ((ld)(arr[i]))/lo; 73 | int v = floor((sqrt(1.0+4*d)-1)/2.0); 74 | tot += v; 75 | ans += ((ld)(arr[i]))/((ld)(v+1)); 76 | } 77 | fout << llround(ans+(tot-k)*lo) << "\n"; 78 | } 79 | -------------------------------------------------------------------------------- /USACO/Contests/2017-2018/December/Platinum/greedy.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define F first 18 | #define S second 19 | #define PB push_back 20 | #define MP make_pair 21 | #define SQ(a) (a)*(a) 22 | 23 | #define MOO(i, a, b) for (int i=a; i= a; i--) 26 | #define M00d(i,a) for (int i = (a)-1; i >= 0; i--) 27 | 28 | #define FAST ios::sync_with_stdio(0); cin.tie(0); 29 | 30 | using namespace std; 31 | 32 | typedef long long ll; 33 | typedef long double ld; 34 | typedef vector vi; 35 | typedef pair pi; 36 | 37 | const ll MOD = 1000000007; 38 | const int MAX_N = 100000; 39 | int n; 40 | int arr[MAX_N]; 41 | 42 | bool poss(int c) { 43 | vi a; 44 | M00(i, c-1) a.PB(arr[i]); 45 | sort(a.begin(), a.end()); 46 | M00(i, a.size()) if(a[i] < i+1) return 0; 47 | return 1; 48 | } 49 | 50 | int main() { FAST 51 | ofstream fout("greedy.out"); 52 | ifstream fin("greedy.in"); 53 | fin >> n; M00(i, n) fin >> arr[i]; 54 | M00(i, n) arr[i] = n - arr[i] - 1; 55 | int cur = 0; 56 | for(int jump = n; jump > 0; jump /= 2) { 57 | while(cur + jump < n && poss(cur + jump)) cur += jump; 58 | } 59 | fout << n - cur << "\n"; 60 | } 61 | -------------------------------------------------------------------------------- /USACO/Training/3.1/inflate.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ID: ldorian1 3 | LANG: C++11 4 | TASK: inflate 5 | */ 6 | 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define FOR(i, a, b) for (int i=a; i= a; i--) 19 | #define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--) 20 | #define INT_MAX 2147483647 21 | 22 | using namespace std; 23 | 24 | int totalTime; 25 | int numCategories; 26 | vector> categories; //categories[i].first is the number of points, categories[i].second is the time 27 | int dparr[10001]; //dparr[i] is max value with i time left 28 | 29 | int main() 30 | { 31 | //READING INPUT 32 | //******************************************************************** 33 | ofstream fout("inflate.out"); 34 | ifstream fin("inflate.in"); 35 | fin >> totalTime >> numCategories; 36 | F0R(i, numCategories) 37 | { 38 | pair temp; 39 | fin >> temp.first >> temp.second; 40 | categories.push_back(temp); 41 | } 42 | 43 | //DP 44 | //******************************************************************** 45 | F0R(i, totalTime+1) 46 | { 47 | int currMax=0; 48 | F0R(j, numCategories) 49 | { 50 | if(i-categories[j].second>=0&&categories[j].first+dparr[i-categories[j].second]>currMax) 51 | currMax=categories[j].first+dparr[i-categories[j].second]; 52 | } 53 | dparr[i]=currMax; 54 | } 55 | 56 | //PRINTING OUTPUT 57 | //******************************************************************** 58 | fout << dparr[totalTime] << endl; 59 | } 60 | -------------------------------------------------------------------------------- /USACO/Training/3.2/stringsobits.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ID: ldorian1 3 | LANG: C++11 4 | TASK: kimbits 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define FOR(i, a, b) for (int i=a; i= a; i--) 21 | #define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--) 22 | #define INT_MAX 2147483647 23 | 24 | using namespace std; 25 | 26 | long long numBits, maxNum1s, n; 27 | string ans = ""; 28 | 29 | long long choose(long long a, long long b) //a choose b 30 | { 31 | if(b>a||b<0||a<0) return 0; 32 | long long answer = 1; 33 | FORd(i, a-b+1, a+1) 34 | { 35 | answer*=i; 36 | answer/=a-i+1; 37 | } 38 | return answer; 39 | } 40 | 41 | long long sumChoose(long long a, long long i, long long j) //a C (i) + a C (i+1) + a C (i+2) + ... + a C (j) 42 | { 43 | long long sum = 0; 44 | FOR(k, i, j+1) sum+=choose(a,k); 45 | return sum; 46 | } 47 | 48 | int main() 49 | { 50 | ofstream fout("kimbits.out"); 51 | ifstream fin("kimbits.in"); 52 | fin >> numBits >> maxNum1s >> n; n--; 53 | long long onesLeft = maxNum1s; 54 | long long min = 0; 55 | long long max = sumChoose(numBits, 0, onesLeft)-1; 56 | while(ans.length()=n) 61 | { 62 | ans+="0"; 63 | max=min+sumIf0-1; 64 | } 65 | else 66 | { 67 | ans+="1"; 68 | onesLeft--; 69 | min=min+sumIf0; 70 | } 71 | } 72 | fout << ans << endl; 73 | } 74 | -------------------------------------------------------------------------------- /USACO/Training/3.3/range.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ID: ldorian1 3 | LANG: C++11 4 | TASK: range 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define FOR(i, a, b) for (int i=a; i= a; i--) 21 | #define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--) 22 | #define INT_MAX 2147483647 23 | 24 | using namespace std; 25 | 26 | const int MAX_N=250; 27 | 28 | bool good[MAX_N][MAX_N]; //good[i][j] determines whether square at (i,j) is edible 29 | bool good1[MAX_N][MAX_N]; 30 | 31 | int main() 32 | { 33 | //READING INPUT 34 | ofstream fout("range.out"); 35 | ifstream fin("range.in"); 36 | int n; fin >> n; 37 | int a[n][n]; 38 | F0R(i, n) 39 | { 40 | string s; fin >> s; 41 | F0R(j, n) 42 | { 43 | a[i][j]=stoi(s.substr(j,1)); 44 | } 45 | } 46 | int ans[n+1]; F0R(i, n+1) ans[i]=0; 47 | 48 | 49 | //SETTING UP SQUARES OF SIDE 1 50 | F0R(i, n) F0R(j, n) if(a[i][j]==1) 51 | { 52 | good[i][j]=true; 53 | } 54 | //MAIN ALGORITHM 55 | FOR(side, 2, n+1) 56 | { 57 | F0R(i, n-side+1) F0R(j, n-side+1) 58 | { 59 | if(good[i][j]&&good[i+1][j]&&good[i][j+1]&&good[i+1][j+1]) 60 | { 61 | good1[i][j]=true; 62 | ans[side]++; 63 | } 64 | } 65 | F0R(i, n) F0R(j, n) 66 | { 67 | good[i][j]=good1[i][j]; 68 | good1[i][j]=false; 69 | } 70 | } 71 | FOR(i, 2, n+1) if(ans[i]!=0) fout << i << " " << ans[i] << endl; 72 | } -------------------------------------------------------------------------------- /USACO/Training/3.4/fence9.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ID: ldorian1 3 | LANG: C++11 4 | TASK: fence9 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define FOR(i, a, b) for (int i=a; i= a; i--) 22 | #define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--) 23 | #define INT_MAX 2147483647 24 | 25 | using namespace std; 26 | 27 | int a, b, p; 28 | 29 | long gcd(int a, int b) 30 | { 31 | if(a==b) return a; 32 | if(a==0) return b; 33 | if(b==0) return a; 34 | if(a> a >> b >> p; 49 | long area = (p*b)/2; 50 | long tBP; 51 | if(p>a) tBP=p+getNumLatticePoints(a, b)+getNumLatticePoints(p-a, b)-2; 52 | else tBP=p+getNumLatticePoints(a, b)+getNumLatticePoints(a-p, b)-2; 53 | fout << area+1-tBP/2 << endl; 54 | } 55 | -------------------------------------------------------------------------------- /USACO/Training/3.4/rockers.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ID: ldorian1 3 | LANG: C++11 4 | TASK: rockers 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define FOR(i, a, b) for (int i=a; i= a; i--) 22 | #define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--) 23 | #define INT_MAX 2147483647 24 | 25 | using namespace std; 26 | 27 | int numSongs, totalTime, numAlbums; 28 | int songs[20]; 29 | 30 | vector binary(long long num, int numDigits) 31 | { 32 | vector ans; 33 | int i = numDigits-1; 34 | while(num>0) 35 | { 36 | if(num%2==1) ans.push_back(i); 37 | num/=2; 38 | i--; 39 | } 40 | return ans; 41 | } 42 | 43 | bool works(vector c) 44 | { 45 | int total=0; 46 | int alb=0; 47 | F0R(i, (int)(c.size())) 48 | { 49 | if(songs[c.at(i)]>totalTime) return false; 50 | total+=songs[c.at(i)]; 51 | if(total>totalTime) 52 | { 53 | total=songs[c.at(i)]; 54 | alb++; 55 | } 56 | if(alb==numAlbums) return false; 57 | } 58 | return true; 59 | } 60 | 61 | int main() 62 | { 63 | ofstream fout("rockers.out"); 64 | ifstream fin("rockers.in"); 65 | fin >> numSongs >> totalTime >> numAlbums; 66 | F0R(i, numSongs) fin >> songs[i]; 67 | int currBest=0; 68 | F0Rd(i, pow(2,numSongs)) 69 | { 70 | vector combo = binary(i, numSongs); 71 | if(combo.size()>currBest) 72 | { 73 | if(works(combo)) currBest=combo.size(); 74 | } 75 | } 76 | fout << currBest << endl; 77 | } 78 | -------------------------------------------------------------------------------- /USACO/Training/4.1/nuggets.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ID: ldorian1 3 | LANG: C++11 4 | TASK: nuggets 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define FOR(i, a, b) for (int i=a; i= a; i--) 22 | #define F0Rd(i,a) for (int i = (a)-1; i >= 0; i--) 23 | #define INT_MAX 2147483647 24 | 25 | using namespace std; 26 | int numOffers; 27 | int nuggets[10]; 28 | bool dparr[100000]; 29 | 30 | int gcd(int a, int b) 31 | { 32 | if(b%a==0) return a; 33 | if(a%b==0) return b; 34 | if(a==b) return a; 35 | if(b>a) return gcd(a, b-a*(b/a)); 36 | return gcd(a-b*(a/b), b); 37 | } 38 | 39 | int gcdAll(int a[], int num) //gcd of first num values in a 40 | { 41 | int ans = a[0]; 42 | F0R(i, num) ans = gcd(ans, a[i]); 43 | return ans; 44 | } 45 | 46 | int main() 47 | { 48 | ofstream fout("nuggets.out"); 49 | ifstream fin("nuggets.in"); 50 | fin >> numOffers; 51 | F0R(i, numOffers) fin >> nuggets[i]; 52 | if(gcdAll(nuggets, numOffers)!=1) 53 | { 54 | fout << "0" << endl; 55 | return 0; 56 | } 57 | int currMax=0; 58 | dparr[0]=true; 59 | F0R(i, 100000) 60 | { 61 | if(dparr[i]) 62 | { 63 | F0R(j, numOffers) 64 | { 65 | if(i+nuggets[j]<100000) dparr[i+nuggets[j]]=true; 66 | } 67 | } 68 | else currMax=i; 69 | } 70 | fout << currMax << endl; 71 | } 72 | -------------------------------------------------------------------------------- /referencepdf/Makefile: -------------------------------------------------------------------------------- 1 | LATEXCMD = pdflatex -shell-escape -output-directory build/ 2 | export TEXINPUTS=.:content/tex/: 3 | export max_print_line = 1048576 4 | 5 | help: 6 | @echo "This makefile builds KACTL (KTH Algorithm Competition Template Library)" 7 | @echo "" 8 | @echo "Available commands are:" 9 | @echo " make fast - to build KACTL, quickly (only runs LaTeX once)" 10 | @echo " make kactl - to build KACTL" 11 | @echo " make clean - to clean up the build process" 12 | @echo " make veryclean - to clean up and remove kactl.pdf" 13 | @echo " make help - to show this information" 14 | @echo "" 15 | @echo "For more information see the file 'doc/README'" 16 | 17 | fast: | build 18 | $(LATEXCMD) content/tex/kactl.tex k 25 | vector gen; 26 | void clear(int p) { 27 | memset(flag,0, sizeof flag); 28 | flag[p] = 1; sigma[p] = id(); 29 | gen.clear(); 30 | } 31 | } g[N]; 32 | 33 | bool check(const vi& cur, int k) { 34 | if (!k) return 1; 35 | int t = cur[k]; 36 | return g[k].flag[t] ? check(inv(g[k].sigma[t])*cur,k-1) : 0; 37 | } 38 | void updateX(const vi& cur, int k); 39 | void ins(const vi& cur, int k) { 40 | if (check(cur,k)) return; 41 | g[k].gen.pb(cur); 42 | F0R(i,n) if (g[k].flag[i]) updateX(cur*g[k].sigma[i],k); 43 | } 44 | void updateX(const vi& cur, int k) { 45 | int t = cur[k]; 46 | if (g[k].flag[t]) ins(inv(g[k].sigma[t])*cur,k-1); // fixes k -> k 47 | else { 48 | g[k].flag[t] = 1, g[k].sigma[t] = cur; 49 | trav(x,g[k].gen) updateX(x*cur,k); 50 | } 51 | } 52 | 53 | ll order(vector gen) { 54 | assert(sz(gen)); n = sz(gen[0]); F0R(i,n) g[i].clear(i); 55 | trav(a,gen) ins(a,n-1); // insert perms into group one by one 56 | ll tot = 1; 57 | F0R(i,n) { 58 | int cnt = 0; F0R(j,i+1) cnt += g[i].flag[j]; 59 | tot *= cnt; 60 | } 61 | return tot; 62 | } -------------------------------------------------------------------------------- /referencepdf/content/combinatorial (11.2)/chapter.tex: -------------------------------------------------------------------------------- 1 | \chapter{Combinatorial} 2 | 3 | \kactlimport{IntPerm.h} 4 | \kactlimport{MatroidIntersect.h} 5 | \kactlimport{PermGroup.h} -------------------------------------------------------------------------------- /referencepdf/content/contest/.bashrc: -------------------------------------------------------------------------------- 1 | co() { 2 | g++ -std=c++11 $1.cpp -o $1 3 | } 4 | 5 | run() { 6 | if [ $# -eq 2 ] 7 | then 8 | ./$1 < $1$2.in 9 | else 10 | ./$1 11 | fi 12 | } 13 | 14 | crun() { 15 | co $1 && echo "Compiled!" && run $1 $2 16 | } 17 | -------------------------------------------------------------------------------- /referencepdf/content/contest/.vimrc: -------------------------------------------------------------------------------- 1 | set nocp bs=indent,eol,start nu ru si ts=4 sw=4 sts=0 sta et is hls sm mouse=a 2 | syntax on 3 | filetype plugin indent on 4 | -------------------------------------------------------------------------------- /referencepdf/content/contest/README.md: -------------------------------------------------------------------------------- 1 | # Template Notes 2 | 3 | - The header files will not compile with clang; use gcc instead. 4 | - If you don't know what the following line does, see Range Queries --> README --> C++ STL for more information. 5 | 6 | ```cpp 7 | template using Tree = tree, rb_tree_tag,tree_order_statistics_node_update>; 8 | ``` 9 | 10 | # Pragma Optimization 11 | 12 | * [Explanation](https://codeforces.com/blog/entry/54682?#comment-387553) 13 | * Problems 14 | * [Nagini](https://codeforces.com/contest/855/submission/47823825) 15 | * [Welcome home, Chtholly](https://codeforces.com/contest/896/submission/47824007) 16 | 17 | # Snippets 18 | 19 | TopCoder: 20 | 21 | [New Java Applet](https://codeforces.com/blog/entry/64597) (use ctrl-c instead of command-c on mac ...) 22 | 23 | ``` 24 | class C { 25 | public: 26 | int m() { 27 | 28 | } 29 | }; 30 | 31 | int main() { 32 | setIO(); 33 | C c; ps(c.m()); 34 | } 35 | ``` 36 | 37 | Google Kickstart / Facebook Hacker Cup 38 | 39 | ``` 40 | int N; 41 | 42 | void inp(vi& v) { // common way to reduce amount of input 43 | v.rsz(1); ll A,B,C; re(v,A,B,C); 44 | while (sz(v) < N) v.pb((A*v.back()+B)%C+1); 45 | } 46 | 47 | void solve(int caseNum) { 48 | cerr << "Doing #" << caseNum << "\n"; 49 | 50 | } 51 | 52 | int main() { 53 | // setIO("A"); 54 | int T; re(T); 55 | FOR(i,1,T+1) { 56 | pr("Case #",i,": "); 57 | solve(i); 58 | } 59 | } 60 | ``` 61 | -------------------------------------------------------------------------------- /referencepdf/content/contest/chapter.tex: -------------------------------------------------------------------------------- 1 | \chapter{Contest} 2 | 3 | \kactlimport[-l rawcpp]{template.cpp} 4 | \kactlimport[-l sh]{.bashrc} 5 | \kactlimport[-l raw]{.vimrc} 6 | \kactlimport[-l raw]{cppreference.txt} 7 | \kactlimport[-l raw]{stress.sh} 8 | 9 | -------------------------------------------------------------------------------- /referencepdf/content/contest/cppreference.txt: -------------------------------------------------------------------------------- 1 | atan(m) -> angle from -pi/2 to pi/2 2 | atan2(y,x) -> angle from -pi to pi 3 | acos(x) -> angle from 0 to pi 4 | asin(y) -> angle from -pi/2 to pi/2 5 | 6 | lower_bound -> first element >= val 7 | upper_bound -> first element > val -------------------------------------------------------------------------------- /referencepdf/content/contest/hash.sh: -------------------------------------------------------------------------------- 1 | # Hashes a file, ignoring all whitespace and comments. Use for 2 | # verifying that code was correctly typed. 3 | cpp -dD -P -fpreprocessed | tr -d '[:space:]'| md5sum |cut -c-6 4 | -------------------------------------------------------------------------------- /referencepdf/content/contest/kactlTemplate.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define rep(i, a, b) for(int i = a; i < (b); ++i) 5 | #define trav(a, x) for(auto& a : x) 6 | #define all(x) begin(x), end(x) 7 | #define sz(x) (int)(x).size() 8 | typedef long long ll; 9 | typedef pair pii; 10 | typedef vector vi; 11 | 12 | int main() { 13 | cin.sync_with_stdio(0); cin.tie(0); 14 | cin.exceptions(cin.failbit); 15 | } 16 | -------------------------------------------------------------------------------- /referencepdf/content/contest/stress.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | g++ -std=c++11 $1.cpp -o solution 4 | g++ -std=c++11 $1Dumb.cpp -o stupid 5 | g++ -std=c++11 $1Gen.cpp -o gen 6 | 7 | for((i = 1; ; i++)) do 8 | ./gen $i > input 9 | ./solution < input > out 10 | ./stupid < input > out-stupid 11 | 12 | if ! cmp -s out out-stupid 13 | then 14 | echo 'FAIL' 15 | echo 'Test case:' 16 | cat input 17 | echo 'Output:' 18 | cat out 19 | echo 'Answer:' 20 | cat out-stupid 21 | break 22 | fi 23 | echo 'OK' 24 | done 25 | -------------------------------------------------------------------------------- /referencepdf/content/contest/template.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define f first 5 | #define s second 6 | #define pb push_back 7 | #define mp make_pair 8 | #define all(v) v.begin(), v.end() 9 | #define sz(v) (int)v.size() 10 | 11 | #define MOO(i, a, b) for(int i=a; i= a; i--) 14 | #define M00d(i,a) for(int i = (a)-1; i>=0; i--) 15 | 16 | #define FAST ios::sync_with_stdio(0); cin.tie(0); 17 | #define finish(x) return cout << x << '\n', 0; 18 | #define dbg(x) cerr << ">>> " << #x << " = " << x << "\n"; 19 | #define _ << " _ " << 20 | 21 | typedef long long ll; 22 | typedef long double ld; 23 | typedef vector vi; 24 | typedef pair pi; 25 | typedef pair pd; 26 | typedef complex cd; 27 | 28 | int main() { FAST 29 | 30 | } 31 | 32 | -------------------------------------------------------------------------------- /referencepdf/content/contest/templateShort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | #define f first 6 | #define s second 7 | #define pb push_back 8 | #define mp make_pair 9 | #define sq(a) (a)*(a) 10 | #define all(v) v.begin(), v.end() 11 | #define sz(v) (int)v.size() 12 | 13 | #define MOO(i, a, b) for(int i=a; i= a; i--) 16 | #define M00d(i,a) for(int i = (a)-1; i>=0; i--) 17 | 18 | #define FAST ios::sync_with_stdio(0); cin.tie(0); 19 | #define finish(x) return cout << x << '\n', 0; 20 | 21 | typedef long long ll; 22 | typedef long double ld; 23 | typedef vector vi; 24 | typedef pair pi; 25 | typedef pair pd; 26 | typedef complex cd; 27 | 28 | int main() { FAST 29 | 30 | } 31 | -------------------------------------------------------------------------------- /referencepdf/content/data-structures/1D Range Queries (9.2)/BIT (9.2).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: $N$-D range sum query with point update 3 | * Source: https://codeforces.com/blog/entry/64914 4 | * Verification: SPOJ matsum 5 | * Time: O((\log N)^D) 6 | */ 7 | 8 | template struct BIT { 9 | T val = 0; 10 | void upd(T v) { val += v; } 11 | T query() { return val; } 12 | }; 13 | 14 | template struct BIT { 15 | BIT bit[N+1]; 16 | template void upd(int pos, Args... args) { 17 | for (; pos <= N; pos += (pos&-pos)) bit[pos].upd(args...); 18 | } 19 | template T sum(int r, Args... args) { 20 | T res = 0; for (; r; r -= (r&-r)) res += bit[r].query(args...); 21 | return res; 22 | } 23 | template T query(int l, int r, Args... args) { 24 | return sum(r,args...)-sum(l-1,args...); 25 | } 26 | }; // BIT gives a 2D BIT -------------------------------------------------------------------------------- /referencepdf/content/data-structures/1D Range Queries (9.2)/BITrange.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: 1D range increment and sum query 3 | * Source: https://www.geeksforgeeks.org/binary-indexed-tree-range-update-range-queries/ 4 | * Verification: CSES 5 | * Time: O(\log N) 6 | */ 7 | 8 | #include "BIT.h" 9 | 10 | template struct BITrange { 11 | BIT bit[2]; // piecewise linear functions 12 | // let cum[x] = sum_{i=1}^{x}a[i] 13 | void upd(int hi, T val) { // add val to a[1..hi] 14 | bit[1].upd(1,val), bit[1].upd(hi+1,-val); // if x <= hi, cum[x] += val*x 15 | bit[0].upd(hi+1,hi*val); // if x > hi, cum[x] += val*hi 16 | } 17 | void upd(int lo, int hi, T val) { upd(lo-1,-val), upd(hi,val); } 18 | T sum(int x) { return bit[1].sum(x)*x+bit[0].sum(x); } // get cum[x] 19 | T query(int x, int y) { return sum(y)-sum(x-1); } 20 | }; -------------------------------------------------------------------------------- /referencepdf/content/data-structures/1D Range Queries (9.2)/MaxQueue.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: queue, but get() returns max element 3 | * Time: O(1) 4 | * Source: none 5 | * Verification: none 6 | */ 7 | 8 | struct maxQueue { 9 | queue q; 10 | deque dq; 11 | void push(int v) { 12 | q.push(v); 13 | if(q.empty()) {dq.push_back(v); return;} 14 | while(!dq.empty() && dq.back() < v) dq.pop_back(); 15 | dq.push_back(v); 16 | } 17 | void pop() { 18 | if(q.front() == dq.front()) dq.pop_front(); 19 | q.pop(); 20 | } 21 | int get() {return dq.front();} 22 | int size() {return (int)q.size();} 23 | }; 24 | -------------------------------------------------------------------------------- /referencepdf/content/data-structures/1D Range Queries (9.2)/Mo (15.1).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Answers queries offline in (N+Q)sqrt(N) 3 | * Also see Mo's on trees 4 | * Source: Codeforces 5 | * Verification: https://codeforces.com/contest/617/problem/E 6 | */ 7 | 8 | int N, A[MX]; 9 | int ans[MX], oc[MX], BLOCK; 10 | vector> todo; // store left, right, index of ans 11 | 12 | bool cmp(array a, array b) { // sort queries 13 | if (a[0]/BLOCK != b[0]/BLOCK) return a[0] < b[0]; 14 | return a[1] < b[1]; 15 | } 16 | 17 | int l = 0, r = -1, cans = 0; 18 | 19 | void modify(int x, int y = 1) { 20 | x = A[x]; 21 | // if condition: cans --; 22 | oc[x] += y; 23 | // if condition: cans ++; 24 | } 25 | 26 | int answer(int L, int R) { // modifyjust interval 27 | while (l > L) modify(--l); 28 | while (r < R) modify(++r); 29 | while (l < L) modify(l++,-1); 30 | while (r > R) modify(r--,-1); 31 | return cans; 32 | } 33 | 34 | void solve() { 35 | BLOCK = sqrt(N); sort(all(todo),cmp); 36 | trav(x,todo) { 37 | answer(x[0],x[1]); 38 | ans[x[2]] = cans; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /referencepdf/content/data-structures/1D Range Queries (9.2)/Node.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Node 3 | * Source: ? 4 | * Verification: ? 5 | */ 6 | 7 | struct node { 8 | int val; 9 | int lazy; 10 | int l, r; 11 | node* left; 12 | node* right; 13 | node(int l, int r) { 14 | this -> val = 0; 15 | this -> lazy = 0; 16 | this -> l = l; 17 | this -> r = r; 18 | this -> left = nullptr; 19 | this -> right = nullptr; 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /referencepdf/content/data-structures/1D Range Queries (9.2)/SegTree (9.2).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: 1D point update, range query 3 | * Time: O(\log N) 4 | * Source: 5 | * http://codeforces.com/blog/entry/18051 6 | * KACTL 7 | * Verification: SPOJ Fenwick 8 | */ 9 | 10 | template struct segtree { 11 | // modify these 12 | T identity = 0; 13 | T comb(T l, T r) { 14 | return l + r; 15 | } 16 | void updLeaf(T& l, T val) { 17 | l = val; 18 | } 19 | 20 | T tree[2*SZ+1]; 21 | segtree() { 22 | M00(i, 2*SZ+1) tree[i] = identity; 23 | } 24 | void upd(int pos, T val) { 25 | pos += SZ+1; 26 | updLeaf(tree[pos], val); 27 | for(pos >>= 1; pos >= 1; pos >>= 1) { 28 | tree[pos] = comb(tree[2*pos], tree[2*pos+1]); 29 | } 30 | } 31 | T query(int l, int r) { 32 | l += SZ+1; 33 | r += SZ+1; 34 | T res = identity; 35 | while(l <= r) { 36 | if(l&1) res = comb(res, tree[l++]); 37 | if(!(r&1)) res = comb(res, tree[r--]); 38 | l >>= 1; r >>= 1; 39 | } 40 | return res; 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /referencepdf/content/data-structures/1D Range Queries (9.2)/SqrtDecomp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: 1D point update, range query 3 | * Time: O(\sqrt{N}) 4 | * Source: imagine 5 | * Verification: imagine 6 | */ 7 | 8 | struct sqrtDecomp { 9 | const static int blockSZ = 10; //change this 10 | int val[blockSZ*blockSZ]; 11 | int lazy[blockSZ]; 12 | 13 | sqrtDecomp() { 14 | M00(i, blockSZ*blockSZ) val[i] = 0; 15 | M00(i, blockSZ) lazy[i] = 0; 16 | } 17 | void upd(int l, int r, int v) { 18 | int ind = l; 19 | while(ind%blockSZ && ind <= r) { 20 | val[ind] += v; 21 | lazy[ind/blockSZ] += v; 22 | ind++; 23 | } 24 | while(ind + blockSZ <= r) { 25 | lazy[ind/blockSZ] += v*blockSZ; 26 | ind += blockSZ; 27 | } 28 | while(ind <= r) { 29 | val[ind] += v; 30 | lazy[ind/blockSZ] += v; 31 | ind++; 32 | } 33 | } 34 | int query(int l, int r) { 35 | int res = 0; 36 | int ind = l; 37 | while(ind%blockSZ && ind <= r) { 38 | res += val[ind]; 39 | ind++; 40 | } 41 | while(ind + blockSZ <= r) { 42 | res += lazy[ind/blockSZ]; 43 | ind += blockSZ; 44 | } 45 | while(ind <= r) { 46 | res += val[ind]; 47 | ind++; 48 | } 49 | return res; 50 | } 51 | }; 52 | -------------------------------------------------------------------------------- /referencepdf/content/data-structures/1D Range Queries (9.2)/Wavelet Tree.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Segment tree on values instead of indices 3 | * Source: http://rachitiitr.blogspot.com/2017/06 4 | /wavelet-trees-wavelet-trees-editorial.html 5 | * Verification: http://www.spoj.com/problems/MKTHNUM/ 6 | */ 7 | 8 | template struct Wavelet { 9 | vi mapl[2*SZ], mapr[2*SZ], val[2*SZ]; 10 | void build(int ind = 1, int L = 0, int R = SZ-1) { // build a wavelet tree 11 | if (ind == 1) { F0R(i,N) val[ind].pb(i); } 12 | if (L == R) return; 13 | int M = (L+R)/2; 14 | trav(i,val[ind]) { 15 | val[2*ind+(A[i] > M)].pb(i); 16 | mapl[ind].pb(sz(val[2*ind])-1); 17 | mapr[ind].pb(sz(val[2*ind+1])-1); 18 | } 19 | build(2*ind,L,M); 20 | build(2*ind+1,M+1,R); 21 | } 22 | 23 | int getl(int ind, int x) { return x < 0 ? -1 : mapl[ind][x]; } 24 | int getr(int ind, int x) { return x < 0 ? -1 : mapr[ind][x]; } 25 | int query(int lind, int rind, int k, int ind = 1, int L = 0, int R = SZ-1) { // get k-th largest number in interval 26 | if (L == R) return L; 27 | 28 | int M = (L+R)/2; 29 | int t = getl(ind,rind)-getl(ind,lind-1); 30 | if (t >= k) return query(getl(ind,lind-1)+1, 31 | getl(ind,rind),k,2*ind,L,M); 32 | return query(getr(ind,lind-1)+1, 33 | getr(ind,rind),k-t,2*ind+1,M+1,R); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /referencepdf/content/data-structures/2D Range Queries (15.2)/2D SegBIT (15.2).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Binary Indexed Tree of Segment Trees 3 | * Source: USACO Mowing the Field 4 | * Verification: ~ 5 | * Dependency: sparse segment tree 6 | */ 7 | 8 | const int SZ = 1<<17; 9 | 10 | // dependency: sparse segment tree 11 | 12 | template struct SegBit { 13 | node seg[SZ+1]; 14 | 15 | SegBit() { 16 | F0R(i,SZ+1) seg[i] = node(); 17 | } 18 | 19 | void upd(int x, int y, int v) { // add v 20 | for (x++;x <= SZ; x += (x&-x)) seg[x].upd(y,v); 21 | } 22 | 23 | T query(int x, int y1, int y2) { 24 | T ret = 0; 25 | for (;x > 0; x -= (x&-x)) ret += seg[x].query(y1,y2); 26 | return ret; 27 | } 28 | 29 | T query(int x1, int x2, int y1, int y2) { // query sum of rectangle 30 | return query(x2+1,y1,y2)-query(x1,y1,y2); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /referencepdf/content/data-structures/2D Range Queries (15.2)/2D SegTree (15.2).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: ? 3 | * Source: USACO Mowing the Field 4 | * Verification: ? 5 | * Dependency: sparse segment tree 6 | */ 7 | 8 | const int SZ = 1<<17; 9 | 10 | 11 | template struct Node { 12 | node seg; 13 | Node* c[2]; 14 | 15 | void upd(int x, int y, T v, int L = 0, int R = SZ-1) { // add v 16 | if (L == x && R == x) { 17 | seg.upd(y,v); 18 | return; 19 | } 20 | 21 | int M = (L+R)/2; 22 | if (x <= M) { 23 | if (!c[0]) c[0] = new Node(); 24 | c[0]->upd(x,y,v,L,M); 25 | } else { 26 | if (!c[1]) c[1] = new Node(); 27 | c[1]->upd(x,y,v,M+1,R); 28 | } 29 | 30 | seg.UPD(y,c[0] ? &c[0]->seg : NULL,c[1] ? &c[1]->seg : NULL); 31 | } 32 | 33 | T query(int x1, int x2, int y1, int y2, int L = 0, int R = SZ-1) { // query sum of rectangle 34 | if (x1 <= L && R <= x2) return seg.query(y1,y2); 35 | if (x2 < L || R < x1) return 0; 36 | 37 | int M = (L+R)/2; 38 | T t = 0; 39 | if (c[0]) t += c[0]->query(x1,x2,y1,y2,L,M); 40 | if (c[1]) t += c[1]->query(x1,x2,y1,y2,M+1,R); 41 | return t; 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /referencepdf/content/data-structures/2D Range Queries (15.2)/Merge-Sort Tree (15.2).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Similar to 2D segtree, less memory 3 | * For more complex queries use a customized treap 4 | * Verification: http://codeforces.com/contest/785/submission/33953058 5 | */ 6 | 7 | template struct mstree { 8 | Tree val[SZ+1]; // for offline queries use vector with binary search instead 9 | 10 | void upd(int x, int y, int t = 1) { // x-coordinate between 1 and SZ inclusive 11 | for (int X = x; X <= SZ; X += X&-X) { 12 | if (t == 1) val[X].insert({y,x}); 13 | else val[X].erase({y,x}); 14 | } 15 | } 16 | 17 | int query(int x, int y) { 18 | int t = 0; 19 | for (;x > 0; x -= x&-x) t += val[x].order_of_key({y,MOD}); 20 | return t; 21 | } 22 | 23 | int query(int lox, int hix, int loy, int hiy) { // query number of elements within a rectangle 24 | return query(hix,hiy)-query(lox-1,hiy) 25 | -query(hix,loy-1)+query(lox-1,loy-1); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /referencepdf/content/data-structures/LichaoSegTree.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: LiChao Segment Tree 3 | * Source: atatomir, misc 4 | * Verification: CSA Squared Ends 5 | */ 6 | 7 | struct Line { 8 | ll k,m; 9 | Line(ll _k, ll _m) { k = _k, m = _m; } 10 | Line() : Line(0,-INF) { } 11 | ll get(ll x) { return k*x+m; } 12 | bool majorize(Line X, int L, int R) { 13 | return get(L) >= X.get(L) && get(R) >= X.get(R); 14 | } 15 | }; 16 | 17 | struct lc { 18 | lc* c[2]; 19 | Line S; 20 | 21 | lc() { 22 | c[0] = c[1] = NULL; 23 | S = Line(); 24 | } 25 | 26 | void rm() { 27 | if (c[0]) c[0]->rm(); 28 | if (c[1]) c[1]->rm(); 29 | delete this; 30 | } 31 | 32 | void mc(int i) { 33 | if (!c[i]) c[i] = new lc(); 34 | } 35 | 36 | ll query(ll X, ll L, ll R) { 37 | ll ans = S.get(X), M = (L+R)/2; 38 | if (X <= M) return max(ans, c[0] ? c[0]->query(X,L,M): -INF); 39 | return max(ans, c[1] ? c[1]->query(X,M+1,R): -INF); 40 | } 41 | 42 | void modify(Line X, ll L, ll R) { 43 | if (X.majorize(S,L,R)) swap(X,S); 44 | if (S.majorize(X,L,R)) return; 45 | if (S.get(L) < X.get(L)) swap(X,S); 46 | 47 | ll M = (L+R)/2; 48 | if (X.get(M) >= S.get(M)) swap(X,S), mc(0), c[0]->modify(X,L,M); 49 | else mc(1), c[1]->modify(X,M+1,R); 50 | } 51 | 52 | void upd(Line X, ll lo, ll hi, ll L, ll R) { // untested 53 | if (R < hi || L < lo) return; 54 | if (lo <= L && R <= hi) { modify(X,L,R); return; } 55 | ll M = (L+R)/2; 56 | mc(0), c[0]->upd(X,lo,hi,L,M); 57 | mc(1), c[1]->upd(X,lo,hi,M+1,R); 58 | } 59 | }; -------------------------------------------------------------------------------- /referencepdf/content/data-structures/LineContainer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Given set of lines, computes greatest $y$-coordinate for any $x$ 3 | * Time: O(\log N) 4 | * Source: KACTL 5 | * https://codeforces.com/blog/entry/63823?#comment-477568 6 | * Verification: 7 | * CSA Squared Ends not working :( 8 | * https://codeforces.com/contest/1083/problem/E 9 | * https://atcoder.jp/contests/arc066/tasks/arc066_d 10 | */ 11 | 12 | struct Line { 13 | mutable ll k, m, p; // slope, y-intercept, last optimal x 14 | ll eval (ll x) { return k*x+m; } 15 | bool operator<(const Line& o) const { return k < o.k; } 16 | bool operator<(ll x) const { return p < x; } 17 | }; 18 | 19 | struct LC : multiset> { 20 | // for doubles, use inf = 1/.0, div(a,b) = a/b 21 | const ll inf = LLONG_MAX; 22 | ll div(ll a, ll b) { return a/b-((a^b) < 0 && a%b); } // floored division 23 | ll bet(const Line& x, const Line& y) { // last x such that first line is better 24 | if (x.k == y.k) return x.m >= y.m ? inf : -inf; 25 | return div(y.m-x.m,x.k-y.k); 26 | } 27 | bool isect(iterator x, iterator y) { // updates x->p, determines if y is unneeded 28 | if (y == end()) { x->p = inf; return 0; } 29 | x->p = bet(*x,*y); return x->p >= y->p; 30 | } 31 | void add(ll k, ll m) { 32 | auto z = insert({k,m,0}), y = z++, x = y; 33 | while (isect(y, z)) z = erase(z); 34 | if (x != begin() && isect(--x, y)) isect(x, y = erase(y)); 35 | while ((y = x) != begin() && (--x)->p >= y->p) isect(x, erase(y)); 36 | } 37 | ll query(ll x) { 38 | assert(!empty()); 39 | auto l = *lb(x); 40 | return l.k*x+l.m; 41 | } 42 | }; -------------------------------------------------------------------------------- /referencepdf/content/data-structures/LineContainerDeque.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: same as linecontainer but linear time given assumptions 3 | */ 4 | 5 | #include "LineContainer.h" 6 | 7 | struct LC0 : deque { // linear time w/ additional assumptions 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) { return a/b-((a^b) < 0 && a%b); } // floored division 11 | ll bet(const Line& x, const Line& y) { // last x such that first line is better 12 | if (x.k == y.k) return x.m >= y.m ? inf : -inf; 13 | return div(y.m-x.m,x.k-y.k); 14 | } 15 | 16 | void addBack(Line L) { // assume nonempty 17 | while (1) { 18 | auto a = back(); pop_back(); a.p = bet(a,L); 19 | if (size() && back().p >= a.p) continue; 20 | pb(a); break; 21 | } 22 | L.p = inf; pb(L); 23 | } 24 | void addFront(Line L) { 25 | while (1) { 26 | if (!size()) { L.p = inf; break; } 27 | if ((L.p = bet(L,front())) >= front().p) pop_front(); 28 | else break; 29 | } 30 | push_front(L); 31 | } 32 | void add(ll k, ll m) { // assume line goes to one end of deque 33 | if (!size() || k <= front().k) addFront({k,m,0}); 34 | else assert(k >= back().k), addBack({k,m,0}); 35 | } 36 | 37 | int ord = 0; // 1 = increasing, -1 = decreasing 38 | ll query(ll x) { 39 | assert(ord); 40 | if (ord == 1) { 41 | while (front().p < x) pop_front(); 42 | return front().eval(x); 43 | } else { 44 | while (size() > 1 && prev(prev(end()))->p >= x) pop_back(); 45 | return back().eval(x); 46 | } 47 | } 48 | }; 49 | -------------------------------------------------------------------------------- /referencepdf/content/data-structures/STL (5)/CustomHash.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: faster than standard unordered map 3 | * Source: 4 | * http://codeforces.com/blog/entry/62393 5 | * KACTL 6 | * Verification: http://codeforces.com/contest/966/problem/E 7 | * normal unordered map gets TLE 8 | */ 9 | 10 | struct chash { 11 | static uint64_t splitmix64(uint64_t x) { 12 | // http://xorshift.di.unimi.it/splitmix64.c 13 | x += 0x9e3779b97f4a7c15; 14 | x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; 15 | x = (x ^ (x >> 27)) * 0x94d049bb133111eb; 16 | return x ^ (x >> 31); 17 | } 18 | 19 | size_t operator()(uint64_t x) const { 20 | static const uint64_t FIXED_RANDOM = 21 | chrono::steady_clock::now() 22 | .time_since_epoch().count(); 23 | return splitmix64(x + FIXED_RANDOM); 24 | } 25 | }; 26 | 27 | template using um = unordered_map; 28 | template using ht = gp_hash_table; 29 | 30 | template V get(ht& u, K x) { 31 | return u.find(x) == end(u) ? 0 : u[x]; 32 | } -------------------------------------------------------------------------------- /referencepdf/content/data-structures/STL (5)/MapComparator (5.2).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: custom comparator for map / set 3 | * Source: StackOverflow 4 | */ 5 | 6 | struct cmp { 7 | bool operator()(const int& l, const int& r) const { 8 | return l > r; 9 | } 10 | }; 11 | 12 | set s; // F0R(i,10) s.insert(rand()); trav(i,s) ps(i); 13 | map m; 14 | -------------------------------------------------------------------------------- /referencepdf/content/data-structures/STL (5)/OrderStatisticTree.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: A set (not multiset!) with support for finding the $n$'th 3 | * element, and finding the index of an element. 4 | * Time: O(\log N) 5 | * Source: KACTL 6 | * Verification: many 7 | */ 8 | 9 | #include 10 | #include 11 | using namespace __gnu_pbds; 12 | 13 | template using Tree = tree, 14 | rb_tree_tag, tree_order_statistics_node_update>; 15 | // to get a map, change null_type 16 | 17 | #define ook order_of_key 18 | #define fbo find_by_order 19 | 20 | void treeExample() { 21 | Tree t, t2; t.insert(8); 22 | auto it = t.insert(10).f; 23 | assert(it == t.lb(9)); 24 | assert(t.ook(10) == 1); 25 | assert(t.ook(11) == 2); 26 | assert(*t.fbo(0) == 8); 27 | t.join(t2); // assuming T < T2 or T > T2, merge t2 into t 28 | } -------------------------------------------------------------------------------- /referencepdf/content/data-structures/STL (5)/Rope.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: insert element at $n$-th position, 3 | * cut a substring and re-insert somewhere else 4 | * Time: O(\log N) per operation? not well tested 5 | * Source: https://codeforces.com/blog/entry/10355 6 | * Verification: CEOI 2018 Day 2 Triangles 7 | */ 8 | 9 | #include 10 | 11 | using namespace __gnu_cxx; 12 | 13 | void ropeExample() { 14 | rope v(5, 0); 15 | F0R(i,sz(v)) v.mutable_reference_at(i) = i+1; // or push_back 16 | rope cur = v.substr(1,2); v.erase(1,2); 17 | F0R(i,sz(v)) cout << v[i] << " "; // 1 4 5 18 | cout << "\n"; 19 | v.insert(v.mutable_begin()+2,cur); 20 | for (rope::iterator it = v.mutable_begin(); it != v.mutable_end(); ++it) 21 | cout << *it << " "; // 1 4 2 3 5 22 | cout << "\n"; 23 | } -------------------------------------------------------------------------------- /referencepdf/content/data-structures/STL.md: -------------------------------------------------------------------------------- 1 | # STL 2 | 3 | ## 2 4 | 5 | * Types 6 | * Set, Multiset, Unordered Set 7 | * Map, Unordered Map (Hashmap) 8 | * see STL demo 9 | * Queue, Deque, Linked List 10 | * Priority Queue (Heap) 11 | * Vector 12 | * Stack 13 | * Bitset 14 | * Tutorial 15 | * CPH (4, Data Structures) 16 | * [C++ Reference](http://www.cplusplus.com/reference/stl/) 17 | * [CPC.2](https://github.com/SuprDewd/T-414-AFLV/tree/master/02_data_structures) 18 | * Problems (sorted by length) 19 | * [Beautiful Triplets](https://www.hackerearth.com/practice/algorithms/greedy/basics-of-greedy-algorithms/practice-problems/algorithm/mancunian-and-beautiful-triplets-30968257/) [](54) 20 | * [Polycarp's Phone Book](http://codeforces.com/contest/860/problem/B) [](56) 21 | * [Jury Marks](http://codeforces.com/contest/831/problem/C) [](67) 22 | * [Mahmoud & Ehab & Function](http://codeforces.com/contest/862/problem/E) [](74) 23 | * [Karen & Cards](http://codeforces.com/contest/815/problem/D) [](86) 24 | * [Tournament](http://codeforces.com/contest/878/problem/C) [](106) 25 | 26 | # 4 27 | 28 | * Order Statistics Tree 29 | * [Codeforces Tutorial](http://codeforces.com/blog/entry/11080) 30 | * Good to know for gold, sometimes can be used in place of BIT 31 | * Rope 32 | * [Codeforces Tutorial](https://codeforces.com/blog/entry/10355) 33 | -------------------------------------------------------------------------------- /referencepdf/content/data-structures/Static Range Queries (9.1)/Prefix Sums (9.1).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: calculates rectangle sums in constant time 3 | * Source: KACTL 4 | * Verification: POI 16 Ticket Inspector 5 | */ 6 | 7 | template struct PrefixSums { 8 | vector> sum; 9 | void init(const vector>& v) { 10 | int R = sz(v), C = sz(v[0]); 11 | sum.assign(R+1,vector(C+1)); 12 | F0R(i,R) F0R(j,C) 13 | sum[i+1][j+1] = v[i][j]+sum[i+1][j]+sum[i][j+1]-sum[i][j]; 14 | } 15 | T get(int X1, int X2, int Y1, int Y2) { 16 | X2 ++, Y2 ++; 17 | return sum[X2][Y2]-sum[X1][Y2] 18 | -sum[X2][Y1]+sum[X1][Y1]; 19 | } 20 | }; -------------------------------------------------------------------------------- /referencepdf/content/data-structures/Static Range Queries (9.1)/RMQ (9.1).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: 1D range minimum query 3 | * Source: KACTL 4 | * Verification: 5 | * https://cses.fi/problemset/stats/1647/ 6 | * http://wcipeg.com/problem/ioi1223 7 | * https://pastebin.com/ChpniVZL 8 | * Time: $O(N\log N)$ build, $O(1)$ query 9 | */ 10 | 11 | template struct RMQ { 12 | constexpr static int level(int x) { 13 | return 31-__builtin_clz(x); 14 | } // floor(log_2(x)) 15 | vector jmp; 16 | vector v; 17 | int comb(int a, int b) { 18 | return v[a] == v[b] ? min(a,b) : (v[a] < v[b] ? a : b); 19 | } // index of minimum 20 | 21 | void init(const vector& _v) { 22 | v = _v; jmp = {vi(sz(v))}; iota(all(jmp[0]),0); 23 | for (int j = 1; 1< struct RangeQuery { 8 | int n; 9 | T stor[SZ][32-__builtin_clz(SZ)], id = 1; 10 | vector a; 11 | 12 | T comb (T a, T b) { return mul(a,b); } // associative operation 13 | 14 | void fill(int l, int r, int ind) { 15 | if (ind < 0) return; 16 | int m = (l+r)/2; 17 | T prod = id; FORd(i,l,m) stor[i][ind] = prod = comb(a[i],prod); 18 | prod = id; FOR(i,m,r) stor[i][ind] = prod = comb(prod,a[i]); 19 | fill(l,m,ind-1); fill(m,r,ind-1); 20 | } 21 | 22 | void init() { 23 | n = 1; while ((1< hull3d(const vP3& A) { 20 | assert(sz(A) >= 4); 21 | vector> E(sz(A), vector(sz(A), {-1, -1})); 22 | #define E(x,y) E[f.x][f.y] 23 | vector FS; // faces 24 | auto mf = [&](int i, int j, int k, int l) { // make face 25 | P3 q = cross(A[j]-A[i],A[k]-A[i]); 26 | if (dot(q,A[l]) > dot(q,A[i])) q *= -1; // make sure q points outward 27 | F f{q, i, j, k}; 28 | E(a,b).ins(k); E(a,c).ins(j); E(b,c).ins(i); 29 | FS.pb(f); 30 | }; 31 | F0R(i,4) FOR(j,i+1,4) FOR(k,j+1,4) mf(i, j, k, 6-i-j-k); 32 | 33 | FOR(i,4,sz(A)) { 34 | F0R(j,sz(FS)) { 35 | F f = FS[j]; 36 | if (dot(f.q,A[i]) > dot(f.q,A[f.a])) { // face is visible, remove edges 37 | E(a,b).rem(f.c), E(a,c).rem(f.b), E(b,c).rem(f.a); 38 | swap(FS[j--], FS.back()); 39 | FS.pop_back(); 40 | } 41 | } 42 | F0R(j,sz(FS)) { // add faces with new point 43 | F f = FS[j]; 44 | #define C(a, b, c) if (E(a,b).cnt() != 2) mf(f.a, f.b, i, f.c); 45 | C(a, b, c); C(a, c, b); C(b, c, a); 46 | } 47 | } 48 | trav(it, FS) if (dot(cross(A[it.b]-A[it.a],A[it.c]-A[it.a]),it.q) <= 0) 49 | swap(it.c, it.b); 50 | return FS; 51 | } // computes hull where no four are coplanar 52 | 53 | T signedPolyVolume(const vP3& p, const vector& trilist) { 54 | T v = 0; 55 | trav(i,trilist) v += dot(cross(p[i.a],p[i.b]),p[i.c]); 56 | return v/6; 57 | } -------------------------------------------------------------------------------- /referencepdf/content/geometry (13)/3D/Point3D.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Basic 3D Geometry 3 | * Source: Own 4 | * Verification: 5 | * AMPPZ 2011 Cross Spider 6 | * https://atcoder.jp/contests/JAG2013Spring/tasks/icpc2013spring_h 7 | */ 8 | 9 | typedef ld T; 10 | 11 | namespace Point3D { 12 | typedef array P3; 13 | typedef vector vP3; 14 | 15 | T norm(const P3& x) { 16 | T sum = 0; F0R(i,sz(x)) sum += x[i]*x[i]; 17 | return sum; 18 | } 19 | T abs(const P3& x) { return sqrt(norm(x)); } 20 | 21 | P3& operator+=(P3& l, const P3& r) { F0R(i,3) l[i] += r[i]; return l; } 22 | P3& operator-=(P3& l, const P3& r) { F0R(i,3) l[i] -= r[i]; return l; } 23 | P3& operator*=(P3& l, const T& r) { F0R(i,3) l[i] *= r; return l; } 24 | P3& operator/=(P3& l, const T& r) { F0R(i,3) l[i] /= r; return l; } 25 | 26 | P3 operator+(P3 l, const P3& r) { return l += r; } 27 | P3 operator-(P3 l, const P3& r) { return l -= r; } 28 | P3 operator*(P3 l, const T& r) { return l *= r; } 29 | P3 operator*(const T& r, const P3& l) { return l*r; } 30 | P3 operator/(P3 l, const T& r) { return l /= r; } 31 | 32 | T dot(const P3& a, const P3& b) { 33 | T sum = 0; F0R(i,3) sum += a[i]*b[i]; 34 | return sum; 35 | } 36 | P3 cross(const P3& a, const P3& b) { 37 | return {a[1]*b[2]-a[2]*b[1], 38 | a[2]*b[0]-a[0]*b[2], 39 | a[0]*b[1]-a[1]*b[0]}; 40 | } 41 | 42 | bool isMult(const P3& a, const P3& b) { 43 | auto c = cross(a,b); 44 | F0R(i,sz(c)) if (c[i] != 0) return 0; 45 | return 1; 46 | } 47 | bool collinear(const P3& a, const P3& b, const P3& c) { return isMult(b-a,c-a); } 48 | bool coplanar(const P3& a, const P3& b, const P3& c, const P3& d) { 49 | return isMult(cross(b-a,c-a),cross(b-a,d-a)); 50 | } 51 | } 52 | 53 | using namespace Point3D; -------------------------------------------------------------------------------- /referencepdf/content/geometry (13)/Circles/Circumcenter.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: returns \{circumcenter,circumradius\} 3 | * Source: EGMO 4 | * Verification: see MEC 5 | */ 6 | 7 | #include "Point.h" 8 | 9 | pair ccCenter(P a, P b, P c) { 10 | b -= a; c -= a; 11 | P res = b*c*(conj(c)-conj(b))/(b*conj(c)-conj(b)*c); 12 | return {a+res,abs(res)}; 13 | } -------------------------------------------------------------------------------- /referencepdf/content/geometry (13)/Circles/MinEnclosingCircle.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: computes minimum enclosing circle 3 | * Time: expected $O(N)$ 4 | * Source: KACTL 5 | * Verification: USACO Camp 2019 Contest 2 #4 6 | */ 7 | 8 | #include "Circumcenter.h" 9 | 10 | pair mec(vP ps) { 11 | shuffle(all(ps), mt19937(time(0))); 12 | P o = ps[0]; T r = 0, EPS = 1 + 1e-8; 13 | F0R(i,sz(ps)) if (abs(o-ps[i]) > r*EPS) { 14 | o = ps[i], r = 0; 15 | F0R(j,i) if (abs(o-ps[j]) > r*EPS) { 16 | o = (ps[i]+ps[j])/2, r = abs(o-ps[i]); 17 | F0R(k,j) if (abs(o-ps[k]) > r*EPS) 18 | tie(o,r) = ccCenter(ps[i],ps[j],ps[k]); 19 | } 20 | } 21 | return {o,r}; 22 | } -------------------------------------------------------------------------------- /referencepdf/content/geometry (13)/Misc/ClosestPair (13.2).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: line sweep to find two closest points 3 | * Time: O(N\log N) 4 | * Source: Own 5 | * Verification: https://open.kattis.com/problems/closestpair2 6 | */ 7 | 8 | using namespace Point; 9 | 10 | pair solve(vP v) { 11 | pair> bes; bes.f = INF; 12 | set

S; int ind = 0; 13 | 14 | sort(all(v)); 15 | F0R(i,sz(v)) { 16 | if (i && v[i] == v[i-1]) return {v[i],v[i]}; 17 | for (; v[i].f-v[ind].f >= bes.f; ++ind) 18 | S.erase({v[ind].s,v[ind].f}); 19 | for (auto it = S.ub({v[i].s-bes.f,INF}); 20 | it != end(S) && it->f < v[i].s+bes.f; ++it) { 21 | P t = {it->s,it->f}; 22 | ckmin(bes,{abs(t-v[i]),{t,v[i]}}); 23 | } 24 | S.insert({v[i].s,v[i].f}); 25 | } 26 | 27 | return bes.s; 28 | } -------------------------------------------------------------------------------- /referencepdf/content/geometry (13)/Misc/DelaunaySlow.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Description: Delaunay Triangulation w/ Bowyer-Watson in O(n^2logn) 3 | * Source: Own 4 | * Verification: ICPC WF 2018 Panda Preserve 5 | */ 6 | 7 | namespace Delaunay { 8 | // use __int128 for better precision, if possible 9 | ld cross(cd b, cd c) { return (conj(b)*c).imag(); } 10 | ld cross(cd a, cd b, cd c) { return cross(b-a,c-a); } 11 | 12 | bool inCircle (cd a, cd b, cd c, cd d) { 13 | a -= d, b -= d, c -= d; 14 | ld x = norm(a)*cross(b,c)+norm(b)*cross(c,a) 15 | +norm(c)*cross(a,b); 16 | if (cross(a,b,c) < 0) x *= -1; 17 | return x > 0; 18 | } 19 | 20 | vector> triangulate(vcd v) { 21 | // works with cyclic quads 22 | // not when all points are collinear! 23 | // creates super-triangle, adjusts as necessary 24 | 25 | v.pb(cd(-1e5,-1e5)); v.pb(cd(1e5,0)); v.pb(cd(0,1e5)); // might not be sufficiently large 26 | 27 | vector> ret; 28 | ret.pb({sz(v)-3,sz(v)-2,sz(v)-1}); 29 | 30 | F0R(i,sz(v)-3) { 31 | map m; 32 | vector> tmp; 33 | trav(a,ret) { 34 | if (inCircle(v[a[0]],v[a[1]],v[a[2]],v[i])) 35 | m[{a[0],a[1]}] ++, m[{a[1],a[2]}] ++, m[{a[0],a[2]}] ++; 36 | else tmp.pb(a); 37 | } 38 | trav(a,m) if (a.s == 1) { 39 | array x = {a.f.f,a.f.s,i}; sort(all(x)); 40 | tmp.pb(x); 41 | } 42 | ret = tmp; 43 | } 44 | vector> tmp; 45 | trav(a,ret) if (a[2] < sz(v)-3) tmp.pb(a); 46 | return tmp; 47 | } 48 | 49 | void print(vcd x) { // produces asymptote code 50 | cout << "[asy]\n"; 51 | cout << "pair[] A = {"; 52 | bool done = 0; 53 | trav(a,x) { 54 | if (done) cout << ","; 55 | cout << a; done = 1; 56 | } 57 | cout << "};\n"; 58 | 59 | cout << "for (int i = 0; i < " << sz(x) << "; ++i) {\n\tdot(A[i]);\n}\n"; 60 | 61 | trav(b,triangulate(x)) cout << "draw(A[" << b[0] << "]--A[" << b[1] << "]--A[" << b[2] << "]--cycle);\n"; 62 | cout << "[/asy]\n"; 63 | } 64 | }; 65 | -------------------------------------------------------------------------------- /referencepdf/content/geometry (13)/Misc/MaxCollinear.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Compute the maximum number of points which lie on the same line in O(n^2logn) 3 | * Source: own 4 | * Verification: https://open.kattis.com/problems/maxcolinear 5 | */ 6 | 7 | pair getline(pi a, pi b) { 8 | pi z = {b.f-a.f,b.s-a.s}; 9 | swap(z.f,z.s); z.f *= -1; 10 | int g = __gcd(z.f,z.s); z.f /= g, z.s /= g; 11 | ckmin(z,{-z.f,-z.s}); 12 | return {z,z.f*a.f+z.s*a.s}; 13 | } 14 | 15 | int solve(vpi p) { 16 | int n = sz(p); 17 | map,int> m; 18 | F0R(i,n) FOR(j,i+1,n) m[getline(p[i],p[j])] ++; 19 | 20 | int mx = 0; trav(a,m) ckmax(mx,a.s); 21 | int ans = 0; FOR(i,1,n+1) if (i*(i-1)/2 <= mx) ans = i; 22 | return ans; 23 | } 24 | -------------------------------------------------------------------------------- /referencepdf/content/geometry (13)/Polygons/Area.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: computes area + the center of mass of 3 | * a polygon with constant mass per unit area 4 | * Time: O(N) 5 | * Source: http://codeforces.com/blog/entry/22175, KACTL 6 | * Verification: kattis polygonarea, VT HSPC 2018 Holiday Stars 7 | */ 8 | 9 | #include "Point.h" 10 | 11 | T area(const vP& v) { 12 | T area = 0; 13 | F0R(i,sz(v)) { 14 | int j = (i+1)%sz(v); T a = cross(v[i],v[j]); 15 | area += a; 16 | } 17 | return std::abs(area)/2; 18 | } 19 | P centroid(const vP& v) { 20 | P cen(0,0); T area = 0; // 2*signed area 21 | F0R(i,sz(v)) { 22 | int j = (i+1)%sz(v); T a = cross(v[i],v[j]); 23 | cen += a*(v[i]+v[j]); area += a; 24 | } 25 | return cen/area/(T)3; 26 | } -------------------------------------------------------------------------------- /referencepdf/content/geometry (13)/Polygons/ConvexHull (13.2).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Top-bottom convex hull 3 | * Time: O(N\log N) 4 | * Source: Wikibooks, KACTL 5 | * Verification: 6 | * https://open.kattis.com/problems/convexhull 7 | */ 8 | 9 | struct convexHull { 10 | set> dupChecker; 11 | vector> points; 12 | vector> dn, up, hull; 13 | 14 | convexHull() {} 15 | bool cw(pd o, pd a, pd b) { 16 | return ((a.f-o.f)*(b.s-o.s)-(a.s-o.s)*(b.f-o.f) <= 0); 17 | } 18 | void addPoint(pair p) { 19 | if(dupChecker.count(p)) return; 20 | points.pb(p); 21 | dupChecker.insert(p); 22 | } 23 | void addPoint(ld x, ld y) { 24 | addPoint(mp(x,y)); 25 | } 26 | void build() { 27 | sort(points.begin(), points.end()); 28 | if(sz(points) < 3) { 29 | for(pair p: points) { 30 | dn.pb(p); 31 | hull.pb(p); 32 | } 33 | M00d(i, sz(points)) { 34 | up.pb(points[i]); 35 | } 36 | } else { 37 | for(int i = 0; i < (int)points.size(); i++) { 38 | while(dn.size() >= 2 && cw(dn[dn.size()-2], dn[dn.size()-1], points[i])) { 39 | dn.erase(dn.end()-1); 40 | } 41 | dn.push_back(points[i]); 42 | } 43 | for(int i = (int)points.size()-1; i >= 0; i--) { 44 | while(up.size() >= 2 && cw(up[up.size()-2], up[up.size()-1], points[i])) { 45 | up.erase(up.end()-1); 46 | } 47 | up.push_back(points[i]); 48 | } 49 | sort(dn.begin(), dn.end()); 50 | sort(up.begin(), up.end()); 51 | 52 | for(int i = 0; i < up.size()-1; i++) hull.pb(up[i]); 53 | for(int i = sz(dn)-1; i > 0; i--) hull.pb(dn[i]); 54 | } 55 | } 56 | }; 57 | -------------------------------------------------------------------------------- /referencepdf/content/geometry (13)/Polygons/InPoly.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: tests whether a point is inside, on, or outside the perimeter of any polygon 3 | * Time: O(N) 4 | * Verification: https://open.kattis.com/problems/pointinpolygon 5 | */ 6 | 7 | #include "Point.h" 8 | 9 | string inPoly(const vP& p, P z) { 10 | int n = sz(p), ans = 0; 11 | F0R(i,n) { 12 | P x = p[i], y = p[(i+1)%n]; 13 | if (onSeg(z,x,y)) return "on"; 14 | if (x.s > y.s) swap(x,y); 15 | if (x.s <= z.s && y.s > z.s && cross(z,x,y) > 0) ans ^= 1; 16 | } 17 | return ans ? "in" : "out"; 18 | } 19 | -------------------------------------------------------------------------------- /referencepdf/content/geometry (13)/Polygons/PolyDiameter.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: computes longest distance between two points in $P$ 3 | * Time: $O(N)$ given convex hull 4 | * Source: KACTL 5 | * Verification: 6 | * https://open.kattis.com/problems/roberthood 7 | */ 8 | 9 | #include "ConvexHull.h" 10 | 11 | ld diameter(vP P) { // rotating calipers 12 | P = hull(P); 13 | int n = sz(P), ind = 1; ld ans = 0; 14 | F0R(i,n) 15 | for (int j = (i+1)%n;;ind = (ind+1)%n) { 16 | ckmax(ans,abs(P[i]-P[ind])); 17 | if (cross(P[j]-P[i],P[(ind+1)%n]-P[ind]) <= 0) break; 18 | } 19 | return ans; 20 | } -------------------------------------------------------------------------------- /referencepdf/content/geometry (13)/Primitives/AngleCmp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: sorts points according to atan2 3 | * Verification: ? 4 | */ 5 | 6 | #include "Point.h" 7 | 8 | template int half(pair x) { return mp(x.s,x.f) > mp((T)0,(T)0); } 9 | bool angleCmp(P a, P b) { 10 | int A = half(a), B = half(b); 11 | return A == B ? cross(a,b) > 0 : A < B; 12 | } 13 | -------------------------------------------------------------------------------- /referencepdf/content/geometry (13)/Primitives/LineDist.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: computes distance between $P$ and line $AB$ 3 | * Source: own 4 | * Verification: ? 5 | */ 6 | 7 | #include "Point.h" 8 | 9 | T lineDist(P p, P a, P b) { return abs(cross(p,a,b))/abs(a-b); } -------------------------------------------------------------------------------- /referencepdf/content/geometry (13)/Primitives/LineIntersect.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: computes the intersection point(s) of lines $AB$, $CD;$ 3 | * returns {-1,{0,0}} if infinitely many, {0,{0,0}} if none, 4 | * {1,x} if x is the unique point 5 | * Source: KACTL 6 | * Verification: ? 7 | */ 8 | 9 | #include "Point.h" 10 | 11 | P extension(P a, P b, P c, P d) { 12 | T x = cross(a,b,c), y = cross(a,b,d); 13 | return (d*x-c*y)/(x-y); 14 | } 15 | pair lineIntersect(P a, P b, P c, P d) { 16 | if (cross(b-a,d-c) == 0) return {-(cross(a,c,d) == 0),P(0,0)}; 17 | return {1,extension(a,b,c,d)}; 18 | } -------------------------------------------------------------------------------- /referencepdf/content/geometry (13)/Primitives/Point.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Easy Geo 3 | * Source: http://codeforces.com/blog/entry/22175, KACTL 4 | * Verification: various 5 | */ 6 | 7 | typedef ld T; 8 | template int sgn(T x) { return (x > 0) - (x < 0); } 9 | 10 | namespace Point { 11 | typedef pair P; 12 | typedef vector

vP; 13 | 14 | P dir(T ang) { 15 | auto c = exp(ang*complex(0,1)); 16 | return P(c.real(),c.imag()); 17 | } 18 | 19 | T norm(P x) { return x.f*x.f+x.s*x.s; } 20 | T abs(P x) { return sqrt(norm(x)); } 21 | T angle(P x) { return atan2(x.s,x.f); } 22 | P conj(P x) { return P(x.f,-x.s); } 23 | 24 | P operator+(const P& l, const P& r) { return P(l.f+r.f,l.s+r.s); } 25 | P operator-(const P& l, const P& r) { return P(l.f-r.f,l.s-r.s); } 26 | P operator*(const P& l, const T& r) { return P(l.f*r,l.s*r); } 27 | P operator*(const T& l, const P& r) { return r*l; } 28 | P operator/(const P& l, const T& r) { return P(l.f/r,l.s/r); } 29 | P operator*(const P& l, const P& r) { return P(l.f*r.f-l.s*r.s,l.s*r.f+l.f*r.s); } 30 | P operator/(const P& l, const P& r) { return l*conj(r)/norm(r); } 31 | 32 | P& operator+=(P& l, const P& r) { return l = l+r; } 33 | P& operator-=(P& l, const P& r) { return l = l-r; } 34 | P& operator*=(P& l, const T& r) { return l = l*r; } 35 | P& operator/=(P& l, const T& r) { return l = l/r; } 36 | P& operator*=(P& l, const P& r) { return l = l*r; } 37 | P& operator/=(P& l, const P& r) { return l = l/r; } 38 | 39 | P unit(P x) { return x/abs(x); } 40 | T dot(P a, P b) { return (conj(a)*b).f; } 41 | T cross(P a, P b) { return (conj(a)*b).s; } 42 | T cross(P p, P a, P b) { return cross(a-p,b-p); } 43 | P rotate(P a, T b) { return a*P(cos(b),sin(b)); } 44 | 45 | P reflect(P p, P a, P b) { return a+conj((p-a)/(b-a))*(b-a); } 46 | P foot(P p, P a, P b) { return (p+reflect(p,a,b))/(T)2; } 47 | bool onSeg(P p, P a, P b) { return cross(a,b,p) == 0 && dot(p-a,p-b) <= 0; } 48 | }; 49 | 50 | using namespace Point; -------------------------------------------------------------------------------- /referencepdf/content/geometry (13)/Primitives/SegDist.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: computes distance between $P$ and line segment $AB$ 3 | * Source: own 4 | * Verification: https://open.kattis.com/problems/segmentdistance 5 | */ 6 | 7 | #include "lineDist.h" 8 | 9 | T segDist(P p, P a, P b) { 10 | if (dot(p-a,b-a) <= 0) return abs(p-a); 11 | if (dot(p-b,a-b) <= 0) return abs(p-b); 12 | return lineDist(p,a,b); 13 | } -------------------------------------------------------------------------------- /referencepdf/content/geometry (13)/Primitives/SegIntersect.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: computes the intersection point(s) of line segments $AB$, $CD$ 3 | * Source: KACTL 4 | * Verification: https://open.kattis.com/problems/segmentintersection 5 | */ 6 | 7 | #include "Point.h" 8 | 9 | vP segIntersect(P a, P b, P c, P d) { 10 | T x = cross(a,b,c), y = cross(a,b,d); 11 | T X = cross(c,d,a), Y = cross(c,d,b); 12 | if (sgn(x)*sgn(y) < 0 && sgn(X)*sgn(Y) < 0) return {(d*x-c*y)/(x-y)}; 13 | set

s; 14 | if (onSeg(a,c,d)) s.insert(a); 15 | if (onSeg(b,c,d)) s.insert(b); 16 | if (onSeg(c,a,b)) s.insert(c); 17 | if (onSeg(d,a,b)) s.insert(d); 18 | return {all(s)}; 19 | } -------------------------------------------------------------------------------- /referencepdf/content/geometry (13)/chapter.tex: -------------------------------------------------------------------------------- 1 | \chapter{Geometry} 2 | 3 | \section{Primitives} 4 | \kactlimport{Primitives/Point.h} 5 | \kactlimport{Primitives/AngleCmp.h} 6 | \kactlimport{Primitives/LineDist.h} 7 | \kactlimport{Primitives/SegDist.h} 8 | \kactlimport{Primitives/LineIntersect.h} 9 | \kactlimport{Primitives/SegIntersect.h} 10 | 11 | \section{Polygons} 12 | \kactlimport{Polygons/Area.h} 13 | \kactlimport{Polygons/InPoly.h} 14 | \kactlimport{Polygons/ConvexHull (13.2).h} 15 | \kactlimport{Polygons/PolyDiameter.h} 16 | 17 | \section{Circles} 18 | \kactlimport{Circles/Circles.h} 19 | \kactlimport{Circles/Circumcenter.h} 20 | \kactlimport{Circles/MinEnclosingCircle.h} 21 | 22 | \section{Misc} 23 | \kactlimport{Misc/ClosestPair (13.2).h} 24 | \kactlimport{Misc/DelaunayFast.h} 25 | 26 | \section{3D} 27 | \kactlimport{3D/Point3D.h} 28 | \kactlimport{3D/Hull3D.h} -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/DFS/2SAT (12.1).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: ? 3 | * Source: KACTL 4 | * Verification: https://codeforces.com/contest/1007/problem/D 5 | */ 6 | 7 | #include "SCC.h" 8 | 9 | template struct TwoSat { 10 | SCC<2*SZ> S; 11 | bitset ans; 12 | int N = 0; 13 | int addVar() { return N++; } 14 | 15 | void either(int x, int y) { 16 | x = max(2*x,-1-2*x), y = max(2*y,-1-2*y); 17 | S.addEdge(x^1,y); S.addEdge(y^1,x); 18 | } 19 | void implies(int x, int y) { either(~x,y); } 20 | void setVal(int x) { either(x,x); } 21 | void atMostOne(const vi& li) { 22 | if (sz(li) <= 1) return; 23 | int cur = ~li[0]; 24 | FOR(i,2,sz(li)) { 25 | int next = addVar(); 26 | either(cur,~li[i]); 27 | either(cur,next); 28 | either(~li[i],next); 29 | cur = ~next; 30 | } 31 | either(cur,~li[1]); 32 | } 33 | 34 | bool solve(int _N) { 35 | if (_N != -1) N = _N; 36 | S.init(2*N); 37 | for (int i = 0; i < 2*N; i += 2) 38 | if (S.comp[i] == S.comp[i^1]) return 0; 39 | reverse(all(S.allComp)); 40 | vi tmp(2*N); 41 | trav(i,S.allComp) if (tmp[i] == 0) 42 | tmp[i] = 1, tmp[S.comp[i^1]] = -1; 43 | F0R(i,N) if (tmp[S.comp[2*i]] == 1) ans[i] = 1; 44 | return 1; 45 | } 46 | }; -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/DFS/BCC (12.4).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: computes biconnected components 3 | * Time: O(N+M) 4 | * Source: GeeksForGeeks (corrected) 5 | * Verification: USACO December 2017, Push a Box 6 | * https://pastebin.com/yUWuzTH8 7 | */ 8 | 9 | template struct BCC { 10 | int N; 11 | vpi adj[SZ], ed; 12 | void addEdge(int u, int v) { 13 | adj[u].pb({v,sz(ed)}), adj[v].pb({u,sz(ed)}); 14 | ed.pb({u,v}); 15 | } 16 | 17 | int disc[SZ]; 18 | vi st; vector fin; 19 | int bcc(int u, int p = -1) { // return lowest disc 20 | static int ti = 0; 21 | disc[u] = ++ti; int low = disc[u]; 22 | int child = 0; 23 | trav(i,adj[u]) if (i.s != p) 24 | if (!disc[i.f]) { 25 | child ++; st.pb(i.s); 26 | int LOW = bcc(i.f,i.s); ckmin(low,LOW); 27 | // disc[u] < LOW -> bridge 28 | if (disc[u] <= LOW) { 29 | // if (p != -1 || child > 1) -> u is articulation point 30 | vi tmp; while (st.back() != i.s) tmp.pb(st.back()), st.pop_back(); 31 | tmp.pb(st.back()), st.pop_back(); 32 | fin.pb(tmp); 33 | } 34 | } else if (disc[i.f] < disc[u]) { 35 | ckmin(low,disc[i.f]); 36 | st.pb(i.s); 37 | } 38 | return low; 39 | } 40 | 41 | void init(int _N) { 42 | N = _N; F0R(i,N) disc[i] = 0; 43 | F0R(i,N) if (!disc[i]) bcc(i); // st should be empty after each iteration 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/DFS/EulerPath (12.2).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Eulerian Path for both directed and undirected graphs 3 | * Time: $O(N+M)$ 4 | * Source: 5 | * USACO Training 6 | * MIT ICPC Notebook 7 | * Verification: 8 | * directed -> https://open.kattis.com/problems/eulerianpath 9 | * undirected -> USACO Training 3.3, Riding the Fences 10 | */ 11 | 12 | template struct Euler { 13 | int N, M = 0; 14 | vpi adj[SZ]; 15 | vpi::iterator its[SZ]; 16 | vector used; 17 | 18 | void addEdge(int a, int b) { 19 | if (directed) adj[a].pb({b,M}); 20 | else adj[a].pb({b,M}), adj[b].pb({a,M}); 21 | used.pb(0); M ++; 22 | } 23 | 24 | vpi solve(int _N, int src = 1) { 25 | N = _N; 26 | FOR(i,1,N+1) its[i] = begin(adj[i]); 27 | vector> ret, s = {{{src,-1},-1}}; 28 | while (sz(s)) { 29 | int x = s.back().f.f; 30 | auto& it = its[x], end = adj[x].end(); 31 | while (it != end && used[it->s]) it ++; 32 | if (it == end) { 33 | if (sz(ret) && ret.back().f.s != s.back().f.f) return {}; // path isn't valid 34 | ret.pb(s.back()), s.pop_back(); 35 | } else { s.pb({{it->f,x},it->s}); used[it->s] = 1; } 36 | } 37 | if (sz(ret) != M+1) return {}; 38 | vpi ans; trav(t,ret) ans.pb({t.f.f,t.s}); 39 | reverse(all(ans)); return ans; 40 | } 41 | }; -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/DFS/SCC (12.1).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Kosaraju's Algorithm: 3 | * DFS two times to generate SCCs in topological order 4 | * Time: $O(N+M)$ 5 | * Source: Wikipedia 6 | * Verification: POI 8 peaceful commission 7 | */ 8 | 9 | template struct SCC { 10 | int N, comp[SZ]; 11 | vi adj[SZ], radj[SZ], todo, allComp; 12 | bitset visit; 13 | void addEdge(int a, int b) { adj[a].pb(b), radj[b].pb(a); } 14 | 15 | void dfs(int v) { 16 | visit[v] = 1; 17 | trav(w,adj[v]) if (!visit[w]) dfs(w); 18 | todo.pb(v); 19 | } 20 | void dfs2(int v, int val) { 21 | comp[v] = val; 22 | trav(w,radj[v]) if (comp[w] == -1) dfs2(w,val); 23 | } 24 | 25 | void init(int _N) { // fills allComp 26 | N = _N; 27 | F0R(i,N) comp[i] = -1, visit[i] = 0; 28 | F0R(i,N) if (!visit[i]) dfs(i); 29 | reverse(all(todo)); // now todo stores vertices in order of topological sort 30 | trav(i,todo) if (comp[i] == -1) dfs2(i,i), allComp.pb(i); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/DFS/TopoSort.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: sorts vertices such that if there exists an edge x->y, then x goes before y 3 | * Source: KACTL 4 | * Verification: https://open.kattis.com/problems/quantumsuperposition 5 | */ 6 | 7 | template struct TopoSort { 8 | int N, in[SZ]; 9 | vi res, adj[SZ]; 10 | void ae(int x, int y) { adj[x].pb(y), in[y] ++; } 11 | bool sort(int _N) { 12 | N = _N; queue todo; 13 | FOR(i,1,N+1) if (!in[i]) todo.push(i); 14 | while (sz(todo)) { 15 | int x = todo.front(); todo.pop(); res.pb(x); 16 | trav(i,adj[x]) if (!(--in[i])) todo.push(i); 17 | } 18 | return sz(res) == N; 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/Flows (12.3)/Dinic.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: faster flow 3 | * Time: $O(N^2M)$ flow, $O(M\sqrt N)$ bipartite matching 4 | * Source: GeeksForGeeks, Chilli 5 | * Verification: RMI 2017 Day 1 Fashion 6 | * https://pastebin.com/VJxTvEg1 7 | */ 8 | 9 | template struct Dinic { 10 | typedef ll F; // flow type 11 | struct Edge { int to, rev; F flow, cap; }; 12 | 13 | int N,s,t; 14 | vector adj[SZ]; 15 | typename vector::iterator cur[SZ]; 16 | void addEdge(int u, int v, F cap) { 17 | assert(cap >= 0); // don't try smth dumb 18 | Edge a{v, sz(adj[v]), 0, cap}, b{u, sz(adj[u]), 0, 0}; 19 | adj[u].pb(a), adj[v].pb(b); 20 | } 21 | 22 | int level[SZ]; 23 | bool bfs() { // level = shortest distance from source 24 | // after computing flow, edges {u,v} such that level[u] \neq -1, level[v] = -1 are part of min cut 25 | M00(i,N) level[i] = -1, cur[i] = begin(adj[i]); 26 | queue q({s}); level[s] = 0; 27 | while (sz(q)) { 28 | int u = q.front(); q.pop(); 29 | for(Edge e: adj[u]) if (level[e.to] < 0 && e.flow < e.cap) 30 | q.push(e.to), level[e.to] = level[u]+1; 31 | } 32 | return level[t] >= 0; 33 | } 34 | F sendFlow(int v, F flow) { 35 | if (v == t) return flow; 36 | for (; cur[v] != end(adj[v]); cur[v]++) { 37 | Edge& e = *cur[v]; 38 | if (level[e.to] != level[v]+1 || e.flow == e.cap) continue; 39 | auto df = sendFlow(e.to,min(flow,e.cap-e.flow)); 40 | if (df) { // saturated at least one edge 41 | e.flow += df; adj[e.to][e.rev].flow -= df; 42 | return df; 43 | } 44 | } 45 | return 0; 46 | } 47 | F maxFlow(int _N, int _s, int _t) { 48 | N = _N, s = _s, t = _t; if (s == t) return -1; 49 | F tot = 0; 50 | while (bfs()) while (auto df = sendFlow(s,numeric_limits::max())) tot += df; 51 | return tot; 52 | } 53 | }; 54 | -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/Flows (12.3)/Flows.md: -------------------------------------------------------------------------------- 1 | # Flows 2 | 3 | ## 4 4 | * Maximum Flow 5 | * Tutorial 6 | * CPH (20, Flows & Cuts) 7 | * Topics 8 | * Edmonds-Karp Algorithm 9 | * Min-Cut Max-Flow Theorem 10 | * [Closure Problem](https://en.wikipedia.org/wiki/Closure_problem) 11 | * Problems 12 | * [Goods Transportation](http://codeforces.com/problemset/problem/724/E) [](52) 13 | * [MUL](http://arc085.contest.atcoder.jp/tasks/arc085_c) [](67) 14 | * [Fashion](https://csacademy.com/contest/rmi-2017-day-1/task/fashion/statement/) [](95) 15 | * [Fast Flow](http://www.spoj.com/problems/FASTFLOW/) [](107) 16 | * [Card Game](http://codeforces.com/problemset/problem/808/F) [](135) 17 | 18 | ## 5 19 | * Faster Max Flow 20 | * Hopcroft-Karp Bipartite Matching 21 | * Dinic's Algorithm 22 | * Push-Relabel 23 | * [Fast Flow Implementation - Chilli](https://codeforces.com/blog/entry/66006) 24 | * Minimum Cost Flow 25 | * Tutorial 26 | * [TopCoder](https://www.topcoder.com/community/data-science/data-science-tutorials/minimum-cost-flow-part-two-algorithms/) 27 | * [Johnson's Algorithm](https://en.wikipedia.org/wiki/Johnson%27s_algorithm) 28 | * Problems 29 | * [April Fool's Problem](http://codeforces.com/contest/802/problem/N) 30 | * [A2OJ](https://a2oj.com/category?ID=662) 31 | 32 | ## 6 33 | * [Max Flow w/ Lower Bounds](https://pdfs.semanticscholar.org/03a2/785783f43202925da70ae842eeda9cebd77e.pdf) 34 | * [Captain America](https://codeforces.com/contest/704/problem/D) 35 | * [Incorrect Flow](https://codeforces.com/contest/708/problem/D) 36 | -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/Fundamentals/DSU (7.6).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: ? 3 | * Time: $O(N\alpha(N))$ 4 | * Source: CSAcademy, KACTL 5 | * Verification: USACO superbull 6 | */ 7 | 8 | template struct DSU { 9 | int par[SZ]; 10 | int size[SZ]; 11 | DSU() { 12 | M00(i, SZ) par[i] = i, size[i] = 1; 13 | } 14 | int get(int node) { 15 | if(par[node] != node) par[node] = get(par[node]); 16 | return par[node]; 17 | } 18 | bool connected(int n1, int n2) { 19 | return (get(n1) == get(n2)); 20 | } 21 | int sz(int node) { 22 | return size[get(node)]; 23 | } 24 | void unite(int n1, int n2) { 25 | n1 = get(n1); 26 | n2 = get(n2); 27 | if(n1 == n2) return; 28 | if(rand()%2) { 29 | par[n1] = n2; 30 | size[n2] += size[n1]; 31 | } else { 32 | par[n2] = n1; 33 | size[n1] += size[n2]; 34 | } 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/Fundamentals/DSUrb (15.5).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Disjoint Set Union with Rollback 3 | * Source: see DSU 4 | * Verification: https://codeforces.com/contest/1140/problem/F 5 | */ 6 | 7 | struct DSUrb { 8 | vi e; 9 | void init(int n) { e = vi(n,-1); } 10 | int get(int x) { return e[x] < 0 ? x : get(e[x]); } // path compression 11 | bool sameSet(int a, int b) { return get(a) == get(b); } 12 | int size(int x) { return -e[get(x)]; } 13 | vector> mod; 14 | bool unite(int x, int y) { // union-by-rank 15 | x = get(x), y = get(y); 16 | if (x == y) { 17 | mod.pb({MOD,MOD,MOD,MOD}); 18 | return 0; 19 | } 20 | if (e[x] > e[y]) swap(x,y); 21 | mod.pb({x,y,e[x],e[y]}); 22 | e[x] += e[y]; e[y] = x; 23 | return 1; 24 | } 25 | void rollback() { 26 | auto a = mod.back(); mod.pop_back(); 27 | if (a[0] != MOD) e[a[0]] = a[2], e[a[1]] = a[3]; 28 | } 29 | }; -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/Fundamentals/Dijkstra.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Dijkstra's algorithm for shortest path 3 | * Time: O(E\log V) 4 | * Source: lmao 5 | * Verification: lmao imagine verifying 6 | */ 7 | 8 | template struct dijkstra { 9 | const int inf = 1e8; 10 | vector adj[SZ]; 11 | bool vis[SZ]; 12 | int d[SZ]; 13 | 14 | void addEdge(int u, int v, int l) { 15 | adj[u].pb(mp(v, l)); 16 | } 17 | int dist(int v) { 18 | return d[v]; 19 | } 20 | void build(int u) { 21 | priority_queue, greater> pq; 22 | M00(i, SZ) d[i] = inf; 23 | d[u] = 0; 24 | pq.push(mp(0, u)); 25 | while(!pq.empty()) { 26 | pi t = pq.top(); pq.pop(); 27 | if(vis[t.s]) continue; 28 | vis[t.s] = 1; 29 | 30 | for(auto v: adj[t.s]) { 31 | if(d[v.f] > d[t.s] + v.s) { 32 | d[v.f] = d[t.s] + v.s; 33 | pq.push(mp(d[t.s]+v.s, v.f)); 34 | } 35 | } 36 | } 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/Fundamentals/DijkstraV2.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Dijkstra's algorithm for shortest path 3 | * Time: O(V^2) 4 | * Source: lmao 5 | * Verification: lmao imagine verifying 6 | */ 7 | 8 | template struct dijkstra { 9 | vector> adj[SZ]; 10 | bool vis[SZ]; 11 | ll d[SZ]; 12 | 13 | void addEdge(int u, int v, ll l) { 14 | adj[u].PB(MP(v, l)); 15 | } 16 | ll dist(int v) { 17 | return d[v]; 18 | } 19 | void build(int u) { 20 | M00(i, SZ) vis[i] = 0; 21 | M00(i, SZ) d[i] = 1e17; 22 | d[u] = 0; 23 | while(1) { 24 | pair t = MP(1e17, -1); 25 | M00(i, SZ) if(!vis[i]) t = min(t, MP(d[i], i)); 26 | if(t.S == -1) return; 27 | vis[t.S] = 1; 28 | 29 | for(auto& v: adj[t.S]) if(!vis[v.F]) { 30 | if(d[v.F] > d[t.S] + v.S) d[v.F] = d[t.S] + v.S; 31 | } 32 | } 33 | } 34 | }; 35 | -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/Fundamentals/DynaCon.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: offline dynamic connectivity 3 | * Source: own 4 | * Verification: https://codeforces.com/contest/1140/problem/F 5 | */ 6 | 7 | #include "DSUrb.h" 8 | 9 | template struct DynaCon { // answer dynamic connectivity queries offline 10 | DSUrb D; 11 | vpi seg[2*SZ]; 12 | void upd(int l, int r, pi p) { // add edge p to all times in interval [l, r] 13 | r++; 14 | for (l += SZ, r += SZ; l < r; l >>= 1, r >>= 1) { 15 | if (l&1) seg[l++].pb(p); 16 | if (r&1) seg[--r].pb(p); 17 | } 18 | } 19 | void process(int ind) { 20 | trav(t,seg[ind]) D.unite(t.f,t.s); 21 | if (ind >= SZ) { 22 | // do stuff with D at time ind-SZ 23 | } else process(2*ind), process(2*ind+1); 24 | trav(t,seg[ind]) D.rollback(); 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/Fundamentals/FloydWarshall.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Floyd Warshall's algorithm for all pairs shortest path 3 | * Time: O(V^3) 4 | * Source: lmao 5 | * Verification: lmao imagine verifying 6 | */ 7 | 8 | /* 9 | let dist be a |V| * |V| array of minimum distances initialized to inf 10 | for each edge (u, v) do 11 | dist[u][v] <- w(u, v) // The weight of the edge (u, v) 12 | for each vertex v do 13 | dist[v][v] <- 0 14 | for k from 1 to |V| 15 | for i from 1 to |V| 16 | for j from 1 to |V| 17 | if dist[i][j] > dist[i][k] + dist[k][j] 18 | dist[i][j] <- dist[i][k] + dist[k][j] 19 | end if 20 | */ 21 | -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/Fundamentals/MST (7.6).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Kruskal's algorithm for minimum spanning tree 3 | * Time: O(M\log M) 4 | * Source: CSAcademy, KACTL 5 | * Verification: USACO superbull 6 | */ 7 | 8 | #include "DSU.h" 9 | 10 | template T kruskal(int n, vector> edge) { 11 | sort(all(edge)); 12 | T ans = 0; DSU D; D.init(n); 13 | trav(a,edge) if (D.unite(a.s.f,a.s.s)) ans += a.f; // edge is in MST 14 | return ans; 15 | } 16 | -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/Matching/DFSmatch.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: naive bipartite matching 3 | * Time: O(NM) 4 | * Source: own 5 | * Verification: USACO Training unmatch 6 | */ 7 | 8 | template struct MaxMatch { 9 | int N, flow = 0, match[SZ], rmatch[SZ]; 10 | bitset vis; 11 | vi adj[SZ]; 12 | MaxMatch() { 13 | memset(match,0,sizeof match); 14 | memset(rmatch,0,sizeof rmatch); 15 | } 16 | 17 | void connect(int a, int b, bool c = 1) { 18 | if (c) match[a] = b, rmatch[b] = a; 19 | else match[a] = rmatch[b] = 0; 20 | } 21 | bool dfs(int x) { 22 | if (!x) return 1; 23 | if (vis[x]) return 0; 24 | vis[x] = 1; 25 | trav(t,adj[x]) if (t != match[x] && dfs(rmatch[t])) 26 | return connect(x,t),1; 27 | return 0; 28 | } 29 | void tri(int x) { vis.reset(); flow += dfs(x); } 30 | void init(int _N) { 31 | N = _N; FOR(i,1,N+1) if (!match[i]) tri(i); 32 | } 33 | }; -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/Matching/Hungarian.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: finds min cost to complete n jobs w/ m workers 3 | * each worker is assigned to at most one job (n <= m) 4 | * Time: ? 5 | * Source: https://github.com/mpfeifer1/Kattis/blob/master/cordonbleu.cpp 6 | * Verification: https://www.spoj.com/problems/BABY/ 7 | * also see https://codeforces.com/blog/entry/63701 8 | */ 9 | 10 | int HungarianMatch(const vector& a) { // cost array, negative values are ok 11 | int n = sz(a)-1, m = sz(a[0])-1; // jobs 1..n, workers 1..m 12 | vi u(n+1), v(m+1), p(m+1); // p[j] -> job picked by worker j 13 | FOR(i,1,n+1) { // find alternating path with job i 14 | p[0] = i; int j0 = 0; 15 | vi dist(m+1, MOD), pre(m+1,-1); // dist, previous vertex on shortest path 16 | vector done(m+1, false); 17 | do { 18 | done[j0] = true; 19 | int i0 = p[j0], j1; int delta = MOD; 20 | FOR(j,1,m+1) if (!done[j]) { 21 | auto cur = a[i0][j]-u[i0]-v[j]; 22 | if (cur < dist[j]) dist[j] = cur, pre[j] = j0; 23 | if (dist[j] < delta) delta = dist[j], j1 = j; 24 | } 25 | F0R(j,m+1) // just dijkstra with potentials 26 | if (done[j]) u[p[j]] += delta, v[j] -= delta; 27 | else dist[j] -= delta; 28 | j0 = j1; 29 | } while (p[j0]); 30 | do { // update values on alternating path 31 | int j1 = pre[j0]; 32 | p[j0] = p[j1]; 33 | j0 = j1; 34 | } while (j0); 35 | } 36 | return -v[0]; // min cost 37 | } -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/Misc/DirectedMstKACTL.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: computes weight of minimum directed spanning tree 3 | * Time: O(M\log M) 4 | * Source: KACTL 5 | * https://courses.cs.washington.edu/courses/cse490u/17wi/slides/CLE.pdf 6 | * Verification: https://open.kattis.com/problems/fastestspeedrun 7 | */ 8 | 9 | #include "DSU.h" 10 | 11 | struct Edge { int a, b; ll w; }; 12 | struct Node { /// lazy skew heap node 13 | Edge key; 14 | Node *l, *r; 15 | ll delta; 16 | void prop() { 17 | key.w += delta; 18 | if (l) l->delta += delta; 19 | if (r) r->delta += delta; 20 | delta = 0; 21 | } 22 | Edge top() { prop(); return key; } 23 | }; 24 | Node *merge(Node *a, Node *b) { 25 | if (!a || !b) return a ?: b; 26 | a->prop(), b->prop(); 27 | if (a->key.w > b->key.w) swap(a, b); 28 | swap(a->l, (a->r = merge(b, a->r))); 29 | return a; 30 | } 31 | void pop(Node*& a) { a->prop(); a = merge(a->l, a->r); } 32 | 33 | ll dmst(int n, int r, vector& g) { 34 | DSU dsu; dsu.init(n); 35 | vector heap(n); 36 | trav(e, g) heap[e.b] = merge(heap[e.b], new Node{e}); 37 | ll res = 0; 38 | vi seen(n, -1), path(n); seen[r] = r; 39 | F0R(s,n) { 40 | int u = s, qi = 0, w; 41 | while (seen[u] < 0) { 42 | path[qi++] = u, seen[u] = s; 43 | if (!heap[u]) return -1; 44 | Edge e = heap[u]->top(); 45 | heap[u]->delta -= e.w, pop(heap[u]); 46 | res += e.w, u = dsu.get(e.a); 47 | if (seen[u] == s) { 48 | Node* cyc = 0; 49 | do cyc = merge(cyc, heap[w = path[--qi]]); 50 | while (dsu.unite(u, w)); 51 | u = dsu.get(u); 52 | heap[u] = cyc, seen[u] = -1; 53 | } 54 | } 55 | } 56 | return res; 57 | } -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/Misc/DominatorTree.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: $a$ dominates $b$ iff every path from $1$ to $b$ passes through $a$ 3 | * Time: O(M\log N) 4 | * Source: https://tanujkhattar.wordpress.com/2016/01/11/dominator-tree-of-a-directed-graph/ 5 | * Verification: https://codeforces.com/gym/100513/problem/L 6 | */ 7 | 8 | template struct Dominator { 9 | vi adj[SZ], ans[SZ]; // input edges, edges of dominator tree 10 | vi radj[SZ], child[SZ], sdomChild[SZ]; 11 | int label[SZ], rlabel[SZ], sdom[SZ], dom[SZ], co; 12 | int root = 1; 13 | 14 | int par[SZ], bes[SZ]; 15 | int get(int x) { 16 | // DSU with path compression 17 | // get vertex with smallest sdom on path to root 18 | if (par[x] != x) { 19 | int t = get(par[x]); par[x] = par[par[x]]; 20 | if (sdom[t] < sdom[bes[x]]) bes[x] = t; 21 | } 22 | return bes[x]; 23 | } 24 | 25 | void dfs(int x) { // create DFS tree 26 | label[x] = ++co; rlabel[co] = x; 27 | sdom[co] = par[co] = bes[co] = co; 28 | trav(y,adj[x]) { 29 | if (!label[y]) { 30 | dfs(y); 31 | child[label[x]].pb(label[y]); 32 | } 33 | radj[label[y]].pb(label[x]); 34 | } 35 | } 36 | void init() { 37 | dfs(root); 38 | ROF(i,1,co+1) { 39 | trav(j,radj[i]) ckmin(sdom[i],sdom[get(j)]); 40 | if (i > 1) sdomChild[sdom[i]].pb(i); 41 | trav(j,sdomChild[i]) { 42 | int k = get(j); 43 | if (sdom[j] == sdom[k]) dom[j] = sdom[j]; 44 | else dom[j] = k; 45 | } 46 | trav(j,child[i]) par[j] = i; 47 | } 48 | FOR(i,2,co+1) { 49 | if (dom[i] != sdom[i]) dom[i] = dom[dom[i]]; 50 | ans[rlabel[dom[i]]].pb(rlabel[i]); 51 | } 52 | } 53 | }; -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/Misc/MaximalCliques.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Used only once. Finds all maximal cliques. 3 | * Time: O(3^{N/3}) 4 | * Source: KACTL 5 | * Verification: BOSPRE 2016 gaudy 6 | */ 7 | 8 | typedef bitset<128> B; 9 | int N; 10 | B adj[128]; 11 | 12 | // possibly in clique, not in clique, in clique 13 | void cliques(B P = ~B(), B X={}, B R={}) { 14 | if (!P.any()) { 15 | if (!X.any()) { 16 | // do smth with R 17 | } 18 | return; 19 | } 20 | int q = (P|X)._Find_first(); 21 | // clique must contain q or non-neighbor of q 22 | B cands = P&~adj[q]; 23 | F0R(i,N) if (cands[i]) { 24 | R[i] = 1; 25 | cliques(P&adj[i],X&adj[i],R); 26 | R[i] = P[i] = 0; X[i] = 1; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/README.md: -------------------------------------------------------------------------------- 1 | # 12 - Graphs Hard 2 | 3 | *Some problems sourced from [here](http://codeforces.com/blog/entry/54526?#comment-385354).* 4 | 5 | [CPC.10](https://github.com/SuprDewd/T-414-AFLV/tree/master/10_graphs_3_network_flow) 6 | 7 | ## 4 8 | * Eulerian Tours 9 | * Tutorial 10 | * CPH (19, Path & Circuits) 11 | * Problems 12 | * [Matching Substrings](https://csacademy.com/contest/archive/task/matching-substrings/) [](87) 13 | * [A2OJ](https://a2oj.com/category?ID=24) 14 | * Biconnected Components 15 | * Related 16 | * Articulation Points 17 | * Bridges 18 | * Tutorial 19 | * [GeeksforGeeks](http://www.geeksforgeeks.org/articulation-points-or-cut-vertices-in-a-graph/) 20 | * Problems 21 | * [Blockade](https://szkopul.edu.pl/problemset/problem/eDt8w290owtatmCjad0O0ywk/site/?key=statement) 22 | * [POLICIJA](http://wcipeg.com/problem/coi06p2) 23 | * [One-Way Streets](https://csacademy.com/contest/archive/task/one-way-streets/) 24 | * [Investment](https://dmoj.ca/problem/tle17c1p6) 25 | * [A2OJ](https://a2oj.com/category?ID=128) 26 | * Strongly Connected Components 27 | * Tutorial 28 | * CPH (17, Strong Connectivity) 29 | * Topics 30 | * Tarjan 31 | * [Kosaraju](https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm) 32 | * [2-SAT](http://codeforces.com/blog/entry/16205) 33 | * Problems 34 | * [A2OJ](https://a2oj.com/category?ID=231) 35 | * [Proving Equivalences](https://open.kattis.com/problems/equivalences) [](78) 36 | * [Festival](https://szkopul.edu.pl/problemset/problem/p9uJo01RR9ouMLLAYroFuQ-7/site/?key=statement) [](173) 37 | * [Linear Programming Trick](https://www.cs.rit.edu/~spr/COURSES/ALG/MIT/lec18.pdf) 38 | 39 | ## 6 40 | * Advanced Stuff 41 | * [DeobureoMinkyuParty ICPC Notebook](https://github.com/koosaga/DeobureoMinkyuParty/blob/master/teamnote.pdf) 42 | -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/Trees (10)/CentroidDecomp (10.3).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: can support tree path queries and updates 3 | * Time: $O(N\log N)$ 4 | * Source: own 5 | * Verification: 6 | * https://codeforces.com/contest/342/problem/E 7 | * Triway Cup 2019 G 8 | */ 9 | 10 | template struct centroidDecomp { 11 | vi neighbor[SZ]; 12 | int subsize[SZ]; 13 | bool vis[SZ]; 14 | int p[SZ]; 15 | int par[SZ]; 16 | vi child[SZ]; 17 | int numNodes; 18 | 19 | centroidDecomp(int num) { 20 | this->numNodes = num; 21 | } 22 | void addEdge(int u, int v) { 23 | neighbor[u].PB(v); 24 | neighbor[v].PB(u); 25 | } 26 | void build() { 27 | M00(i, numNodes) vis[i] = 0, par[i] = -1; 28 | solve(0); 29 | M00(i, numNodes) if(par[i] != -1) child[par[i]].PB(i); 30 | } 31 | void getSizes(int node) { 32 | subsize[node] = 1; 33 | for(int ch: neighbor[node]) if(!vis[ch] && ch != p[node]) { 34 | p[ch] = node; 35 | getSizes(ch); 36 | subsize[node] += subsize[ch]; 37 | } 38 | } 39 | int getCentroid(int root) { 40 | p[root] = -1; 41 | getSizes(root); 42 | int cur = root; 43 | while(1) { 44 | pi hi = MP(subsize[root]-subsize[cur], cur); 45 | for(int v: neighbor[cur]) if(!vis[v] && v != p[cur]) hi = max(hi, MP(subsize[v], v)); 46 | if(hi.F <= subsize[root]/2) return cur; 47 | cur = hi.S; 48 | } 49 | } 50 | int solve(int node) { 51 | node = getCentroid(node); 52 | vis[node] = 1; 53 | for(int ch: neighbor[node]) if(!vis[ch]) par[solve(ch)] = node; 54 | return node; 55 | } 56 | }; 57 | -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/Trees (10)/LCAjumps (10.2).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: calculates least common ancestor in tree with binary jumping 3 | * Time: O(N\log N) 4 | * Source: USACO Camp 5 | * Verification: Debug the Bugs 6 | */ 7 | 8 | template struct tree { 9 | vector> adj[SZ]; 10 | const static int LGSZ = 32-__builtin_clz(SZ-1); 11 | pair ppar[SZ][LGSZ]; 12 | int depth[SZ]; 13 | ll distfromroot[SZ]; 14 | 15 | void addEdge(int u, int v, int d) { 16 | adj[u].PB(MP(v, d)); 17 | adj[v].PB(MP(u, d)); 18 | } 19 | void dfs(int u, int dep, ll dis) { 20 | depth[u] = dep; 21 | distfromroot[u] = dis; 22 | for(auto& v: adj[u]) if(ppar[u][0].F != v.F) { 23 | ppar[v.F][0] = MP(u, v.S); 24 | dfs(v.F, dep + 1, dis + v.S); 25 | } 26 | } 27 | void build() { 28 | ppar[0][0] = MP(0, 0); 29 | M00(i, SZ) depth[i] = 0; 30 | dfs(0, 0, 0); 31 | MOO(i, 1, LGSZ) M00(j, SZ) { 32 | ppar[j][i].F = ppar[ppar[j][i-1].F][i-1].F; 33 | ppar[j][i].S = ppar[j][i-1].S + ppar[ppar[j][i-1].F][i-1].S; 34 | } 35 | } 36 | int lca(int u, int v) { 37 | if(depth[u] < depth[v]) swap(u, v); 38 | M00d(i, LGSZ) if(depth[ppar[u][i].F] >= depth[v]) u = ppar[u][i].F; 39 | if(u == v) return u; 40 | M00d(i, LGSZ) { 41 | if(ppar[u][i].F != ppar[v][i].F) { 42 | u = ppar[u][i].F; 43 | v = ppar[v][i].F; 44 | } 45 | } 46 | return ppar[u][0].F; 47 | } 48 | ll dist(int u, int v) { 49 | return distfromroot[u] + distfromroot[v] - 2*distfromroot[lca(u, v)]; 50 | } 51 | }; 52 | -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/Trees (10)/README.md: -------------------------------------------------------------------------------- 1 | # Trees 2 | 3 | ## 4 4 | 5 | [This](http://www.usaco.org/index.php?page=viewproblem2&cpid=921) USACO Gold problem can be solved using LCA or HLD. However, I'm still counting these topics as platinum because I don't expect this to occur again. 6 | 7 | General: 8 | 9 | * CPH (14, Tree Algorithms) 10 | * CPH (18, Tree Queries) 11 | 12 | Topics: 13 | 14 | * Tree Diameter 15 | * Problem(s) 16 | * [Tree Construction](https://csacademy.com/contest/archive/task/tree-construct) 17 | * Least Common Ancestor 18 | * Problems 19 | * [Hot & Cold](https://dmoj.ca/problem/bts17p7) [](105) 20 | * [Root LCA Queries](https://csacademy.com/contest/archive/task/root-lca-queries/) [](107) 21 | * Small to Large (Offline) 22 | * Centroid Decomposition 23 | * [GeeksForGeeks](http://www.geeksforgeeks.org/centroid-decomposition-of-tree/) 24 | * [A2OJ](https://a2oj.com/category?ID=319) 25 | * Heavy-Light Decomposition 26 | * [Anudeep2011](https://blog.anudeep2011.com/heavy-light-decomposition/) 27 | * [AI-Cash](http://codeforces.com/blog/entry/22072) 28 | * [adamant](https://codeforces.com/blog/entry/53170) 29 | -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/Trees (10)/SmallToLarge (10.2).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: offline subtree queries in O(Nlog^2N) 3 | * Source: own 4 | * Verification: January Easy 2018 - Shubham & Tree 1 5 | */ 6 | 7 | struct SmallToLarge { 8 | int val[MX]; 9 | vi child[MX]; 10 | map dat[MX]; 11 | 12 | void comb(int a, int b) { 13 | bool swa = 0; 14 | if (sz(dat[a]) < sz(dat[b])) swap(a,b), swa = 1; // swapping doesn't seem to work for indexed set 15 | trav(x,dat[b]) dat[a][x.f] += x.s; 16 | dat[b].clear(); 17 | if (swa) swap(dat[a],dat[b]); 18 | } 19 | 20 | void process(int ind) { 21 | dat[ind][val[ind]] ++; 22 | trav(i,child[ind]) { 23 | process(i); 24 | comb(ind,i); 25 | } 26 | // now do stuff with values 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/Trees (10)/TreeDiameter (10.1).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Calculates longest path in tree 3 | * Source: own 4 | * Verification: 5 | * http://www.spoj.com/problems/PT07Z/ 6 | * https://codeforces.com/contest/1182/problem/D 7 | */ 8 | 9 | template struct TreeDiameter { 10 | int n; 11 | vi adj[SZ]; 12 | void addEdge(int a, int b) { adj[a].pb(b), adj[b].pb(a); } 13 | 14 | int par[SZ], dist[SZ]; 15 | void dfs(int x) { 16 | trav(y,adj[x]) if (y != par[x]) { 17 | par[y] = x; dist[y] = dist[x]+1; 18 | dfs(y); 19 | } 20 | } 21 | void genDist(int x) { par[x] = -1; dist[x] = 0; dfs(x); } 22 | 23 | int diaLength; 24 | vi center, dia = {1,1}; 25 | void init(int _n) { 26 | n = _n; 27 | genDist(1); FOR(i,1,n+1) if (dist[i] > dist[dia[0]]) dia[0] = i; // find one endpoint of a diameter 28 | genDist(dia[0]); FOR(i,1,n+1) if (dist[i] > dist[dia[1]]) dia[1] = i; 29 | diaLength = dist[dia[1]]; 30 | 31 | int cen = dia[1]; F0R(i,diaLength/2) cen = par[cen]; 32 | if (diaLength&1) center = {cen,par[cen]}; 33 | else center = {cen}; 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /referencepdf/content/graphs (12)/chapter.tex: -------------------------------------------------------------------------------- 1 | \chapter{Graphs} 2 | 3 | \section{Fundamentals} 4 | \kactlimport{Fundamentals/DSU (7.6).h} 5 | \kactlimport{Fundamentals/ManhattanMST.h} 6 | \kactlimport{Fundamentals/Dijkstra.h} 7 | \kactlimport{Fundamentals/FloydWarshall.h} 8 | 9 | \section{Trees} 10 | \kactlimport{Trees (10)/LCAjumps (10.2).h} 11 | \kactlimport{Trees (10)/LCArmq (10.2).h} 12 | \kactlimport{Trees (10)/CentroidDecomp (10.3).h} 13 | \kactlimport{Trees (10)/HLD (10.3).h} 14 | 15 | \section{DFS Algorithms} 16 | \kactlimport{DFS/SCC (12.1).h} 17 | \kactlimport{DFS/TopoSort.h} 18 | \kactlimport{DFS/2SAT (12.1).h} 19 | \kactlimport{DFS/EulerPath (12.2).h} 20 | \kactlimport{DFS/BCC (12.4).h} 21 | 22 | \section{Flows} 23 | \kactlimport{Flows (12.3)/Dinic.h} 24 | \kactlimport{Flows (12.3)/MCMF.h} 25 | \kactlimport{Flows (12.3)/GomoryHu.h} 26 | 27 | \section{Matching} 28 | \kactlimport{Matching/DFSmatch.h} 29 | \kactlimport{Matching/Hungarian.h} 30 | \kactlimport{Matching/UnweightedMatch.h} 31 | 32 | \section{Misc} 33 | \kactlimport{Misc/MaximalCliques.h} 34 | \kactlimport{Misc/LCT.h} 35 | \kactlimport{Misc/DirectedMST.h} 36 | \kactlimport{Misc/DominatorTree.h} 37 | \kactlimport{Misc/EdgeColor.h} 38 | -------------------------------------------------------------------------------- /referencepdf/content/math/sphericalCoordinates.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ldcWV/CP/720f064af7f7fabb2225fedcbe41821b7f23ed4e/referencepdf/content/math/sphericalCoordinates.pdf -------------------------------------------------------------------------------- /referencepdf/content/number-theory (11.1)/DiscreteLog.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: find least integer p such that r^p=x(mod m) 3 | * meet in the middle: O(sqrt(mod)) per query 4 | * Source: Own 5 | * Verification: https://www.hackerrank.com/contests/infinitum11/challenges/discrete-logarithm/problem 6 | * Dependency: Modular Int 7 | */ 8 | 9 | struct DiscreteLog { 10 | int mod, root, block; 11 | unordered_map u; 12 | mi cur; 13 | 14 | int query(mi x) { 15 | F0R(i,block) { 16 | if (u.count((int)x)) return i*block+u[(int)x]; 17 | x *= cur; 18 | } 19 | return -1; 20 | } 21 | 22 | void init(int m, int r) { // gcd(m,r) = 1 23 | mod = m; root = r; block = sqrt(mod)+1; 24 | u.clear(); 25 | cur = mi(1,mod); 26 | F0R(i,block) { 27 | if (!u.count((int)cur)) u[(int)cur] = i; 28 | cur *= root; 29 | } 30 | cur = 1/cur; 31 | } 32 | }; -------------------------------------------------------------------------------- /referencepdf/content/number-theory (11.1)/Divisibility/CRT.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Chinese Remainder Theorem 3 | * Source: Own 4 | * Verification: Kattis generalchineseremainder 5 | */ 6 | 7 | #include "Euclid.h" 8 | 9 | pl solve(pl a, pl b) { 10 | auto g = __gcd(a.s,b.s), l = a.s/g*b.s; 11 | if ((b.f-a.f) % g != 0) return {-1,-1}; 12 | auto A = a.s/g, B = b.s/g; 13 | auto mul = (b.f-a.f)/g*invGeneral(A,B) % B; 14 | return {((mul*a.s+a.f)%l+l)%l,l}; 15 | } 16 | -------------------------------------------------------------------------------- /referencepdf/content/number-theory (11.1)/Divisibility/Euclid.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Euclidean Algorithm 3 | * Source: KACTL 4 | */ 5 | 6 | pl euclid(ll a, ll b) { // returns {x,y} such that a*x+b*y=gcd(a,b) 7 | if (!b) return {1,0}; 8 | pl p = euclid(b,a%b); 9 | return {p.s,p.f-a/b*p.s}; 10 | } 11 | ll invGeneral(ll a, ll b) { 12 | pl p = euclid(a,b); assert(p.f*a+p.s*b == 1); 13 | return p.f+(p.f<0)*b; 14 | } -------------------------------------------------------------------------------- /referencepdf/content/number-theory (11.1)/Modular Arithmetic/ModFact.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: pre-compute factorial mod inverses for $MOD$, 3 | * assumes $MOD$ is prime and $SZ < MOD$ 4 | * Time: O(SZ) 5 | * Source: KACTL 6 | * Verification: https://dmoj.ca/problem/tle17c4p5 7 | */ 8 | 9 | vl inv, fac, ifac; 10 | void genInv(int SZ) { 11 | inv.rsz(SZ), fac.rsz(SZ), ifac.rsz(SZ); 12 | inv[1] = 1; FOR(i,2,SZ) inv[i] = MOD-MOD/i*inv[MOD%i]%MOD; 13 | fac[0] = ifac[0] = 1; 14 | FOR(i,1,SZ) { 15 | fac[i] = fac[i-1]*i%MOD; 16 | ifac[i] = ifac[i-1]*inv[i]%MOD; 17 | } 18 | } -------------------------------------------------------------------------------- /referencepdf/content/number-theory (11.1)/Modular Arithmetic/ModMulLL.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: multiply two 64-bit integers mod another if 128-bit is not available 3 | * works for $0\le a,b=(ll)mod))*mod; 14 | } 15 | ul modPow(ul a, ul b, const ul mod) { 16 | if (b == 0) return 1; 17 | ul res = modPow(a,b/2,mod); 18 | res = modMul(res,res,mod); 19 | if (b&1) return modMul(res,a,mod); 20 | return res; 21 | } -------------------------------------------------------------------------------- /referencepdf/content/number-theory (11.1)/Modular Arithmetic/ModSqrt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: find sqrt of integer mod a prime 3 | * Time: ? 4 | * Source: http://www.math.vt.edu/people/brown/class_homepages/shanks_tonelli.pdf 5 | * Verification: https://www.spoj.com/problems/CRYPTO1 6 | */ 7 | 8 | #include "Modular.h" 9 | 10 | template T sqrt(modular a) { 11 | auto p = pow(a,(MOD-1)/2); if (p != 1) return p == 0 ? 0 : -1; // check if zero or does not have sqrt 12 | T s = MOD-1, e = 0; while (s % 2 == 0) s /= 2, e ++; 13 | modular n = 1; while (pow(n,(MOD-1)/2) == 1) n = (T)(n)+1; // find non-square residue 14 | 15 | auto x = pow(a,(s+1)/2), b = pow(a,s), g = pow(n,s); 16 | int r = e; 17 | while (1) { 18 | auto B = b; int m = 0; while (B != 1) B *= B, m ++; 19 | if (m == 0) return min((T)x,MOD-(T)x); 20 | F0R(i,r-m-1) g *= g; 21 | x *= g; g *= g; b *= g; r = m; 22 | } 23 | } 24 | 25 | /* Explanation: 26 | * Initially, x^2=ab, ord(b) = 2^m, ord(g) = 2^r where m ord(g) = 2^{m+1} 28 | * if x'=x*g, then b' = b*g^2 29 | (b')^{2^{m-1}} = (b*g^2)^{2^{m-1}} 30 | = b^{2^{m-1}}*g^{2^m} 31 | = -1*-1 32 | = 1 33 | -> ord(b')|ord(b)/2 34 | * m decreases by at least one each iteration 35 | */ -------------------------------------------------------------------------------- /referencepdf/content/number-theory (11.1)/Modular Arithmetic/ModSum Explanation.tex: -------------------------------------------------------------------------------- 1 | Explanation: 2 | $$\sum_{i=0}^{to-1}\left\lfloor \frac{ki+c}{m}\right\rfloor=\sum_{x=1}^{to}\left\lfloor \frac{k(to-x)+c}{m}\right\rfloor$$ 3 | This is equal the number of lattice points $(x,y)$ such that $x,y>0$ and 4 | $$y\le \left\lfloor \frac{k(to-x)+c}{m}\right\rfloor\implies my+kx\le k\cdot to+c.$$ 5 | If we swap $x,y$ then the sum is equal to 6 | \begin{align*} 7 | \sum_{y=1}^{to2}\left\lfloor \frac{k\cdot to+c-my}{k}\right\rfloor&=\sum_{y=1}^{to2}\left\lfloor \frac{k\cdot to+c-my}{k}\right\rfloor\\ 8 | &=\sum_{y=1}^{to2}to+\left\lfloor \frac{c-my}{k}\right\rfloor\\ 9 | &=to\cdot to2-\sum_{y=1}^{to2}\left\lceil \frac{my-c}{k}\right\rceil\\ 10 | &=to\cdot to2-\sum_{y=1}^{to2}\left\lfloor \frac{my-c+k-1}{k}\right\rfloor\\ 11 | &=to\cdot to2-\sum_{y=0}^{to2-1}\left\lfloor \frac{my+m-c+k-1}{k}\right\rfloor\\ 12 | &=(to-1)\cdot to2-\sum_{y=0}^{to2-1}\left\lfloor \frac{my+m-c-1}{k}\right\rfloor 13 | \end{align*} 14 | as desired. -------------------------------------------------------------------------------- /referencepdf/content/number-theory (11.1)/Modular Arithmetic/ModSum.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Sums of mod'ed arithmetic progressions 3 | * Source: KACTL 4 | * Verification: ? 5 | */ 6 | 7 | typedef unsigned long long ul; 8 | 9 | ul sumsq(ul to) { return (to-1)*to/2; } // sum of 0..to-1 10 | 11 | ul divsum(ul to, ul c, ul k, ul m) { // sum_{i=0}^{to-1}floor((ki+c)/m) 12 | ul res = k/m*sumsq(to)+c/m*to; 13 | k %= m; c %= m; if (!k) return res; 14 | ul to2 = (to*k+c)/m; 15 | return res+(to-1)*to2-divsum(to2,m-1-c,m,k); 16 | } 17 | 18 | ll modsum(ul to, ll c, ll k, ll m) { 19 | c = (c%m+m)%m, k = (k%m+m)%m; 20 | return to*c+k*sumsq(to)-m*divsum(to,c,k,m); 21 | } -------------------------------------------------------------------------------- /referencepdf/content/number-theory (11.1)/Modular Arithmetic/Order.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Calculates smallest P such that x^P equiv 1 (mod p) 3 | * Source: Own 4 | * Verification: https://atcoder.jp/contests/jag2015summer-day4/tasks/icpc2015summer_day4_d 5 | */ 6 | 7 | using namespace rpm; 8 | using namespace basicFactor; 9 | 10 | ll order(ll x, ll p) { 11 | if (__gcd(x,p) != 1) return 0; 12 | ll P = phi(p); auto a = factor(P); 13 | trav(t,a) while (P % t.f == 0 && mod_pow(x,P/t.f,p) == 1) P /= t.f; 14 | return P; 15 | } 16 | -------------------------------------------------------------------------------- /referencepdf/content/number-theory (11.1)/Primality/FactorBasic.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: factors N in O(sqrtN) time 3 | * Source: Own 4 | * Verification: https://csacademy.com/contest/ceoi-2018-day-2/task/toys-big/ 5 | */ 6 | 7 | namespace factorBasic { 8 | template vector> factor(T x) { // x <= 10^{14} is fine 9 | vector> pri; 10 | 11 | for (T i = 2; i*i <= x; ++i) if (x % i == 0) { 12 | int t = 0; 13 | while (x % i == 0) x /= i, t ++; 14 | pri.pb({i,t}); 15 | } 16 | 17 | if (x > 1) pri.pb({x,1}); 18 | return pri; 19 | } 20 | 21 | /* Note: 22 | * number of operations needed s.t. 23 | * phi(phi(...phi(n)...))=1 24 | * is O(log n). 25 | * Euler's theorem: a^{\phi(p)}\equiv 1 (mod p), gcd(a,p)=1 26 | */ 27 | 28 | ll phi(ll x) { 29 | trav(a,factor(x)) x -= x/a.f; 30 | return x; 31 | } 32 | 33 | template void tour(vector>& v, vector& V, int ind, T cur) { 34 | if (ind == sz(v)) V.pb(cur); 35 | else { 36 | T mul = 1; 37 | F0R(i,v[ind].s+1) { 38 | tour(v,V,ind+1,cur*mul); 39 | mul *= v[ind].f; 40 | } 41 | } 42 | } 43 | 44 | template vector getDivi(T x) { 45 | auto v = factor(x); 46 | vector V; tour(v,V,0,(T)1); sort(all(V)); 47 | return V; 48 | } 49 | } 50 | 51 | using namespace factorBasic; -------------------------------------------------------------------------------- /referencepdf/content/number-theory (11.1)/Primality/FactorFast.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Factors integers up to $2^{60}$ 3 | * Time: ? 4 | * Source: KACTL 5 | * https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test 6 | * https://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm 7 | * https://codeforces.com/contest/1033/submission/44009089 is faster 8 | * Verification: https://www.spoj.com/problems/FACT0/ 9 | */ 10 | 11 | #include "PrimeSieve.h" 12 | 13 | Sieve<1<<20> S = Sieve<1<<20>(); // should take care of all primes up to n^(1/3) 14 | 15 | bool millerRabin(ll p) { // test primality 16 | if (p == 2) return true; 17 | if (p == 1 || p % 2 == 0) return false; 18 | ll s = p - 1; while (s % 2 == 0) s /= 2; 19 | F0R(i,30) { // strong liar with probability <= 1/4 20 | ll a = rand() % (p - 1) + 1, tmp = s; 21 | ll mod = mod_pow(a, tmp, p); 22 | while (tmp != p - 1 && mod != 1 && mod != p - 1) { 23 | mod = mod_mul(mod, mod, p); 24 | tmp *= 2; 25 | } 26 | if (mod != p - 1 && tmp % 2 == 0) return false; 27 | } 28 | return true; 29 | } 30 | 31 | ll f(ll a, ll n, ll &has) { return (mod_mul(a, a, n) + has) % n; } 32 | 33 | vpl pollardsRho(ll d) { 34 | vpl res; 35 | auto& pr = S.pr; 36 | for (int i = 0; i < sz(pr) && pr[i]*pr[i] <= d; i++) if (d % pr[i] == 0) { 37 | int co = 0; while (d % pr[i] == 0) d /= pr[i], co ++; 38 | res.pb({pr[i],co}); 39 | } 40 | if (d > 1) { // d is now a product of at most 2 primes. 41 | if (millerRabin(d)) res.pb({d,1}); 42 | else while (1) { 43 | ll has = rand() % 2321 + 47; 44 | ll x = 2, y = 2, c = 1; 45 | for (; c == 1; c = __gcd(abs(x-y), d)) { 46 | x = f(x, d, has); 47 | y = f(f(y, d, has), d, has); 48 | } // should cycle in ~sqrt(smallest nontrivial divisor) turns 49 | if (c != d) { 50 | d /= c; if (d > c) swap(d,c); 51 | if (c == d) res.pb({c,2}); 52 | else res.pb({c,1}), res.pb({d,1}); 53 | break; 54 | } 55 | } 56 | } 57 | return res; 58 | } -------------------------------------------------------------------------------- /referencepdf/content/number-theory (11.1)/Primality/PrimeSieve.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: tests primality up to $SZ$ 3 | * Time: O(SZ\log\log SZ) 4 | * Source: KACTL 5 | * Verification: https://open.kattis.com/problems/primesieve 6 | */ 7 | 8 | template struct Sieve { 9 | bitset isprime; 10 | vi pr; 11 | Sieve() { 12 | isprime.set(); isprime[0] = isprime[1] = 0; 13 | for (int i = 4; i < SZ; i += 2) isprime[i] = 0; 14 | for (int i = 3; i*i < SZ; i += 2) if (isprime[i]) 15 | for (int j = i*i; j < SZ; j += i*2) isprime[j] = 0; 16 | FOR(i,2,SZ) if (isprime[i]) pr.pb(i); 17 | } 18 | }; -------------------------------------------------------------------------------- /referencepdf/content/number-theory (11.1)/Primality/PrimeSieveLinear.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Linear Time Prime Sieve 3 | */ 4 | 5 | template struct Sieve { 6 | int sp[SZ]; 7 | vi pr; 8 | 9 | Sieve() { 10 | memset(sp,0,sizeof sp); 11 | FOR(i,2,SZ) { // O(N) sieve 12 | if (sp[i] == 0) { sp[i] = i; pr.pb(i); } 13 | trav(p,pr) { 14 | if (p > sp[i] || i*p >= SZ) break; 15 | sp[i*p] = p; 16 | } 17 | } 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /referencepdf/content/number-theory (11.1)/README.md: -------------------------------------------------------------------------------- 1 | # Number Theory 2 | 3 | ### 4 4 | 5 | * Eratosthenes' Sieve 6 | * Tutorial 7 | * CPH (21, NT) 8 | 9 | ### 5 10 | 11 | * Modular Arithmetic 12 | * Modular Inverse 13 | * Chinese Remainder Theorem 14 | * Euler's Theorem, Phi Function 15 | * Discrete Logarithm 16 | -------------------------------------------------------------------------------- /referencepdf/content/number-theory (11.1)/chapter.tex: -------------------------------------------------------------------------------- 1 | \chapter{Number Theory} 2 | 3 | \section{Modular Arithmetic} 4 | \kactlimport{Modular Arithmetic/Modular.h} 5 | \kactlimport{Modular Arithmetic/ModFact.h} 6 | \kactlimport{Modular Arithmetic/ModMulLL.h} 7 | \kactlimport{Modular Arithmetic/ModSqrt.h} 8 | \kactlimport{Modular Arithmetic/ModSum.h} 9 | 10 | \section{Primality} 11 | \kactlimport{Primality/PrimeSieve.h} 12 | \kactlimport{Primality/FactorFast.h} 13 | 14 | \section{Divisibility} 15 | \kactlimport{Divisibility/Euclid.h} 16 | \kactlimport{Divisibility/CRT.h} -------------------------------------------------------------------------------- /referencepdf/content/numerical/Arithmetic/Fraction.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Operations with fractions 3 | * Source: https://martin-thoma.com/fractions-in-cpp/ 4 | * Verification: TopCoder MinimizeAbsoluteDifferenceDiv1 5 | */ 6 | 7 | struct frac { 8 | ll n,d; 9 | frac() { n = 0, d = 1; } 10 | frac(ll _n, ll _d) { 11 | n = _n, d = _d; 12 | ll g = __gcd(n,d); n /= g, d /= g; 13 | if (d < 0) n *= -1, d *= -1; 14 | } 15 | frac(ll _n) : frac(_n,1) {} 16 | 17 | friend frac abs(frac F) { return frac(abs(F.n),F.d); } 18 | 19 | friend bool operator<(const frac& l, const frac& r) { return l.n*r.d < r.n*l.d; } 20 | friend bool operator==(const frac& l, const frac& r) { return l.n == r.n && l.d == r.d; } 21 | friend bool operator!=(const frac& l, const frac& r) { return !(l == r); } 22 | 23 | friend frac operator+(const frac& l, const frac& r) { return frac(l.n*r.d+r.n*l.d,l.d*r.d); } 24 | friend frac operator-(const frac& l, const frac& r) { return frac(l.n*r.d-r.n*l.d,l.d*r.d); } 25 | friend frac operator*(const frac& l, const frac& r) { return frac(l.n*r.n,l.d*r.d); } 26 | friend frac operator*(const frac& l, int r) { return l*frac(r,1); } 27 | friend frac operator*(int r, const frac& l) { return l*r; } 28 | friend frac operator/(const frac& l, const frac& r) { return l*frac(r.d,r.n); } 29 | friend frac operator/(const frac& l, const int& r) { return l/frac(r,1); } 30 | friend frac operator/(const int& l, const frac& r) { return frac(l,1)/r; } 31 | 32 | friend frac& operator+=(frac& l, const frac& r) { return l = l+r; } 33 | friend frac& operator-=(frac& l, const frac& r) { return l = l-r; } 34 | template friend frac& operator*=(frac& l, const T& r) { return l = l*r; } 35 | template friend frac& operator/=(frac& l, const T& r) { return l = l/r; } 36 | 37 | friend ostream& operator<<(ostream& strm, const frac& a) { 38 | strm << a.n; 39 | if (a.d != 1) strm << "/" << a.d; 40 | return strm; 41 | } 42 | }; -------------------------------------------------------------------------------- /referencepdf/content/numerical/Matrix (11.3)/Matrix.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: 2D matrix operations 3 | * Source: KACTL 4 | * Verification: https://dmoj.ca/problem/si17c1p5, SPOJ MIFF 5 | */ 6 | 7 | template struct Mat { 8 | int r,c; 9 | vector> d; 10 | Mat(int _r, int _c) : r(_r), c(_c) { d.assign(r,vector(c)); } 11 | Mat() : Mat(0,0) {} 12 | Mat(const vector>& _d) : r(sz(_d)), c(sz(_d[0])) { d = _d; } 13 | friend void pr(const Mat& m) { pr(m.d); } 14 | 15 | Mat& operator+=(const Mat& m) { 16 | assert(r == m.r && c == m.c); 17 | F0R(i,r) F0R(j,c) d[i][j] += m.d[i][j]; 18 | return *this; 19 | } 20 | Mat& operator-=(const Mat& m) { 21 | assert(r == m.r && c == m.c); 22 | F0R(i,r) F0R(j,c) d[i][j] -= m.d[i][j]; 23 | return *this; 24 | } 25 | Mat operator*(const Mat& m) { 26 | assert(c == m.r); Mat x(r,m.c); 27 | F0R(i,r) F0R(j,c) F0R(k,m.c) x.d[i][k] += d[i][j]*m.d[j][k]; 28 | return x; 29 | } 30 | 31 | Mat operator+(const Mat& m) { return Mat(*this)+=m; } 32 | Mat operator-(const Mat& m) { return Mat(*this)-=m; } 33 | Mat& operator*=(const Mat& m) { return *this = (*this)*m; } 34 | 35 | friend Mat pow(Mat m, ll p) { 36 | assert(m.r == m.c); 37 | Mat r(m.r,m.c); 38 | F0R(i,m.r) r.d[i][i] = 1; 39 | for (; p; p /= 2, m *= m) if (p&1) r *= m; 40 | return r; 41 | } 42 | }; -------------------------------------------------------------------------------- /referencepdf/content/numerical/Matrix (11.3)/MatrixInv.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: calculates determinant via gaussian elimination 3 | * Time: O(N^3) 4 | * Source: various 5 | * Verification: SPOJ MIFF (matrix inverse modulo prime) 6 | */ 7 | 8 | #include "Matrix.h" 9 | 10 | template T gauss(Mat& m) { // determinant of 1000x1000 Matrix in ~1s 11 | int n = m.r; 12 | T prod = 1; int nex = 0; 13 | F0R(i,n) { 14 | int row = -1; // for ld use EPS rather than 0 15 | FOR(j,nex,n) if (m.d[j][i] != 0) { row = j; break; } 16 | if (row == -1) { prod = 0; continue; } 17 | if (row != nex) prod *= -1, swap(m.d[row],m.d[nex]); 18 | prod *= m.d[nex][i]; 19 | auto x = 1/m.d[nex][i]; FOR(k,i,m.c) m.d[nex][k] *= x; 20 | F0R(j,n) if (j != nex) { 21 | auto v = m.d[j][i]; 22 | if (v != 0) FOR(k,i,m.c) m.d[j][k] -= v*m.d[nex][k]; 23 | } 24 | nex ++; 25 | } 26 | return prod; 27 | } 28 | 29 | template Mat inv(Mat m) { 30 | int n = m.r; 31 | Mat x(n,2*n); 32 | F0R(i,n) { 33 | x.d[i][i+n] = 1; 34 | F0R(j,n) x.d[i][j] = m.d[i][j]; 35 | } 36 | if (gauss(x) == 0) return Mat(0,0); 37 | Mat r(n,n); 38 | F0R(i,n) F0R(j,n) r.d[i][j] = x.d[i][j+n]; 39 | return r; 40 | } -------------------------------------------------------------------------------- /referencepdf/content/numerical/Matrix (11.3)/MatrixTree.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Kirchhoff's Matrix Tree Theorem: 3 | * given adjacency matrix, calculates \# of spanning trees 4 | * Source: various 5 | * Verification: SPOJ MIFF (matrix inverse modulo prime) 6 | */ 7 | 8 | #include "MatrixInv.h" 9 | 10 | mi numSpan(Mat m) { 11 | int n = m.r; 12 | Mat res(n-1,n-1); 13 | F0R(i,n) FOR(j,i+1,n) { 14 | mi ed = m.d[i][j]; 15 | res.d[i][i] += ed; 16 | if (j != n-1) { 17 | res.d[j][j] += ed; 18 | res.d[i][j] -= ed, res.d[j][i] -= ed; 19 | } 20 | } 21 | return gauss(res); 22 | } 23 | -------------------------------------------------------------------------------- /referencepdf/content/numerical/Misc/Integrate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: ? 3 | * Source: KACTL 4 | * https://en.wikipedia.org/wiki/Simpson%27s_rule 5 | * Verification: https://codeforces.com/gym/101793/problem/C 6 | */ 7 | 8 | // db f(db x) { return x*x+3*x+1; } 9 | 10 | db quad(db (*f)(db), db a, db b) { 11 | const int n = 1000; 12 | db dif = (b-a)/2/n, tot = f(a)+f(b); 13 | FOR(i,1,2*n) tot += f(a+i*dif)*(i&1?4:2); 14 | return tot*dif/3; 15 | } -------------------------------------------------------------------------------- /referencepdf/content/numerical/Misc/IntegrateAdaptive.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: ? 3 | * Source: KACTL 4 | * https://en.wikipedia.org/wiki/Adaptive_Simpson%27s_method 5 | * Verification: ? 6 | */ 7 | 8 | // db f(db x) { return x*x+3*x+1; } 9 | 10 | db simpson(db (*f)(db), db a, db b) { 11 | db c = (a+b) / 2; 12 | return (f(a) + 4*f(c) + f(b)) * (b-a) / 6; 13 | } 14 | 15 | db rec(db (*f)(db), db a, db b, db eps, db S) { 16 | db c = (a+b) / 2; 17 | db S1 = simpson(f, a, c); 18 | db S2 = simpson(f, c, b), T = S1 + S2; 19 | if (abs(T - S) <= 15*eps || b-a < 1e-10) 20 | return T + (T - S) / 15; 21 | return rec(f, a, c, eps/2, S1) + rec(f, c, b, eps/2, S2); 22 | } 23 | 24 | db quad(db (*f)(db), db a, db b, db eps = 1e-8) { 25 | return rec(f, a, b, eps, simpson(f, a, b)); 26 | } -------------------------------------------------------------------------------- /referencepdf/content/numerical/Misc/LinRec.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Berlekamp-Massey: computes linear recurrence of 3 | * order $n$ for sequence of $2n$ terms 4 | * Time: ? 5 | * Source: 6 | * https://en.wikipedia.org/wiki/Berlekamp%E2%80%93Massey_algorithm 7 | * http://codeforces.com/blog/entry/61306 8 | * MIT ICPC notebook 9 | * Verification: http://codeforces.com/contest/506/problem/E 10 | */ 11 | 12 | using namespace vecOp; 13 | 14 | struct LinRec { 15 | vmi x; // original sequence 16 | vmi C, rC; 17 | void init(const vmi& _x) { 18 | x = _x; int n = sz(x), m = 0; 19 | vmi B; B = C = {1}; // B is fail vector 20 | 21 | mi b = 1; // B gives 0,0,0,...,b 22 | F0R(i,n) { 23 | m ++; 24 | mi d = x[i]; FOR(j,1,sz(C)) d += C[j]*x[i-j]; 25 | if (d == 0) continue; // recurrence still works 26 | auto _B = C; C.rsz(max(sz(C),m+sz(B))); 27 | mi coef = d/b; FOR(j,m,m+sz(B)) C[j] -= coef*B[j-m]; // recurrence that gives 0,0,0,...,d 28 | if (sz(_B) < m+sz(B)) { B = _B; b = d; m = 0; } 29 | } 30 | 31 | rC = C; reverse(all(rC)); // polynomial for getPo 32 | C.erase(begin(C)); trav(t,C) t *= -1; // x[i]=sum_{j=0}^{sz(C)-1}C[j]*x[i-j-1] 33 | } 34 | 35 | vmi getPo(int n) { 36 | if (n == 0) return {1}; 37 | vmi x = getPo(n/2); x = rem(x*x,rC); 38 | if (n&1) { vmi v = {0,1}; x = rem(x*v,rC); } 39 | return x; 40 | } 41 | mi eval(int n) { 42 | vmi t = getPo(n); 43 | mi ans = 0; F0R(i,sz(t)) ans += t[i]*x[i]; 44 | return ans; 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /referencepdf/content/numerical/Polynomials/FFT.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: multiply two polynomials 3 | * Time: O(N\log N) 4 | * Source: KACTL, https://cp-algorithms.com/algebra/fft.html 5 | * Verification: 6 | * SPOJ polymul, CSA manhattan, CF Perfect Encoding 7 | * http://codeforces.com/contest/632/problem/E 8 | */ 9 | 10 | #include "Modular.h" 11 | 12 | typedef complex cd; 13 | const int MOD = (119 << 23) + 1, root = 3; // = 998244353 14 | // NTT: For p < 2^30 there is also e.g. (5 << 25, 3), (7 << 26, 3), 15 | // (479 << 21, 3) and (483 << 21, 5). The last two are > 10^9. 16 | 17 | constexpr int size(int s) { return s > 1 ? 32-__builtin_clz(s-1) : 0; } 18 | void genRoots(vmi& roots) { // primitive n-th roots of unity 19 | int n = sz(roots); mi r = pow(mi(root),(MOD-1)/n); 20 | roots[0] = 1; FOR(i,1,n) roots[i] = roots[i-1]*r; 21 | } 22 | void genRoots(vcd& roots) { // change cd to complex instead? 23 | int n = sz(roots); double ang = 2*PI/n; 24 | F0R(i,n) roots[i] = cd(cos(ang*i),sin(ang*i)); // is there a way to do this more quickly? 25 | } 26 | 27 | template void fft(vector& a, const vector& roots, bool inv = 0) { 28 | int n = sz(a); 29 | for (int i = 1, j = 0; i < n; i++) { // sort by reverse bit representation 30 | int bit = n >> 1; 31 | for (; j&bit; bit >>= 1) j ^= bit; 32 | j ^= bit; if (i < j) swap(a[i], a[j]); 33 | } 34 | for (int len = 2; len <= n; len <<= 1) 35 | for (int i = 0; i < n; i += len) 36 | F0R(j,len/2) { 37 | int ind = n/len*j; if (inv && ind) ind = n-ind; 38 | auto u = a[i+j], v = a[i+j+len/2]*roots[ind]; 39 | a[i+j] = u+v, a[i+j+len/2] = u-v; 40 | } 41 | if (inv) { T i = T(1)/T(n); trav(x,a) x *= i; } 42 | } 43 | 44 | template vector mult(vector a, vector b) { 45 | int s = sz(a)+sz(b)-1, n = 1< roots(n); genRoots(roots); 47 | a.rsz(n), fft(a,roots); 48 | b.rsz(n), fft(b,roots); 49 | F0R(i,n) a[i] *= b[i]; 50 | fft(a,roots,1); return a; 51 | } -------------------------------------------------------------------------------- /referencepdf/content/numerical/Polynomials/FFTmod.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: multiply two polynomials with arbitrary $MOD$ 3 | * ensures precision by splitting in half 4 | * Source: KACTL, https://cp-algorithms.com/algebra/fft.html 5 | * Verification: see FFT 6 | */ 7 | 8 | #include "FFT.h" 9 | 10 | vl multMod(const vl& a, const vl& b) { 11 | if (!min(sz(a),sz(b))) return {}; 12 | int s = sz(a)+sz(b)-1, n = 1< 1 ? 32-__builtin_clz(s-1) : 0; } 12 | 13 | void karatsuba(ll *a, ll *b, ll *c, ll *t, int n) { 14 | int ca = 0, cb = 0; F0R(i,n) ca += !!a[i], cb += !!b[i]; 15 | if (min(ca, cb) <= 1500/n) { // few numbers to multiply 16 | if (ca > cb) swap(a, b); 17 | F0R(i,n) if (a[i]) F0R(j,n) c[i+j] += a[i]*b[j]; 18 | } else { 19 | int h = n >> 1; 20 | karatsuba(a, b, c, t, h); // a0*b0 21 | karatsuba(a+h, b+h, c+n, t, h); // a1*b1 22 | F0R(i,h) a[i] += a[i+h], b[i] += b[i+h]; 23 | karatsuba(a, b, t, t+n, h); // (a0+a1)*(b0+b1) 24 | F0R(i,h) a[i] -= a[i+h], b[i] -= b[i+h]; 25 | F0R(i,n) t[i] -= c[i]+c[i+n]; 26 | F0R(i,n) c[i+h] += t[i], t[i] = 0; 27 | } 28 | } 29 | 30 | vl conv(vl a, vl b) { 31 | int sa = sz(a), sb = sz(b); if (!sa || !sb) return {}; 32 | int n = 1< bool small(const vector& a, const vector& b) { 10 | return (ll)sz(a)*sz(b) <= 500000; // for small vectors, multiply directly 11 | } 12 | vmi smart(const vmi& a, const vmi& b) { return mult(a,b); } 13 | vcd smart(const vcd& a, const vcd& b) { return mult(a,b); } 14 | vl smart(const vl& a, const vl& b) { 15 | auto X = smart(vcd(all(a)),vcd(all(b))); 16 | vl x(sz(X)); F0R(i,sz(X)) x[i] = round(X[i].real()); 17 | return x; 18 | } 19 | template vector conv(const vector& a, const vector& b) { 20 | if (small(a,b)) return a*b; 21 | return smart(a,b); 22 | } -------------------------------------------------------------------------------- /referencepdf/content/numerical/Polynomials/PolyDiv.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: divide two polynomials 3 | * Time: $O(N\log N)?$ 4 | */ 5 | 6 | #include "PolyInv.h" 7 | 8 | template pair,vector> divi(const vector& f, const vector& g) { // f = q*g+r 9 | if (sz(f) < sz(g)) return {{},f}; 10 | auto q = mult(inv(rev(g),sz(f)-sz(g)+1),rev(f)); 11 | q.rsz(sz(f)-sz(g)+1); q = rev(q); 12 | auto r = f-mult(q,g); r.rsz(sz(g)-1); 13 | return {q,r}; 14 | } 15 | -------------------------------------------------------------------------------- /referencepdf/content/numerical/Polynomials/PolyInv.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: ? 3 | * Time: ? 4 | * Source: CF, http://people.csail.mit.edu/madhu/ST12/scribe/lect06.pdf 5 | * Verification: https://codeforces.com/contest/438/problem/E 6 | */ 7 | 8 | #include "FFT.h" 9 | 10 | template vector inv(vector v, int p) { // compute inverse of v mod x^p, where v[0] = 1 11 | v.rsz(p); vector a = {T(1)/v[0]}; 12 | for (int i = 1; i < p; i *= 2) { 13 | if (2*i > p) v.rsz(2*i); 14 | auto l = vector(begin(v),begin(v)+i), r = vector(begin(v)+i,begin(v)+2*i); 15 | auto c = mult(a,l); c = vector(begin(c)+i,end(c)); 16 | auto b = mult(a*T(-1),mult(a,r)+c); b.rsz(i); 17 | a.insert(end(a),all(b)); 18 | } 19 | a.rsz(p); return a; 20 | } -------------------------------------------------------------------------------- /referencepdf/content/numerical/Polynomials/PolyRoots.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Source: KACTL 3 | * Description: Finds the real roots of a polynomial. 4 | * Usage: poly_roots({{2,-3,1}},-1e9,1e9) // solve x^2-3x+2 = 0 5 | * Time: O(N^2 \log(1/\epsilon)) 6 | */ 7 | 8 | #include "VecOp.h" 9 | 10 | vd polyRoots(vd p, ld xmin, ld xmax) { 11 | if (sz(p) == 2) { return {-p[0]/p[1]}; } 12 | auto dr = polyRoots(dif(p),xmin,xmax); 13 | dr.pb(xmin-1); dr.pb(xmax+1); sort(all(dr)); 14 | vd ret; 15 | F0R(i,sz(dr)-1) { 16 | auto l = dr[i], h = dr[i+1]; 17 | bool sign = eval(p,l) > 0; 18 | if (sign ^ (eval(p,h) > 0)) { 19 | F0R(it,60) { // while (h - l > 1e-8) 20 | auto m = (l+h)/2, f = eval(p,m); 21 | if ((f <= 0) ^ sign) l = m; 22 | else h = m; 23 | } 24 | ret.pb((l+h)/2); 25 | } 26 | } 27 | return ret; 28 | } -------------------------------------------------------------------------------- /referencepdf/content/numerical/Polynomials/PolySqrt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: find sqrt of polynomial 3 | * Time: $O(N\log N)?$ 4 | */ 5 | 6 | #include "PolyInv.h" 7 | 8 | template vector sqrt(vector v, int p) { // S*S = v mod x^p, p is power of 2 9 | assert(v[0] == 1); if (p == 1) return {1}; 10 | v.rsz(p); 11 | auto S = sqrt(v,p/2); 12 | auto ans = S+mult(v,inv(S,p)); 13 | ans.rsz(p); ans *= T(1)/T(2); 14 | return ans; 15 | } -------------------------------------------------------------------------------- /referencepdf/content/numerical/chapter.tex: -------------------------------------------------------------------------------- 1 | \chapter{Numerical} 2 | 3 | \section{Matrix} 4 | \kactlimport{Matrix (11.3)/Matrix.h} 5 | \kactlimport{Matrix (11.3)/MatrixInv.h} 6 | \kactlimport{Matrix (11.3)/MatrixTree.h} 7 | 8 | \section{Polynomials} 9 | \kactlimport{Polynomials/VecOp.h} 10 | \kactlimport{Polynomials/PolyRoots.h} 11 | \kactlimport{Polynomials/Karatsuba.h} 12 | \kactlimport{Polynomials/FFT.h} 13 | \kactlimport{Polynomials/FFTmod.h} 14 | \kactlimport{Polynomials/PolyInv.h} 15 | \kactlimport{Polynomials/PolyDiv.h} 16 | \kactlimport{Polynomials/PolySqrt.h} 17 | 18 | \section{Misc} 19 | \kactlimport{Misc/LinRec.h} 20 | \kactlimport{Misc/Integrate.h} 21 | \kactlimport{Misc/IntegrateAdaptive.h} 22 | \kactlimport{Misc/Simplex.h} -------------------------------------------------------------------------------- /referencepdf/content/strings (14)/Lightweight/Bitset Trie (14.1).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: query max xor with some int in the trie 3 | * Source: CF Algorithms Gym 4 | * Verification: January Easy 2018 - Shubham and Subarray Xor 5 | */ 6 | 7 | template struct Trie { 8 | int nex[MX][2], sz[MX], num = 0; // num is last node in trie 9 | // change 2 to 26 for lowercase letters 10 | Trie() { 11 | memset(nex,0,sizeof nex); 12 | memset(sz,0,sizeof sz); 13 | } 14 | 15 | void ins(ll x, int a = 1) { // insert or delete 16 | int cur = 0; sz[cur] += a; 17 | R0F(i,MXBIT) { 18 | int t = (x>>i)&1; 19 | if (!nex[cur][t]) nex[cur][t] = ++num; 20 | sz[cur = nex[cur][t]] += a; 21 | } 22 | } 23 | ll test(ll x) { // compute max xor 24 | if (!sz[0]) return -INF; // no elements in trie 25 | int cur = 0; 26 | R0F(i,MXBIT) { 27 | int t = ((x>>i)&1)^1; 28 | if (!nex[cur][t] || !sz[nex[cur][t]]) t ^= 1; 29 | cur = nex[cur][t]; if (t) x ^= 1LL< duval(const string& s) { 12 | int n = sz(s); vector factors; 13 | for (int i = 0; i < n; ) { 14 | int j = i + 1, k = i; 15 | for (; j < n && s[k] <= s[j]; j++) { 16 | if (s[k] < s[j]) k = i; 17 | else k ++; 18 | } 19 | for (; i <= k; i += j-k) factors.pb(s.substr(i, j-k)); 20 | } 21 | return factors; 22 | } 23 | 24 | int minRotation(string s) { // get min index i such that cyclic shift starting at i is min rotation 25 | int n = sz(s); s += s; 26 | auto d = duval(s); int ind = 0, ans = 0; 27 | while (ans+sz(d[ind]) < n) ans += sz(d[ind++]); 28 | while (ind && d[ind] == d[ind-1]) ans -= sz(d[ind--]); 29 | return ans; 30 | } 31 | -------------------------------------------------------------------------------- /referencepdf/content/strings (14)/Lightweight/Manacher.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Source: http://codeforces.com/blog/entry/12143 3 | * Time: O(N) 4 | * Description: Calculates length of largest palindrome centered at each character of string 5 | * Verification: http://www.spoj.com/problems/MSUBSTR/ 6 | */ 7 | 8 | vi manacher(string s) { 9 | string s1 = "@"; 10 | trav(c,s) s1 += c, s1 += "#"; 11 | s1[sz(s1)-1] = '&'; 12 | 13 | vi ans(sz(s1)-1); 14 | int lo = 0, hi = 0; 15 | FOR(i,1,sz(s1)-1) { 16 | if (i != 1) ans[i] = min(hi-i,ans[hi-i+lo]); 17 | while (s1[i-ans[i]-1] == s1[i+ans[i]+1]) ans[i] ++; 18 | if (i+ans[i] > hi) lo = i-ans[i], hi = i+ans[i]; 19 | } 20 | 21 | ans.erase(begin(ans)); 22 | F0R(i,sz(ans)) if ((i&1) == (ans[i]&1)) ans[i] ++; // adjust lengths 23 | return ans; 24 | } 25 | // ps(manacher("abacaba")) -------------------------------------------------------------------------------- /referencepdf/content/strings (14)/Lightweight/MinRotation.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: minimum rotation of string 3 | * Time: O(N) 4 | * Source: KACTL 5 | * Verification: https://cses.fi/problemset/task/1110/ 6 | */ 7 | 8 | int minRotation(string s) { 9 | int a = 0, N = sz(s); s += s; 10 | F0R(b,N) F0R(i,N) { // a is current best rotation found up to b-1 11 | if (a+i == b || s[a+i] < s[b+i]) { b += max(0, i-1); break; } // b to b+i-1 can't be better than a to a+i-1 12 | if (s[a+i] > s[b+i]) { a = b; break; } // new best found 13 | } 14 | return a; 15 | } -------------------------------------------------------------------------------- /referencepdf/content/strings (14)/Lightweight/RabinKarp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Source: WhaleVomit 3 | * Time: O(N)\text{ build, }O(1)\text{ get hash value of a substring} 4 | * Description: generates hash values of any substring in $O(1)$, equal strings have same hash value 5 | * Verification: lmao imagine verifying 6 | */ 7 | 8 | template struct rabinKarp { 9 | const ll mods[3] = {1000000007, 999119999, 1000992299}; 10 | ll p[3][SZ]; 11 | ll h[3][SZ]; 12 | const ll base = 1000696969; 13 | rabinKarp() {} 14 | void build(string a) { 15 | M00(i, 3) { 16 | p[i][0] = 1; 17 | h[i][0] = (int)a[0]; 18 | MOO(j, 1, (int)a.length()) { 19 | p[i][j] = (p[i][j-1] * mods[i]) % base; 20 | h[i][j] = (h[i][j-1] * mods[i] + (int)a[j]) % base; 21 | } 22 | } 23 | } 24 | tuple hsh(int a, int b) { 25 | if(a == 0) return make_tuple(h[0][b], h[1][b], h[2][b]); 26 | tuple ans; 27 | get<0>(ans) = (((h[0][b] - h[0][a-1]*p[0][b-a+1]) % base) + base) % base; 28 | get<1>(ans) = (((h[1][b] - h[1][a-1]*p[1][b-a+1]) % base) + base) % base; 29 | get<2>(ans) = (((h[2][b] - h[2][a-1]*p[2][b-a+1]) % base) + base) % base; 30 | return ans; 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /referencepdf/content/strings (14)/Lightweight/Trie.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: trie 3 | * Source: CF Algorithms Gym 4 | * Verification: January Easy 2018 - Shubham and Subarray Xor 5 | */ 6 | 7 | struct tnode { 8 | char c; 9 | bool used; 10 | tnode* next[26]; 11 | tnode() { 12 | c = ' '; 13 | used = 0; 14 | M00(i, 26) next[i] = nullptr; 15 | } 16 | }; 17 | 18 | tnode* root; 19 | 20 | void addToTrie(string s) { 21 | tnode* cur = root; 22 | for(char ch: s) { 23 | int idx = ch - 'a'; 24 | if(cur->next[idx] == nullptr) { 25 | cur->next[idx] = new tnode(); 26 | } 27 | cur = cur->next[idx]; 28 | cur->c = ch; 29 | } 30 | cur->used = 1; 31 | } 32 | -------------------------------------------------------------------------------- /referencepdf/content/strings (14)/Lightweight/Z (14.3).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Source: http://codeforces.com/blog/entry/3107 3 | * Time: O(N) 4 | * Description: for each index $i$, computes the the maximum $len$ such that 5 | * \texttt{s.substr(0,len) == s.substr(i,len)} 6 | * Verification: POI 12 Template, https://codeforces.com/contest/1137/problem/B 7 | */ 8 | 9 | vi z(string s) { 10 | int N = sz(s); s += '#'; 11 | vi ans(N); ans[0] = N; 12 | int L = 1, R = 0; 13 | FOR(i,1,N) { 14 | if (i <= R) ans[i] = min(R-i+1,ans[i-L]); 15 | while (s[i+ans[i]] == s[ans[i]]) ans[i] ++; 16 | if (i+ans[i]-1 > R) L = i, R = i+ans[i]-1; 17 | } 18 | return ans; 19 | } 20 | 21 | vi getPrefix(string a, string b) { // find prefixes of a in b 22 | vi t = z(a+b), T(sz(b)); 23 | F0R(i,sz(T)) T[i] = min(t[i+sz(a)],sz(a)); 24 | return T; 25 | } 26 | 27 | // pr(z("abcababcabcaba"),getPrefix("abcab","uwetrabcerabcab")); 28 | -------------------------------------------------------------------------------- /referencepdf/content/strings (14)/Misc/TandemRepeats.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: Main-Lorentz algorithm, 3 | * finds all $(x,y)$ such that \texttt{s.substr(x,y-1) == s.substr(x+y,y-1)} 4 | * Time: O(N\log N) 5 | * Source: https://cp-algorithms.com/string/main_lorentz.html 6 | * Verification: http://codeforces.com/contest/1043/problem/G 7 | */ 8 | 9 | #include "Z.h" 10 | 11 | struct StringRepeat { 12 | string S; 13 | vector> al; 14 | // (t[0],t[1],t[2]) -> there is a repeating substring starting at x 15 | // with length t[0]/2 for all t[1] <= x <= t[2] 16 | 17 | vector> solveLeft(string s, int m) { 18 | vector> v; 19 | 20 | vi v2 = getPrefix(string(s.begin()+m+1,s.end()),string(s.begin(),s.begin()+m+1)); 21 | string V = string(s.begin(),s.begin()+m+2); reverse(all(V)); vi v1 = z(V); reverse(all(v1)); 22 | 23 | F0R(i,m+1) if (v1[i]+v2[i] >= m+2-i) { 24 | int lo = max(1,m+2-i-v2[i]), hi = min(v1[i],m+1-i); 25 | lo = i-lo+1, hi = i-hi+1; swap(lo,hi); 26 | v.pb({2*(m+1-i),lo,hi}); 27 | } 28 | 29 | return v; 30 | } 31 | 32 | void divi(int l, int r) { 33 | if (l == r) return; 34 | int m = (l+r)/2; divi(l,m); divi(m+1,r); 35 | 36 | string t = string(S.begin()+l,S.begin()+r+1); 37 | m = (sz(t)-1)/2; 38 | auto a = solveLeft(t,m); 39 | reverse(all(t)); 40 | auto b = solveLeft(t,sz(t)-2-m); 41 | 42 | trav(x,a) al.pb({x[0],x[1]+l,x[2]+l}); 43 | trav(x,b) { 44 | int ad = r-x[0]+1; 45 | al.pb({x[0],ad-x[2],ad-x[1]}); 46 | } 47 | } 48 | 49 | void init(string _S) { 50 | S = _S; divi(0,sz(S)-1); 51 | } 52 | 53 | vi genLen() { // min length of repeating substring starting at each index 54 | priority_queue> m; m.push({MOD,MOD}); 55 | vpi ins[sz(S)]; trav(a,al) ins[a[1]].pb({a[0],a[2]}); 56 | vi len(sz(S)); 57 | F0R(i,sz(S)) { 58 | trav(j,ins[i]) m.push(j); 59 | while (m.top().s < i) m.pop(); 60 | len[i] = m.top().f; 61 | } 62 | return len; 63 | } 64 | }; -------------------------------------------------------------------------------- /referencepdf/content/strings (14)/Suffix Structures/ACfixed.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: for each prefix, stores link to max length suffix which is also a prefix 3 | * Time: O(N\sum) 4 | * Source: https://ideone.com/0cMjZJ 5 | * https://codeforces.com/contest/710/problem/F 6 | * https://codeforces.com/contest/1207/problem/G 7 | */ 8 | 9 | struct ACfixed { // fixed alphabet 10 | struct node { 11 | array to; 12 | int link; 13 | }; 14 | vector d; 15 | ACfixed() { d.eb(); } 16 | 17 | int add(string s) { // add word 18 | int v = 0; 19 | trav(C,s) { 20 | int c = C-'a'; 21 | if (!d[v].to[c]) { 22 | d[v].to[c] = sz(d); 23 | d.eb(); 24 | } 25 | v = d[v].to[c]; 26 | } 27 | return v; 28 | } 29 | 30 | void init() { // generate links 31 | d[0].link = -1; 32 | queue q; q.push(0); 33 | while (sz(q)) { 34 | int v = q.front(); q.pop(); 35 | F0R(c,26) { 36 | int u = d[v].to[c]; if (!u) continue; 37 | d[u].link = d[v].link == -1 ? 0 : d[d[v].link].to[c]; 38 | q.push(u); 39 | } 40 | if (v) F0R(c,26) if (!d[v].to[c]) 41 | d[v].to[c] = d[d[v].link].to[c]; 42 | } 43 | } 44 | }; -------------------------------------------------------------------------------- /referencepdf/content/strings (14)/Suffix Structures/ACunfixed.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: for each prefix, stores link to max length suffix which is also a prefix 3 | * Source: https://ideone.com/0cMjZJ 4 | * Verification: 5 | * Kattis stringmultimatching 6 | */ 7 | 8 | struct ACunfixed { 9 | struct node { 10 | map to; 11 | int link; 12 | }; 13 | vector d; 14 | ACunfixed() { d.emplace_back(); } 15 | 16 | int add(string s) { // add word 17 | int v = 0; 18 | trav(c,s) { 19 | if (!d[v].to.count(c)) { 20 | d[v].to[c] = sz(d); 21 | d.emplace_back(); 22 | } 23 | v = d[v].to[c]; 24 | } 25 | return v; 26 | } 27 | 28 | int nex(int j, char c) { // state after adding character 29 | while (j != -1 && !d[j].to.count(c)) j = d[j].link; 30 | return j == -1 ? 0 : d[j].to[c]; 31 | } 32 | void init() { // generate links 33 | d[0].link = -1; 34 | queue q; q.push(0); 35 | while (sz(q)) { 36 | int v = q.front(); q.pop(); 37 | trav(it,d[v].to) { 38 | char c = it.f; int u = it.s; 39 | d[u].link = nex(d[v].link,c); 40 | q.push(u); 41 | } 42 | } 43 | } 44 | }; -------------------------------------------------------------------------------- /referencepdf/content/strings (14)/Suffix Structures/PalTree.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: palindromic tree, computes number of occurrences 3 | * of each palindrome within string 4 | * Time: O(N\sum) 5 | * Source: http://codeforces.com/blog/entry/13959 6 | * Verification: https://oj.uz/problem/view/APIO14_palindrome 7 | */ 8 | 9 | template struct PalTree { 10 | static const int sigma = 26; 11 | int s[SZ], len[SZ], link[SZ], to[SZ][sigma], oc[SZ]; 12 | int n, last, sz; 13 | PalTree() { s[n++] = -1; link[0] = 1; len[1] = -1; sz = 2; } 14 | 15 | int getLink(int v) { 16 | while (s[n-len[v]-2] != s[n-1]) v = link[v]; 17 | return v; 18 | } 19 | void addChar(int c) { 20 | s[n++] = c; 21 | last = getLink(last); 22 | if (!to[last][c]) { 23 | len[sz] = len[last]+2; 24 | link[sz] = to[getLink(link[last])][c]; 25 | to[last][c] = sz++; 26 | } 27 | last = to[last][c]; oc[last] ++; 28 | } 29 | void numOc() { 30 | vpi v; FOR(i,2,sz) v.pb({len[i],i}); 31 | sort(rall(v)); trav(a,v) oc[link[a.s]] += oc[a.s]; 32 | } 33 | }; -------------------------------------------------------------------------------- /referencepdf/content/strings (14)/Suffix Structures/ReverseBW (14.4).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: The Burrows-Wheeler Transform appends \# to a string, 3 | * sorts the rotations of the string in increasing order, 4 | * and constructs a new string that contains the last character 5 | * of each rotation. This function reverses the transform. 6 | * Time: O(N\log N) 7 | * Source: ? 8 | * Verification: https://cses.fi/problemset/task/1113/ 9 | */ 10 | 11 | string reverseBW(string s) { 12 | vi nex(sz(s)); 13 | vector> v; F0R(i,sz(s)) v.pb({s[i],i}); 14 | sort(all(v)); F0R(i,sz(v)) nex[i] = v[i].s; 15 | int cur = nex[0]; string ret; 16 | for (; cur;cur = nex[cur]) ret += v[cur].f; 17 | return ret; 18 | } -------------------------------------------------------------------------------- /referencepdf/content/strings (14)/Suffix Structures/SuffixArray (14.4).h: -------------------------------------------------------------------------------- 1 | /** 2 | * Description: ? 3 | * Time: O(N\log N) 4 | * Source: SuprDewd, KACTL, majk, ekzhang 5 | * Verification: 6 | * http://usaco.org/index.php?page=viewproblem2&cpid=768 7 | * https://pastebin.com/y2Z9FYr6 8 | * https://open.kattis.com/problems/suffixsorting 9 | * https://codeforces.com/contest/1090/problem/J 10 | */ 11 | 12 | template struct suffixArray { 13 | const static int LGSZ = 33-__builtin_clz(SZ-1); 14 | pair tup[SZ]; 15 | int sortIndex[LGSZ][SZ]; 16 | int res[SZ]; 17 | int len; 18 | suffixArray(string s) { 19 | this->len = (int)s.length(); 20 | M00(i, len) tup[i] = MP(MP((int)s[i], -1), i); 21 | sort(tup, tup+len); 22 | int temp = 0; 23 | tup[0].F.F = 0; 24 | MOO(i, 1, len) { 25 | if(s[tup[i].S] != s[tup[i-1].S]) temp++; 26 | tup[i].F.F = temp; 27 | } 28 | M00(i, len) sortIndex[0][tup[i].S] = tup[i].F.F; 29 | MOO(i, 1, LGSZ) { 30 | M00(j, len) tup[j] = MP(MP(sortIndex[i-1][j], (j+(1<<(i-1))= len || y >= len) break; 46 | if(sortIndex[i][x] == sortIndex[i][y]) { 47 | x += (1< h: 43 | % find . -name "*.cpp" -exec bash -c 'mv "$1" "${1%.cpp}".h' - '{}' \; 44 | % replace spaces with tabs 45 | % find . -name '*.h' ! -type d -exec bash -c 'unexpand -t 4 "$0" > /tmp/e && mv /tmp/e "$0"' {} \; 46 | % find F0Rd 47 | % grep -r 'F0Rd' . -------------------------------------------------------------------------------- /referencepdf/content/tex/texput.log: -------------------------------------------------------------------------------- 1 | This is pdfTeX, Version 3.14159265-2.6-1.40.20 (TeX Live 2019) (preloaded format=pdflatex 2019.5.8) 25 OCT 2019 23:19 2 | entering extended mode 3 | restricted \write18 enabled. 4 | %&-line parsing enabled. 5 | **kactlpkg.tex 6 | 7 | ! Emergency stop. 8 | <*> kactlpkg.tex 9 | 10 | *** (job aborted, file error in nonstop mode) 11 | 12 | 13 | Here is how much of TeX's memory you used: 14 | 3 strings out of 492616 15 | 103 string characters out of 6129482 16 | 57117 words of memory out of 5000000 17 | 4025 multiletter control sequences out of 15000+600000 18 | 3640 words of font info for 14 fonts, out of 8000000 for 9000 19 | 1141 hyphenation exceptions out of 8191 20 | 0i,0n,0p,1b,6s stack positions out of 5000i,500n,10000p,200000b,80000s 21 | ! ==> Fatal error occurred, no output PDF file produced! 22 | -------------------------------------------------------------------------------- /referencepdf/header.tmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ldcWV/CP/720f064af7f7fabb2225fedcbe41821b7f23ed4e/referencepdf/header.tmp -------------------------------------------------------------------------------- /referencepdf/kactl.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ldcWV/CP/720f064af7f7fabb2225fedcbe41821b7f23ed4e/referencepdf/kactl.pdf --------------------------------------------------------------------------------