diff --git a/content/4_Gold/BFS.mdx b/content/4_Gold/BFS.mdx
index b146dc9..9509f90 100644
--- a/content/4_Gold/BFS.mdx
+++ b/content/4_Gold/BFS.mdx
@@ -3,7 +3,7 @@ id: bfs
title: "Breadth First Search (BFS)"
author: Benjamin Qi, Michael Cao
prerequisites:
- - Silver - Depth First Search
+ - dfs
description: "Traversing a graph in a way such that vertices closer to the starting vertex are processed first."
frequency: 2
---
@@ -33,7 +33,7 @@ export const metadata = {
interactive
-
+
@@ -43,7 +43,70 @@ export const metadata = {
## Implementation
-
+
+
+
+
+From the CSA article:
+
+```cpp
+#include
+#include
+#include
+#include
+using namespace std;
+const int MAX_N = 100005;
+
+vector graph[MAX_N];
+int dist[MAX_N];
+bool visited[MAX_N];
+
+void bfs(int startNode) {
+ dist[startNode] = 0;
+ queue bfsQueue;
+ bfsQueue.push(startNode);
+ visited[startNode] = true;
+ while (!bfsQueue.empty()) {
+ int currentNode = bfsQueue.front();
+ bfsQueue.pop();
+ for (auto neighbour: graph[currentNode]) {
+ if (!visited[neighbour]) {
+ visited[neighbour] = true;
+ dist[neighbour] = dist[currentNode] + 1;
+ bfsQueue.push(neighbour);
+ }
+ }
+ }
+}
+
+int main() {
+ int N, M, v, x, y;
+ cin >> N >> M >> v;
+ for (int i = 1; i <= M; i += 1) {
+ cin >> x >> y;
+ graph[x].push_back(y);
+ }
+ for (int i = 1; i <= N; i += 1) {
+ dist[i] = -1;
+ }
+ bfs(v);
+ for (int i = 1; i <= N; i += 1) {
+ cout << dist[i] << " ";
+ }
+ return 0;
+}
+```
+
+
+
+
+
+
+
+
+
+
+
## Example: Cow Navigation
diff --git a/content/4_Gold/Cyc.mdx b/content/4_Gold/Cyc.mdx
index b7ea418..a1b211e 100644
--- a/content/4_Gold/Cyc.mdx
+++ b/content/4_Gold/Cyc.mdx
@@ -3,7 +3,7 @@ id: cyc
title: Cycle Detection
author: Siyong Huang
prerequisites:
- - Gold - Topological Sort
+ - toposort
description: "A simple cycle is a non-empty path of distinct edges that start and end at the same vertex such that no vertex appears more than once. Describes how to detect cycles in both directed and undirected graphs."
frequency: 0
---
diff --git a/content/4_Gold/DP.mdx b/content/4_Gold/DP.mdx
index 1f5fbe5..e086f76 100644
--- a/content/4_Gold/DP.mdx
+++ b/content/4_Gold/DP.mdx
@@ -2,7 +2,8 @@
id: intro-dp
title: "Introduction to Dynamic Programming"
author: Michael Cao
-prerequisites:
+prerequisites:
+ - complete-search
- prefix-sums
description: "Speeding up naive recursive solutions with memoization."
frequency: 4
@@ -44,7 +45,8 @@ export const metadata = {
new Problem("Old Gold", "Palindromic Paths", "553", "Hard", false, ["DP"], "start from the middle, dp[row i][row j][length] = number of strings of length 2 * length + 1 with ends at row i and j"),
],
lis: [
- new Problem("LC", "Longest Increasing Subsequence", "https://leetcode.com/problems/longest-increasing-subsequence/", "Easy", true, ["DP"], "dp[i] = LIS up to i, use binary search to decrease runtime from quadratic"),
+ new Problem("LC", "Longest Increasing Subsequence", "https://leetcode.com/problems/longest-increasing-subsequence/", "Very Easy", true, ["DP"], "dp[i] = LIS up to i, use binary search to decrease runtime from quadratic"),
+ new Problem("Kattis", "Longest Increasing Subsequence", "longincsubseq", "Easy", true, [], ""),
new Problem("Old Gold", "Cowjog", "496", "Easy", false, ["DP"], "direct application of longest increasing subsequence"),
new Problem("Plat", "Sort It Out", "865", "Very Hard", false, ["DP"], "component of kth largest LIS, read editorial for more details"),
],
@@ -97,7 +99,7 @@ Interesting applications of "number of paths on a grid," some of which don't dir
## Longest Increasing Subsequence
-The first problem requires a quadratic time complexity solution to Longset Increasing subsequence, but you should optimize it to $O(N \log N)$. Some of the problems in this section don't initially look like Longest Increasing Subsequence, but it ends up being the solution This can happen a lot, which is why it's a good idea to not focus on one topic unless you have a full solution.
+Some of the problems in this section don't initially look like Longest Increasing Subsequence, but it ends up being the solution. This can happen a lot, which is why it's a good idea to not focus on one topic unless you have a full solution
diff --git a/content/4_Gold/DP_Trees.mdx b/content/4_Gold/DP_Trees.mdx
index b0c12ec..305e8ea 100644
--- a/content/4_Gold/DP_Trees.mdx
+++ b/content/4_Gold/DP_Trees.mdx
@@ -3,8 +3,8 @@ id: dp-trees
title: "Dynamic Programming on Trees"
author: Michael Cao
prerequisites:
- - Silver - Depth First Search
- - Gold - Introduction to Dynamic Programming
+ - dfs
+ - intro-dp
description: "Using subtrees as subproblems."
frequency: 1
---
@@ -39,6 +39,8 @@ export const metadata = {
lol this code format is terrible
+## Sample Solution
+
## Solving for All Roots
diff --git a/content/4_Gold/DSU.mdx b/content/4_Gold/DSU.mdx
index 8fbd64e..b74cc10 100644
--- a/content/4_Gold/DSU.mdx
+++ b/content/4_Gold/DSU.mdx
@@ -3,7 +3,7 @@ id: dsu
title: "Disjoint Set Union"
author: Benjamin Qi, Michael Cao
prerequisites:
- - Silver - Depth First Search
+ - dfs
description: "The Disjoint Set Union (DSU) data structure allows you to add edges to an initially empty graph and test whether two vertices of the graph are connected."
frequency: 3
---
@@ -28,9 +28,9 @@ export const metadata = {
both optimizations, diagrams
+ both optimizations, no diagrams
small to large, diagrams
path compression, diagrams
- both optimizations, no diagrams
diagrams
@@ -46,7 +46,32 @@ Note: You may prefer to use this in place of DFS for computing connected compone
## Implementations
-
+Check PAPS for the explanation. `e[x]` contains the negation of the size of $x$'s component if $x$ is the representative of its component, and the parent of $x$ otherwise.
+
+
+
+
+
+
+
+```cpp
+struct DSU {
+ vi e; void init(int N) { e = vi(N,-1); }
+ // get representive component, uses path compression
+ int get(int x) { return e[x] < 0 ? x : e[x] = get(e[x]); }
+ bool sameSet(int a, int b) { return get(a) == get(b); }
+ int size(int x) { return -e[get(x)]; }
+ bool unite(int x, int y) { // union by size
+ x = get(x), y = get(y); if (x == y) return 0;
+ if (e[x] > e[y]) swap(x,y);
+ e[x] += e[y]; e[y] = x; return 1;
+ }
+};
+```
+
+
+
+
## Problems
diff --git a/content/4_Gold/Faster_Hash.mdx b/content/4_Gold/Faster_Hash.mdx
index 468ebc8..dc99137 100644
--- a/content/4_Gold/Faster_Hash.mdx
+++ b/content/4_Gold/Faster_Hash.mdx
@@ -5,7 +5,7 @@ author: Benjamin Qi
description: "Introduces gp_hash_table."
frequency: 1
prerequisites:
- - Bronze - Unordered Maps & Sets
+ - unordered
---
import { Problem } from "../models";
diff --git a/content/4_Gold/Intro_NT.mdx b/content/4_Gold/Intro_NT.mdx
index bde4901..e4926b3 100644
--- a/content/4_Gold/Intro_NT.mdx
+++ b/content/4_Gold/Intro_NT.mdx
@@ -4,6 +4,7 @@ title: "Introductory Number Theory"
author: Darren Yao, Michael Cao
prerequisites:
- intro-dp
+ - binary representation
description: Introduces divisibility and modular arithmetic.
frequency: 1
---
@@ -31,6 +32,8 @@ export const metadata = {
module is based off this
+ practice problems, set focus to number theory!
+ good book :D
primes and factors, modular arithmetic
same as below
lots of advanced stuff you don't need to know at this level
@@ -52,6 +55,12 @@ Now, we will discuss how to find the prime factorization of an integer.
![Pseudocode](factoralgorithm1.png)
+
+
+replace with code in all langs?
+
+
+
This algorithm runs in $O(\sqrt{n})$ time, because the for loop checks divisibility for at most $\sqrt{n}$ values. Even though there is a while loop inside the for loop, dividing $n$ by $i$ quickly reduces the value of $n$, which means that the outer for loop runs less iterations, which actually speeds up the code.
Let's look at an example of how this algorithm works, for $n = 252$.
@@ -61,9 +70,9 @@ Let's look at an example of how this algorithm works, for $n = 252$.
At this point, the for loop terminates, because $i$ is already 3 which is greater than $\lfloor \sqrt{7} \rfloor$. In the last step, we add $7$ to the list of factors $v$, because it otherwise won't be added, for a final prime factorization of $\{2, 2, 3, 3, 7\}$.
-## GCD & LCM
+## GCD
-The **greatest common divisor (GCD)** of two integers $a$ and $b$ is the largest integer that is a factor of both $a$ and $b$. In order to find the GCD of two numbers, we use the Euclidean Algorithm, which is as follows:
+The **greatest common divisor (GCD)** of two integers $a$ and $b$ is the largest integer that is a factor of both $a$ and $b$. In order to find the GCD of two numbers, we use the **Euclidean Algorithm**, which is as follows:
$$
\gcd(a, b) = \begin{cases}
@@ -80,25 +89,52 @@ This algorithm is very easy to implement using a recursive function, as follows:
```java
public int gcd(int a, int b){
- if(b == 0) return a;
+ if (b == 0) return a;
return gcd(b, a % b);
}
```
+
+
+```cpp
+int GCD(int a, int b){
+ if (b == 0) return a;
+ return GCD(b, a % b);
+}
+```
+
+For C++14 and below, use the built-in `__gcd(a,b)`. C++17 has built in `gcd(a,b)`.
+
+
+
-For C++, use the built-in `__gcd(a,b)`. Finding the GCD of two numbers can be done in $O(\log n)$ time, where $n = \min(a, b)$.
+This function runs in $O(\log \max(a,b))$ time.
+
+
+
+proof?
+
+
+
+## LCM
The **least common multiple (LCM)** of two integers $a$ and $b$ is the smallest integer divisible by both $a$ and $b$.
The LCM can easily be calculated from the following property with the GCD:
$$
-\operatorname{lcm}(a, b) = \frac{a \cdot b}{\gcd(a, b)}.
+\operatorname{lcm}(a, b) = \frac{a \cdot b}{\gcd(a, b)}=\frac{a}{\gcd(a,b)}\cdot b.
$$
+
+
+Dividing by $\gcd(a,b)$ first might prevent integer overflow.
+
+
+
If we want to take the GCD or LCM of more than two elements, we can do so two at a time, in any order. For example,
$$
@@ -107,7 +143,11 @@ $$
## Modular Arithmetic
-In **modular arithmetic**, instead of working with integers themselves, we work with their remainders when divided by $m$. We call this taking modulo $m$. For example, if we take $m = 23$, then instead of working with $x = 247$, we use $x \bmod 23 = 17$. Usually, $m$ will be a large prime, given in the problem; the two most common values are $10^9 + 7$, and $998\,244\,353$. Modular arithmetic is used to avoid dealing with numbers that overflow built-in data types, because we can take remainders, according to the following formulas:
+
+
+
+
+In **modular arithmetic**, instead of working with integers themselves, we work with their remainders when divided by $m$. We call this taking modulo $m$. For example, if we take $m = 23$, then instead of working with $x = 247$, we use $x \bmod 23 = 17$. Usually, $m$ will be a large prime, given in the problem; the two most common values are $10^9 + 7$, and $998\,244\,353=119\cdot 2^{23}+1$. Modular arithmetic is used to avoid dealing with numbers that overflow built-in data types, because we can take remainders, according to the following formulas:
$$
(a+b) \bmod m = (a \bmod m + b \bmod m) \bmod m
@@ -127,7 +167,9 @@ $$
## Modular Exponentiation
-Under a **prime** modulus, division can be performed using modular inverses.
+
+
+
**Modular Exponentiation** can be used to efficently compute $x ^ n \mod m$. To do this, let's break down $x ^ n$ into binary components. For example, $5 ^ {10}$ = $5 ^ {1010_2}$ = $5 ^ 8 \cdot 5 ^ 4$. Then, if we know $x ^ y$ for all $y$ which are powers of two ($x ^ 1$, $x ^ 2$, $x ^ 4$, $\dots$ , $x ^ {2^{\lfloor{\log_2n} \rfloor}}$, we can compute $x ^ n$ in $\mathcal{O}(\log n)$. Finally, since $x ^ y$ for some $y \neq 1$ equals $2 \cdot x ^ {y - 1}$, and $x$ otherwise, we can compute these sums efficently. To deal with $m$, observe that modulo doesn't affect multiplications, so we can directly implement the above "binary exponentiation" algorithm while adding a line to take results $\pmod m$.
@@ -155,10 +197,12 @@ long long binpow(long long x, long long n, long long m) {
-## Modular Inverse (Prime Moduli)
+## Modular Inverse
+
+We'll only consider **prime** moduli here. Division can be performed using modular inverses.
- Various ways to take modular inverse
+ Various ways to take modular inverse
### With Exponentiation
@@ -177,7 +221,7 @@ Also, one must always ensure that they do not attempt to divide by 0. Be aware t
-See [this module](../adv/extend-euclid).
+See the module in the [Advanced](../adv/extend-euclid) section.
diff --git a/content/4_Gold/MST.mdx b/content/4_Gold/MST.mdx
index c5d1917..e5f025a 100644
--- a/content/4_Gold/MST.mdx
+++ b/content/4_Gold/MST.mdx
@@ -27,8 +27,6 @@ export const metadata = {
}
};
-## Sample
-
## Resources
@@ -41,6 +39,13 @@ export const metadata = {
+## Implementation
+
+### Kruskal's
+
+### Prim's
+
+
## USACO Problems
diff --git a/content/4_Gold/PURS.mdx b/content/4_Gold/PURS.mdx
index f78d80b..48005c3 100644
--- a/content/4_Gold/PURS.mdx
+++ b/content/4_Gold/PURS.mdx
@@ -3,7 +3,7 @@ id: PURS
title: "Point Update Range Sum"
author: Benjamin Qi
prerequisites:
- - Silver - Prefix Sums
+ - prefix-sums
description: "Introducing Segment Trees, Binary Indexed Trees, and Indexed Sets (C++ only)."
frequency: 3
---
@@ -55,7 +55,7 @@ Most gold range query problems require you to support following tasks in $O(\log
- Update the element at a single position (point).
- Query the sum of some consecutive subarray.
-Both **segment tree*s* and **binary indexed trees** can accomplish this.
+Both **segment trees** and **binary indexed trees** can accomplish this.
## Segment Tree
@@ -128,14 +128,19 @@ Implementation is shorter than segment tree, but maybe more confusing at first g
### Implementations
+
+
+
+
based off above
-(implementation)
+
+
+
-
## Finding $k$-th Element
diff --git a/content/4_Gold/SP.mdx b/content/4_Gold/SP.mdx
index 4ac3c3a..e9a299b 100644
--- a/content/4_Gold/SP.mdx
+++ b/content/4_Gold/SP.mdx
@@ -3,7 +3,7 @@ id: sp
title: "Shortest Paths with Non-Negative Edge Weights"
author: Benjamin Qi
prerequisites:
- - Gold - Breadth First Search
+ - bfs
description: "Introduces Dijkstra's Algorithm for a single source shortest path as well as Floyd-Warshall for All-Pairs Shortest Path."
frequency: 3
---
diff --git a/content/4_Gold/SRQ.mdx b/content/4_Gold/SRQ.mdx
index a9071bf..ee333f9 100644
--- a/content/4_Gold/SRQ.mdx
+++ b/content/4_Gold/SRQ.mdx
@@ -5,6 +5,7 @@ author: Benjamin Qi
description: "Range queries for any associative operation over a static array."
frequency: 1
---
+
import { Problem } from "../models";
export const metadata = {
diff --git a/content/4_Gold/Springboards.mdx b/content/4_Gold/Springboards.mdx
index 570164f..dabff80 100644
--- a/content/4_Gold/Springboards.mdx
+++ b/content/4_Gold/Springboards.mdx
@@ -3,8 +3,7 @@ id: springboards
title: "Max Suffix Query with Insertions Only"
author: Benjamin Qi
prerequisites:
- - Silver - More with Maps & Sets
- - Silver - Amortized Analysis
+ - harder-ordered
description: "A solution to USACO Gold - Springboards."
frequency: 1
---
diff --git a/content/4_Gold/String_Hashing.mdx b/content/4_Gold/String_Hashing.mdx
index a4d4e74..839d36b 100644
--- a/content/4_Gold/String_Hashing.mdx
+++ b/content/4_Gold/String_Hashing.mdx
@@ -4,6 +4,8 @@ title: "String Hashing"
author: Benjamin Qi
description: "Quickly test equality of substrings with a small probability of failure."
frequency: 1
+prerequisites:
+ - intro-nt
---
import { Problem } from "../models";
diff --git a/src/components/markdown/ResourcesList.tsx b/src/components/markdown/ResourcesList.tsx
index bfa7609..93d264c 100644
--- a/src/components/markdown/ResourcesList.tsx
+++ b/src/components/markdown/ResourcesList.tsx
@@ -76,6 +76,7 @@ export const sourceTooltip = {
LC: 'LeetCode',
POI: 'Polish Olympiad in Informatics',
SO: 'StackOverflow',
+ KA: 'KhanAcademy',
'Old Bronze': 'USACO Platinum did not exist prior to 2015-16.',
'Old Silver': 'USACO Platinum did not exist prior to 2015-16.',
'Old Gold': 'USACO Platinum did not exist prior to 2015-16.',