diff --git a/content/1_Intro/Code_Conventions.mdx b/content/1_Intro/Code_Conventions.mdx index ef100f0..7a23561 100644 --- a/content/1_Intro/Code_Conventions.mdx +++ b/content/1_Intro/Code_Conventions.mdx @@ -2,7 +2,7 @@ id: code-con title: Code Conventions author: Nathan Wang, Benjamin Qi, Michael Cao, Nathan Chen -description: "The conventions that this guide uses" +description: "What the code we provide should look like." prerequisites: - expected - modules diff --git a/content/1_Intro/Debugging_Cpp.mdx b/content/1_Intro/Debugging.mdx similarity index 99% rename from content/1_Intro/Debugging_Cpp.mdx rename to content/1_Intro/Debugging.mdx index 588c42c..95ce8b6 100644 --- a/content/1_Intro/Debugging_Cpp.mdx +++ b/content/1_Intro/Debugging.mdx @@ -2,7 +2,7 @@ id: debugging title: Debugging author: Benjamin Qi, Aaron Chew -description: "Debugging your code is an extremely important skill. Here are some useful debugging-related tips." +description: "Identifying errors within your program and how to avoid them in the first place." --- ## Within Your Program diff --git a/content/1_Intro/Expected.mdx b/content/1_Intro/Expected.mdx index b3b50f6..25ae612 100644 --- a/content/1_Intro/Expected.mdx +++ b/content/1_Intro/Expected.mdx @@ -9,15 +9,13 @@ prerequisites: import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { general: [ new Problem("Bronze", "Promotion Counting", "591", "Very Easy"), new Problem("Bronze", "Word Processor", "987", "Very Easy"), new Problem("Bronze", "Square Pasture", "663", "Very Easy"), new Problem("Bronze", "Bucket Brigade", "939", "Very Easy"), ] - } }; The remainder of this guide assumes that you know the basics of how to code in one of the languages listed above, including the following topics: @@ -52,7 +50,7 @@ You may find the following resources helpful for familiarizing yourself with you The following require relatively little programming experience and no algorithmic knowledge. - + Also check the [CSES Introductory Problems](https://cses.fi/problemset/list/) up to and including "Palindrome Reorder." Once you're done with these, you should continue onto Bronze. diff --git a/content/1_Intro/Input_Output.mdx b/content/1_Intro/Input_Output.mdx index dfe2d8f..e382d5f 100644 --- a/content/1_Intro/Input_Output.mdx +++ b/content/1_Intro/Input_Output.mdx @@ -9,21 +9,13 @@ prerequisites: import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { cses: [ new Problem("CSES", "Weird Algorithm", "1068", "Very Easy"), ], fence: [ new Problem("Bronze", "Fence Painting", "567", "Very Easy"), ], - general: [ - new Problem("Bronze", "Promotion Counting", "591", "Very Easy"), - new Problem("Bronze", "Word Processor", "987", "Very Easy"), - new Problem("Bronze", "Square Pasture", "663", "Very Easy"), - new Problem("Bronze", "Bucket Brigade", "939", "Very Easy"), - ] - } }; @@ -38,7 +30,7 @@ export const metadata = { In most websites (such as CodeForces and CSES), input and output are **standard**. - + Note that this problem requires **64-bit integers**. @@ -170,7 +162,7 @@ public static void main(String[] args) { ## File I/O - + In USACO, input is read from a file called `problemname.in`. After the program is run, output must be printed to a file called `problemname.out`. Note that you'll have to rename the `.in` and `.out` files depending on the problem. For example, in the above problem you would use `paint.in` and `paint.out`. diff --git a/content/1_Intro/Lambda.mdx b/content/1_Intro/Lambda.mdx new file mode 100644 index 0000000..48c561d --- /dev/null +++ b/content/1_Intro/Lambda.mdx @@ -0,0 +1,101 @@ +--- +id: lambda +title: Lambda Expressions +author: Benjamin Qi +description: "Unnamed function objects capable of capturing variables in scope." +--- + + + + + + +## Introduction + + + reference + + + + + +Anything more beginner-friendly? + + + + + + + + + +## Recursive Lambdas + + + + + + +If we add the following from the link above in C++14: + +```cpp +namespace std { + +template +class y_combinator_result { + Fun fun_; +public: + template + explicit y_combinator_result(T &&fun): fun_(std::forward(fun)) {} + + template + decltype(auto) operator()(Args &&...args) { + return fun_(std::ref(*this), std::forward(args)...); + } +}; + +template +decltype(auto) y_combinator(Fun &&fun) { + return y_combinator_result>(std::forward(fun)); +} + +} // namespace std +``` + +Then we can have code like the following! + +```cpp +int main() { + cout << y_combinator([](auto gcd, int a, int b) -> int { + return b == 0 ? a : gcd(b, a % b); + })(20,30) << "\n"; // outputs 10 +} +``` + +Looks like [ecnerwal](https://codeforces.com/contest/1375/submission/86008510) uses these a lot ... + + + + + + + \ No newline at end of file diff --git a/content/1_Intro/Tips.mdx b/content/1_Intro/Tips.mdx index ef03a84..3ad1c74 100644 --- a/content/1_Intro/Tips.mdx +++ b/content/1_Intro/Tips.mdx @@ -2,7 +2,7 @@ id: cpp-tips title: C++ Tips & Tricks author: Benjamin Qi -description: "?" +description: "Things you should know about my template." --- ## `#include ` @@ -116,82 +116,4 @@ Instructions (Mac): ``` 4. Run `makeSnip` from terminal. It should display a list of the templates that will be added as snippets. - 5. If this succeeded, then typing `Temp` in a cpp file will automatically load my template! - - -## Lambda Expressions - - - - {' '} - - - -(describe more) - -### Recursive Lambdas - - - - - - -We can do stuff like the following in C++14: - -```cpp -namespace std { - -template -class y_combinator_result { - Fun fun_; -public: - template - explicit y_combinator_result(T &&fun): fun_(std::forward(fun)) {} - - template - decltype(auto) operator()(Args &&...args) { - return fun_(std::ref(*this), std::forward(args)...); - } -}; - -template -decltype(auto) y_combinator(Fun &&fun) { - return y_combinator_result>(std::forward(fun)); -} - -} // namespace std - -int main() { - cout << y_combinator([](auto gcd, int a, int b) -> int { - return b == 0 ? a : gcd(b, a % b); - })(20,30) << "\n"; // outputs 10 -} -``` - -Looks like [ecnerwal](https://codeforces.com/contest/1375/submission/86008510) uses these a lot ... - - - \ No newline at end of file + 5. If this succeeded, then typing `Temp` in a cpp file will automatically load my template! \ No newline at end of file diff --git a/content/1_Intro/USACO_Camp.mdx b/content/1_Intro/USACO_Camp.mdx index 21d44a9..f421a62 100644 --- a/content/1_Intro/USACO_Camp.mdx +++ b/content/1_Intro/USACO_Camp.mdx @@ -1,8 +1,8 @@ --- id: usaco-camp -title: Making USACO Camp +title: USACO Camp author: Benjamin Qi -description: "" +description: "Relevant Quora links (and more) regarding camp qualification." --- diff --git a/content/2_Bronze/Complete_Search.mdx b/content/2_Bronze/Complete_Search.mdx index 90dbe16..b914942 100644 --- a/content/2_Bronze/Complete_Search.mdx +++ b/content/2_Bronze/Complete_Search.mdx @@ -2,14 +2,13 @@ id: complete-search title: "Complete Search" author: Darren Yao -description: "Solving bronze problems with complete search, or checking all possible cases in the solution space." +description: "Solving bronze problems by checking all possible cases in the solution space." frequency: 4 --- import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { easier: [ new Problem("CSES", "Apple Division", "1623", "Intro|Very Easy", false, ["Recursion"], "all $2^n$ subsets"), new Problem("Bronze", "Diamond Collector", "639", "Easy", false, ["Nested Loop"], "fix the min"), // 99.9 @@ -30,7 +29,6 @@ export const metadata = { new Problem("Bronze", "Bull in a China Shop", "640", "Very Hard", false, [], "lots of WA on this one"), // 47.38 new Problem("Silver", "Field Reduction", "642", "Very Hard", false, [], ""), ], - } }; @@ -115,8 +113,8 @@ A couple notes: ### Easier - + ### Harder - + diff --git a/content/2_Bronze/Gen_Perm.mdx b/content/2_Bronze/Gen_Perm.mdx index 20d5951..ecfac77 100644 --- a/content/2_Bronze/Gen_Perm.mdx +++ b/content/2_Bronze/Gen_Perm.mdx @@ -2,7 +2,7 @@ id: gen-perm title: "Generating Permutations" author: Darren Yao, Sam Zhang -description: "Methods to generate all permutations of an array in C++ and Java (and Python?), a common technique associated with complete search." +description: "Methods to generate all permutations of an array, a common technique associated with complete search." frequency: 4 prerequisites: - complete-search @@ -10,8 +10,7 @@ prerequisites: import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { permSam: [ new Problem("CSES", "Creating Strings I", "1622", "Intro|Easy", false, [], "all perms of string"), ], @@ -22,10 +21,9 @@ export const metadata = { new Problem("CSES", "Chessboard and Queens", "1624", "Normal", false, [], "Recursively backtrack. See CSES book for more details."), new Problem("Bronze", "Livestock Lineup", "965", "Hard", false, ["permutations"], ""), // 91.95 ] - } }; - +
@@ -39,7 +37,7 @@ A **permutation** is a reordering of a list of elements. Some problems will ask This term is mentioned quite frequently: - + Think about how are words ordered in a dictionary. (In fact, this is where the term "lexicographical" comes from.) @@ -125,4 +123,4 @@ public class Test { ### Problems - \ No newline at end of file + \ No newline at end of file diff --git a/content/2_Bronze/Intro_DS.mdx b/content/2_Bronze/Intro_DS.mdx index 3203918..dea06b7 100644 --- a/content/2_Bronze/Intro_DS.mdx +++ b/content/2_Bronze/Intro_DS.mdx @@ -2,25 +2,26 @@ id: intro-ds title: Introduction to Data Structures author: Darren Yao, Benjamin Qi -description: "Basic data structures in multiple languages such as dynamic arrays." +description: "Basic data structures in multiple languages, dynamic arrays and sorting." frequency: 4 --- import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { bubble: [ - new Problem("HR", "Bubble Sort", "https://www.hackerrank.com/challenges/ctci-bubble-sort/problem", "Easy", false, [], "O(N^2)"), + new Problem("HR", "Bubble Sort", "https://www.hackerrank.com/challenges/ctci-bubble-sort/problem", "Very Easy", false, [], ""), ], easy: [ new Problem("CSES", "Distinct Numbers", "1621", "Easy"), new Problem("CSES", "Stick Lengths", "1074", "Normal", false, [], "Spoiler: Optimal length is median"), - new Problem("Silver", "Teleportation", "812", "Very Hard", false, [], ""), ], - } }; + + module is based off this vectors, strings @@ -279,20 +280,29 @@ for(auto element : v) { ## Sorting - + -**Sorting** refers to arranging items in some particular order. You do not need to know how to sort an array in $O(N\log N)$ time for Bronze, but you should be aware of how to use built-in methods to sort a (possibly dynamic) array. +**Sorting** refers to arranging items in some particular order. + + + + + + + +You should know how to use built-in methods to sort a (possibly dynamic) array. -In order to sort a dynamic array, use `sort(v.begin(), v.end())` (or `sort(begin(v),end(v))`), whereas static arrays require `sort(arr, arr + N)` where $N$ is the number of elements to be sorted. The default sort function sorts the array in ascending order. + + can stop before comparison operators, which are covered in silver + reference + first two related to sorting + - - [std::sort](https://en.cppreference.com/w/cpp/algorithm/sort) - - [std::stable\_sort](http://www.cplusplus.com/reference/algorithm/stable_sort/) - - [Golovanov399 - C++ Tricks](https://codeforces.com/blog/entry/74684) - - first two related to sorting +In order to sort a dynamic array, use `sort(v.begin(), v.end())` (or `sort(begin(v),end(v))`), whereas static arrays require `sort(arr, arr + N)` where $N$ is the number of elements to be sorted. The default sort function sorts the array in ascending order. @@ -322,4 +332,4 @@ Two ways to avoid this: ## Problems - + diff --git a/content/2_Bronze/Intro_Graphs.mdx b/content/2_Bronze/Intro_Graphs.mdx index ddd1d70..23d2387 100644 --- a/content/2_Bronze/Intro_Graphs.mdx +++ b/content/2_Bronze/Intro_Graphs.mdx @@ -8,8 +8,7 @@ frequency: 2 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { general: [ new Problem("Silver", "Grass Planting", "894", "Normal", false, ["tree"]), new Problem("Bronze", "The Great Revegetation", "916", "Hard", false, []), @@ -19,7 +18,6 @@ export const metadata = { new Problem("Bronze", "Swapity Swap", "1013", "Hard", false, ["permutation"], "Hint: One option is to keep swapping until the permutation returns to its original state (but can you do better?)."), new Problem("Bronze", "Cow Evolution", "941", "Hard", false, [], ""), ] - } }; Graphs can be used to represent many things, from images to wireless signals, but one of the simplest analogies is to a map. Consider a map with several cities and bidirectional roads connecting the cities. Some problems relating to graphs are: @@ -45,4 +43,4 @@ Both of these tasks will be covered in higher divisions. For now, it suffices to ## Problems - \ No newline at end of file + \ No newline at end of file diff --git a/content/2_Bronze/Intro_Greedy.mdx b/content/2_Bronze/Intro_Greedy.mdx index 1e2ef55..b9b3585 100644 --- a/content/2_Bronze/Intro_Greedy.mdx +++ b/content/2_Bronze/Intro_Greedy.mdx @@ -2,14 +2,13 @@ id: intro-greedy title: Introduction to Greedy Algorithms author: Michael Cao, Darren Yao -description: "Selecting the optimal choice at each step in your algorithm without looking at the solution space as a whole." +description: "Selecting the choice that seems to be the best at the moment at every step of your algorithm." frequency: 2 --- import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { tutorial: [ new Problem("Bronze", "Mad Scientist", "1012", "Normal", false, [], ""), ], @@ -17,7 +16,6 @@ export const metadata = { new Problem("Bronze", "Cow Tipping", "689", "Hard", false, [], "Cells in the last row and column can be toggled uniquely. Toggle the appropriate ones and then recurse to the rectangle in the previous row/column, and solve the same way."), new Problem("Bronze", "Race", "989", "Very Hard", false, [], "Greedily increment/decrement Bessies speed to fit the conditions until her total distance exceeds K."), ], - } }; ## Ad Hoc @@ -141,7 +139,7 @@ If we use greedy based on highest value first, we choose item A and then we are Try to come up with a greedy algorithm for the USACO Bronze problem "Mad Scientist." - + @@ -165,7 +163,7 @@ Sometimes, if the algorithm is easy enough to implement, you don't even need to ## Problems - + diff --git a/content/2_Bronze/Pairs_Tuples.mdx b/content/2_Bronze/Pairs_Tuples.mdx index 72ccf1e..70ab3c3 100644 --- a/content/2_Bronze/Pairs_Tuples.mdx +++ b/content/2_Bronze/Pairs_Tuples.mdx @@ -2,7 +2,7 @@ id: pairs-tuples title: Pairs & Tuples author: Benjamin Qi, Nathan Wang, Darren Yao, Abutalib Namazov -description: "Introduction to pairs, which allow you to store two objects (possibly of different types) as a single unit, as well as tuples, which are a generalization of pairs." +description: "Storing two or more objects (possibly of different types) as a single unit." prerequisites: - intro-ds --- @@ -55,18 +55,17 @@ If you sort one of $x_i$ and $y_i$ without considering the other, the points wil Example: ```cpp -#include - +#include using namespace std; int main() { - pair myPair1 = make_pair("Testing", 123); - cout << myPair1.first << " " << myPair1.second << endl; // Testing 123 - myPair1.first = "It is possible to edit pairs after declaring them"; - cout << myPair1.first << " " << myPair1.second << endl; - - pair myPair2 = {"Testing", "curly braces"}; - cout << myPair2.first << " " << myPair2.second << endl; // Testing curly braces + pair myPair1 = make_pair("Testing", 123); + cout << myPair1.first << " " << myPair1.second << endl; // Testing 123 + myPair1.first = "It is possible to edit pairs after declaring them"; + cout << myPair1.first << " " << myPair1.second << endl; + + pair myPair2 = {"Testing", "curly braces"}; + cout << myPair2.first << " " << myPair2.second << endl; // Testing curly braces } /* Output @@ -99,23 +98,20 @@ This is not frequently used by competitive programmers, but it is good to know a Example: ```cpp -#include -#include /// needs additional library -#include - +#include using namespace std; int main() { - int a = 3, b = 4, c = 5; - tuple t = tie(a, b, c); - cout << get<0>(t) << " " << get<1>(t) << " " << get<2>(t) << endl; - get<0>(t) = 7; - cout << get<0>(t) << " " << get<1>(t) << " " << get<2>(t) << endl; + int a = 3, b = 4, c = 5; + tuple t = tie(a, b, c); + cout << get<0>(t) << " " << get<1>(t) << " " << get<2>(t) << endl; + get<0>(t) = 7; + cout << get<0>(t) << " " << get<1>(t) << " " << get<2>(t) << endl; - tuple tp2 = make_tuple("Hello", "world", 100); - string s1, s2; int x; - tie(s1, s2, x) = tp2; - cout << s1 << " " << s2 << " " << x << endl; + tuple tp2 = make_tuple("Hello", "world", 100); + string s1, s2; int x; + tie(s1, s2, x) = tp2; + cout << s1 << " " << s2 << " " << x << endl; } /* Output * 3 4 5 @@ -139,12 +135,12 @@ Example from CPH: using namespace std; int main() { - vector> v; - v.push_back({1,5}); - v.push_back({2,3}); - v.push_back({1,2}); - sort(v.begin(), v.end()); - for (pair p: v) cout << p.first << " " << p.second << "\n"; + vector> v; + v.push_back({1,5}); + v.push_back({2,3}); + v.push_back({1,2}); + sort(v.begin(), v.end()); + for (pair p: v) cout << p.first << " " << p.second << "\n"; } /* Output: diff --git a/content/2_Bronze/Rect_Geo.mdx b/content/2_Bronze/Rect_Geo.mdx index f697e5d..ca83c39 100644 --- a/content/2_Bronze/Rect_Geo.mdx +++ b/content/2_Bronze/Rect_Geo.mdx @@ -7,17 +7,15 @@ frequency: 2 --- import { Problem } from "../models"; -export const metadata = { - problems: { - blocked: [ - new Problem("Bronze", "Blocked Billboard", "759", "Easy", false, ["rect"]), - ], - general: [ - new Problem("Bronze", "Square Pasture", "663", "Very Easy", false, ["rect"]), - new Problem("Bronze", "Blocked Billboard II", "783", "Easy", false, ["rect"]), - new Problem("CF", "Div. 3 C - White Sheet", "contest/1216/problem/C", "Normal", false, ["rect"],"See this code (TODO; codeforces is down) for a nice implementation using the Java Rectangle class."), - ] - } +export const problems = { + blocked: [ + new Problem("Bronze", "Blocked Billboard", "759", "Easy", false, ["rect"]), + ], + general: [ + new Problem("Bronze", "Square Pasture", "663", "Very Easy", false, ["rect"]), + new Problem("Bronze", "Blocked Billboard II", "783", "Easy", false, ["rect"]), + new Problem("CF", "Div. 3 C - White Sheet", "contest/1216/problem/C", "Normal", false, ["rect"],"See this code (TODO; codeforces is down) for a nice implementation using the Java Rectangle class."), + ] }; @@ -30,7 +28,7 @@ Most only include two or three squares or rectangles, in which case you can simp ## Example: Blocked Billboard - + ### Naive Solution @@ -212,4 +210,4 @@ int main(){ ## Problems - + diff --git a/content/2_Bronze/Simulation.mdx b/content/2_Bronze/Simulation.mdx index 3e6cc94..9f51e74 100644 --- a/content/2_Bronze/Simulation.mdx +++ b/content/2_Bronze/Simulation.mdx @@ -8,8 +8,7 @@ frequency: 4 import { Problem } from "../models" -export const metadata = { - problems: { +export const problems = { easier: [ new Problem("Bronze", "Shell Game", "891", "Easy", false, ["Nested Loop"]), // 99.93 new Problem("Bronze", "Mixing Milk", "855", "Easy", false, ["Single Loop"], "just pour 100 times"), // 99.87 @@ -26,7 +25,6 @@ export const metadata = { new Problem("Bronze", "Milk Measurement", "761", "Hard"), // 95.97 new Problem("Bronze", "Angry Cows", "592", "Hard", false, [], ""), // 94.15 ] - } }; @@ -186,8 +184,8 @@ pw.close(); // flush the output ### Easier - + ### Harder - + diff --git a/content/2_Bronze/Time_Comp.mdx b/content/2_Bronze/Time_Comp.mdx index a6e58db..af58746 100644 --- a/content/2_Bronze/Time_Comp.mdx +++ b/content/2_Bronze/Time_Comp.mdx @@ -8,7 +8,7 @@ description: "Evaluating a program's time complexity, or how fast your program r module is based off this Intro and examples - More in-depth. In particular, 5.2 gives a formal definition of Big O. + More in-depth. In particular, 5.2 gives a formal definition of Big O.
@@ -326,11 +326,21 @@ for i in range(m): ## Constant Factor -The **constant factor** of an algorithm refers to the coefficient of the complexity of an algorithm. If an algorithm runs in $O(kn)$ time, where $k$ is a constant and $n$ is the input size, then the "constant factor" would be $k$. (Ben - this is not a great definition) +The **constant factor** of an algorithm refers to the coefficient of the complexity of an algorithm. If an algorithm runs in $O(kn)$ time, where $k$ is a constant and $n$ is the input size, then the "constant factor" would be $k$. - + -Normally when using the big-O notation, we ignore the constant factor: $O(3n) = O(n)$. This is fine most of the time, but sometimes we have an algorithm that just barely gets TLE, perhaps by just a few hundred milliseconds. When this happens, it is worth optimizing the constant factor of our algorithm. For example, if our code currently runs in $O(n^2)$ time, perhaps we can modify our code to make it run in $O(n^2/32)$ by using a bitset. (Of course, with big-O notation, $O(n^2) = O(n^2/32)$.) +this is a terrible definition + + + +Normally when using big-O notation, we ignore the constant factor: $O(3n) = O(n)$. This is fine most of the time, but sometimes we have an algorithm that just barely gets TLE, perhaps by just a few hundred milliseconds. When this happens, it is worth optimizing the constant factor of our algorithm. For example, if our code currently runs in $O(n^2)$ time, perhaps we can modify our code to make it run in $O(n^2/32)$ by using a bitset. (Of course, with big-O notation, $O(n^2) = O(n^2/32)$.) + + + +fix math + + For now, don't worry about how to optimize constant factors -- just be aware of them. diff --git a/content/2_Bronze/Unordered.mdx b/content/2_Bronze/Unordered.mdx index c56c0d6..073fd5b 100644 --- a/content/2_Bronze/Unordered.mdx +++ b/content/2_Bronze/Unordered.mdx @@ -2,7 +2,7 @@ id: unordered title: Unordered Maps & Sets author: Darren Yao, Benjamin Qi -description: "An introduction to unordered maps and sets in multiple languages, two powerful data structures can help simplify bronze problems." +description: "?" frequency: 2 prerequisites: - pairs-tuples @@ -10,8 +10,7 @@ prerequisites: import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { dis: [ new Problem("CSES", "Distinct Numbers", "1621", "Easy", false, [], "Store every number in a set and print the size."), ], @@ -23,7 +22,6 @@ export const metadata = { new Problem("Bronze", "Where Am I?", "964", "Easy", false, [], "Store all substrings in a map of , and then find the longest length such that no substring of that length appears twice."), new Problem("Silver", "Cities & States", "667", "Hard", false, [], "Store two maps of counts for the first two letters of a city and state code, then iterate over the cities and use the maps to efficently query for the corresponding counts."), ], - } }; @@ -46,7 +44,7 @@ Both Java and C++ contain two versions of sets and maps; one in which the keys a ## Sets - + @@ -105,7 +103,7 @@ for(int element : set){ ## Maps - + @@ -149,6 +147,8 @@ System.out.println(map.containsKey(1)); // true ### Custom Hashing +There is no built in method for hashing pairs or vectors. Namely, `unordered_set>` does not work. In this case, we can use an [ordered map](../silver/intro-ordered) (which supports all of the functions used in the code above) or declare our own hash function. + @@ -197,7 +197,7 @@ int main() { } ``` -However, this hash function is quite bad; if we insert $(0,0), (1,1), (2,2) \ldots$ then they will all be mapped to the same bucket. +However, this hash function is quite bad; if we insert $(0,0), (1,1), (2,2) \ldots$ then they will all be mapped to the same bucket (so it would easily be **hacked**). @@ -232,9 +232,11 @@ Essentially use `unordered_map` defined in the blog above ```cpp struct chash { /// use most bits rather than just the lowest ones const uint64_t C = ll(2e18*PI)+71; // large odd number - const int RANDOM = rng(); - ll operator()(ll x) const { /// https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html - return __builtin_bswap64((x^RANDOM)*C); } + const int RANDOM = rng(); // random 32-bit number + ll operator()(ll x) const { + // https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html + return __builtin_bswap64((x^RANDOM)*C); + } }; template using um = unordered_map; ``` @@ -247,8 +249,8 @@ template using um = unordered_map; ### `gp_hash_table` -Mentioned in several of the links above. See Gold for dtails. +Mentioned in several of the links above. See [Gold](../gold/faster-hashmap) for details. ## Problems - + diff --git a/content/3_Silver/2P.mdx b/content/3_Silver/2P.mdx new file mode 100644 index 0000000..3ebbbbd --- /dev/null +++ b/content/3_Silver/2P.mdx @@ -0,0 +1,39 @@ +--- +id: 2P +title: "Two Pointers" +author: Darren Yao +prerequisites: +description: "Refers to iterating two monotonic pointers across an array to search for a pair of indices satisfying some condition in linear time." +frequency: 2 +--- + +import { Problem } from "../models"; + +export const problems = { + sample: [ + new Problem("CSES", "Sum of Two Values", "1141", "Easy", false, []), + new Problem("CSES", "Subarray Sums I", "1660", "Easy", false, [], ""), + ], + ad: [ + new Problem("CSES", "Sum of Three Values", "1641", "Easy", false, [], ""), + new Problem("Silver", "Diamond Collector", "643", "Easy", false, ["2P", "Sorting"], ""), + new Problem("Silver", "Sleepy Cow Herding", "918", "Normal", false, ["2P", "Sorting"], ""), + new Problem("CF", "Books", "problemset/problem/279/B", "Normal", false, []), + new Problem("CF", "Cellular Network", "problemset/problem/702/C", "Normal", false, []), + new Problem("CF", "USB vs. PS/2", "problemset/problem/762/B", "Normal", false, []), + new Problem("CF", "K-Good Segment", "problemset/problem/616/D", "Normal", false, []), + new Problem("CF", "Garland", "problemset/problem/814/C", "Normal", false, []), + new Problem("CF", "Jury Meeting", "problemset/problem/853/B", "Normal", false, []), + ], +}; + + + + + solutions to the problems above + + + +## Problems + + \ No newline at end of file diff --git a/content/3_Silver/Binary_Search_Ans.mdx b/content/3_Silver/Binary_Search_Ans.mdx index cf45396..b6dc707 100644 --- a/content/3_Silver/Binary_Search_Ans.mdx +++ b/content/3_Silver/Binary_Search_Ans.mdx @@ -10,8 +10,7 @@ frequency: 3 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { ex: [ new Problem("CF", "Div 2 C - Maximum Median", "contest/1201/problem/C", "Easy", false, [], ""), ], @@ -35,7 +34,6 @@ export const metadata = { new Problem("CF", "Level Generation", "problemset/problem/818/F", "Hard", false, [], "first find out which is the best way to construct the graph, then it's possible to see that the number of edges increase for some range and then decrease; so, using binary search find the last i such that f(i-1)<=f(i)"), new Problem("CF", "Packmen", "contest/847/problem/E", "Hard", false, [], "binary search on time and check if packmen can eat all keeping left and right endpoints"), ], - } }; @@ -154,7 +152,7 @@ static long search(){ ## Example: Maximum Median - + **Statement:** Given an array $\texttt{arr}$ of $n$ integers, where $n$ is odd, we can perform the following operation on it $k$ times: take any element of the array and increase it by $1$. We want to make the median of the array as large as possible after $k$ operations. @@ -261,8 +259,8 @@ static boolean check(long x){ ## USACO Problems - + ## General Problems - + diff --git a/content/3_Silver/Binary_Search_Sorted.mdx b/content/3_Silver/Binary_Search_Sorted.mdx index ee1a896..49099d0 100644 --- a/content/3_Silver/Binary_Search_Sorted.mdx +++ b/content/3_Silver/Binary_Search_Sorted.mdx @@ -10,8 +10,7 @@ frequency: 2 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { bubble: [ new Problem("HR", "Bubble Sort", "https://www.hackerrank.com/challenges/ctci-bubble-sort/problem", "Easy", false, [], "O(N^2)"), new Problem("Silver", "Out of Sorts", "834", "Very Hard", false, []), @@ -19,7 +18,6 @@ export const metadata = { count: [ new Problem("Silver", "Counting Haybales", "666", "Normal", false, []), ], - } }; Suppose that we want to find an element in a sorted array of size $N$ in $O(\log N)$ time. We can do this with [**binary search**](https://en.wikipedia.org/wiki/Binary_search_algorithm); each iteration of the binary search cuts the search space in half, so the algorithm tests $O(\log N)$ values. This is efficient and much better than testing every element in an array. @@ -60,7 +58,7 @@ Suppose that we want to find an element in a sorted array of size $N$ in $O(\log A related topic is **coordinate compression**, which takes some points and reassigns them to remove wasted space. - + > Farmer John has just arranged his $N$ haybales $(1\le N \le 100,000)$ at various points along the one-dimensional road running across his farm. To make sure they are spaced out appropriately, please help him answer $Q$ queries ($1 \le Q \le 100,000$), each asking for the number of haybales within a specific interval along the road. diff --git a/content/3_Silver/Custom_Cpp_STL.mdx b/content/3_Silver/Custom_Cpp_STL.mdx index c6498e9..debb4ce 100644 --- a/content/3_Silver/Custom_Cpp_STL.mdx +++ b/content/3_Silver/Custom_Cpp_STL.mdx @@ -5,12 +5,14 @@ author: Siyong Huang, Benjamin Qi prerequisites: - sorting-custom - intro-ordered + - lambda description: "More ways to write custom comparators in C++ and incorporating them into STL objects." frequency: 1 --- Covers all of this material. + reference
@@ -45,6 +47,12 @@ int main() { ## Comparator + + + + +### With a Function + ```cpp #include using namespace std; @@ -66,20 +74,14 @@ int main() { } ``` - +You can also use the following syntax to declare set `v` using a function: -You can also use the following syntax to declare set `v` using a function +`set v(cmp);` -`set v(cmp);` - - - -Lambda expressions also work: +### With Lambda Expressions ```cpp auto cmp = [](const Edge& x, const Edge& y) { return x.w < y.w; }; -//The real type of cmp is function -//auto is used for short int main() { int M = 4; @@ -92,13 +94,11 @@ int main() { } ``` - - -You can also use the following syntax to declare set `v` using a lambda +You can also use the following syntax to declare set `v` using a lambda: `set v(cmp);` - +though `decltype(cmp)` is **not** actually equivalent to `bool(*)(const Edge&,const Edge&)`. ## Functors @@ -191,15 +191,4 @@ map> b; priority_queue,greater> c; ``` - - -In C++, priority queues are sorted in decreasing order. -Specifically, larger elements have higher 'priority' and are popped first. - -If you want smaller elements to be at the front of the queue, two ways are listed below - -1. Overload the (`<`) operator to output the opposite effect. - -2. Overload the (`>`) operator properly and use the (`greater`) functor. - - +Using a custom comparator for priority queues is especially common. Again, a C++ priority queue will pop its largest element by default, while the above code will cause one to pop its smallest element instead. \ No newline at end of file diff --git a/content/3_Silver/DFS.mdx b/content/3_Silver/DFS.mdx index acdd898..1b4fb52 100644 --- a/content/3_Silver/DFS.mdx +++ b/content/3_Silver/DFS.mdx @@ -4,14 +4,13 @@ title: Depth First Search (DFS) author: Siyong Huang prerequisites: - intro-graphs -description: "A way to recursively traverse through a graph." +description: "A way to recursively traverse a graph." frequency: 4 --- import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("CSES", "Building Roads", "1666", "Intro|Easy", false, ["DFS"]), ], @@ -49,7 +48,6 @@ export const metadata = { new Problem("Silver", "The Great Revegetation", "920", "Easy", false, ["Bipartite"]), new Problem("Silver", "Clock Tree", "1016", "Hard", false, []), ], - } }; ## Resources @@ -66,7 +64,7 @@ export const metadata = { ## Counting Connected Components - + ### Implementation @@ -128,7 +126,7 @@ public static int count_components() ### Problems - + ## Tree Problems @@ -192,14 +190,14 @@ public static void dfs(int node) ### Problems - + ## Graph Two-Coloring *Graph two-coloring* refers to assigning a boolean value to each node of the graph, dictated by the edge configuration. The most common example of a two-colored graph is a *bipartite graph*, in which each edge connects two nodes of opposite colors. - + ### Resources @@ -268,4 +266,4 @@ public static void dfs(int node) ### Problems - + diff --git a/content/3_Silver/Flood_Fill.mdx b/content/3_Silver/Flood_Fill.mdx index a7c61e7..8d89ee3 100644 --- a/content/3_Silver/Flood_Fill.mdx +++ b/content/3_Silver/Flood_Fill.mdx @@ -10,8 +10,7 @@ frequency: 3 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("LC", "Flood Fill", "https://leetcode.com/problems/flood-fill/", "Intro|Easy", false, []), new Problem("CSES", "Counting Rooms", "1192", "Easy", false, []), @@ -29,10 +28,9 @@ export const metadata = { new Problem("Silver", "Snow Boots", "811", "Hard", false, []), new Problem("Silver", "Mooyo Mooyo", "860", "Hard", false, []), ], - } }; - +
@@ -208,4 +206,4 @@ static void floodfill(int r, int c, int color){ ## Problems - \ No newline at end of file + \ No newline at end of file diff --git a/content/3_Silver/Func_Graphs.mdx b/content/3_Silver/Func_Graphs.mdx index 91e4e3d..42c619b 100644 --- a/content/3_Silver/Func_Graphs.mdx +++ b/content/3_Silver/Func_Graphs.mdx @@ -4,15 +4,14 @@ title: Functional Graphs author: Siyong Huang prerequisites: - dfs -description: "Properties of a functional graphs, directed graphs in which every vertex has exactly one outgoing edge." +description: "Properties of functional graphs, directed graphs in which every vertex has exactly one outgoing edge." frequency: 1 --- import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("CF", "Div 2 B - Badge", "contest/1020/problem/B", "Very Easy", false, ["Func Graph"], "Try to solve the problem in $O(N)$!"), ], @@ -26,14 +25,13 @@ export const metadata = { new Problem("POI", "Frog", "https://szkopul.edu.pl/problemset/problem/qDH9CkBHZKHY4vbKRBlXPrA7/site/?key=statement", "Hard", false, [], ""), new Problem("ojuz", "Space Pirate", "JOI14_space_pirate", "Very Hard", false, ["Graphs"], "One of the most difficult problems of all time. Build a tree with a single back edge. Break into three cases: path -> other cycle, path -> subtree, path -> non-subtree. Then perform some black magic."), ], - } }; ## Functional Graphs We'll consider graphs like the one presented in this problem: - + < br/> @@ -122,4 +120,4 @@ pair detect_cycle(int *next, int start_node) //return pair(length of c ### Problems - + diff --git a/content/3_Silver/Greedy.mdx b/content/3_Silver/Greedy.mdx index 3bd67bd..5c9987c 100644 --- a/content/3_Silver/Greedy.mdx +++ b/content/3_Silver/Greedy.mdx @@ -12,8 +12,7 @@ frequency: 3 import {Problem} from "../models" -export const metadata = { - problems: { +export const problems = { movie: [ new Problem("CSES", "Movie Festival", "1629", "Easy", false, [], ""), ], @@ -42,7 +41,6 @@ export const metadata = { new Problem("CF", "Kayaking", "contest/863/problem/B", "?", false, [], "Huffman Coding?"), new Problem("CF", "New Year and Three Musketeers", "contest/611/problem/E", "Hard", false, [], "needs maps"), ] - } }; @@ -64,7 +62,7 @@ Here, we'll focus on problems where some sorting step is involved. ## Example: The Scheduling Problem - + There are $N$ events, each described by their starting and ending times. You can only attend one event at a time, and if you choose to attend an event, you must attend the entire event. Traveling between events is instantaneous. What's the maximum number of events you can attend? @@ -177,12 +175,12 @@ pw.close(); ## CSES Problems - + ## USACO Problems - + ## Other Problems - \ No newline at end of file + \ No newline at end of file diff --git a/content/3_Silver/Harder_Ordered.mdx b/content/3_Silver/Harder_Ordered.mdx index a856d78..e503ca2 100644 --- a/content/3_Silver/Harder_Ordered.mdx +++ b/content/3_Silver/Harder_Ordered.mdx @@ -4,129 +4,12 @@ title: "Harder Problems with Ordered Sets" author: Benjamin Qi prerequisites: - custom-cpp-stl - - stacks-queues description: "More advanced uses of ordered sets with example problems." frequency: 2 --- import { Problem } from "../models"; -export const metadata = { - problems: { - sample: [ - new Problem("CSES", "Bit Inversions", "1188", "Normal", false, []), - ], - general: [ - new Problem("Silver", "Milk Measurement", "763", "Normal", false, []), - new Problem("Silver", "Convention II", "859", "Normal", false, []), - new Problem("Gold", "Snow Boots", "813", "Normal", false, []), - new Problem("CF", "Jury Marks", "contest/831/problem/C", "Hard", false, [], "Hard, would recommend skipping (1700 on CF)"), - new Problem("CF", "Mahmoud & Ehab & Function", "contest/862/problem/E", "Hard", false, [], "Hard, do not attempt until Gold/Plat (2100 on CF)"), - new Problem("CF", "Tournament", "contest/878/problem/C", "Very Hard", false, [], "First solve problem for $n$-th tournament only. Extremely hard, do not attempt (2700 on CF)"), - ] - } +export const problems = { }; - -## Example: Using Iterators - - - - - -```cpp -#include -using namespace std; - -#define sz(x) (x).size() - -string s; -int m; -multiset ans, ret; - -void modify(int x) { - if (x == 0 || x == sz(s)) return; - auto it = ans.find(x); - if (it != end(ans)) { - int a = *prev(it), b = *next(it); - ret.erase(ret.find(x-a)), ret.erase(ret.find(b-x)); - ret.insert(b-a); - ans.erase(it); - } else { - it = ans.insert(x); - int a = *prev(it), b = *next(it); - ret.erase(ret.find(b-a)); - ret.insert(x-a), ret.insert(b-x); - } -} - -int main() { - ios_base::sync_with_stdio(0); cin.tie(0); - cin >> s >> m; - ans.insert(0); ans.insert(sz(s)); - for (int i = 0; i < sz(s)-1; ++i) - if (s[i] != s[i+1]) ans.insert(i+1); - for (auto it = ans.begin(); next(it) != ans.end(); it ++) - ret.insert(*next(it)-*it); - for (int i = 0; i < m; ++i) { - int x; cin >> x; - modify(x-1); modify(x); - cout << *ret.rbegin() << " "; - } -} -``` - -
- -Note that `multiset` has a high constant factor, so replacing `ret` with an array and a `priority_queue` reduces the runtime by a factor of 2. - -```cpp -#include -using namespace std; - -#define sz(x) (x).size() - -string s; -int m; -set ans; -priority_queue ret; -int cnt[200005]; - -void ad(int x) { cnt[x] ++; ret.push(x); } -void modify(int x) { - if (x == 0 || x == sz(s)) return; - auto it = ans.find(x); - if (it != end(ans)) { - int a = *prev(it), b = *next(it); ans.erase(it); - cnt[x-a] --, cnt[b-x] --; ad(b-a); - } else { - it = ans.insert(x).first; - int a = *prev(it), b = *next(it); - cnt[b-a] --, ad(x-a), ad(b-x); - } -} - -int main() { - ios_base::sync_with_stdio(0); cin.tie(0); - cin >> s >> m; - ans.insert(0); ans.insert(sz(s)); - for (int i = 0; i < sz(s)-1; ++i) - if (s[i] != s[i+1]) ans.insert(i+1); - for (auto it = ans.begin(); next(it) != ans.end(); it ++) - ad(*next(it)-*it); - for (int i = 0; i < m; ++i) { - int x; cin >> x; - modify(x-1); modify(x); - while (!cnt[ret.top()]) ret.pop(); - cout << ret.top() << " "; - } -} -``` - -
- - - -## Problems - - diff --git a/content/3_Silver/Intro_Ordered.mdx b/content/3_Silver/Intro_Ordered.mdx index 7e60a9a..cdc351d 100644 --- a/content/3_Silver/Intro_Ordered.mdx +++ b/content/3_Silver/Intro_Ordered.mdx @@ -3,20 +3,29 @@ id: intro-ordered title: "Introduction to Ordered Sets" author: Darren Yao, Benjamin Qi prerequisites: - - Bronze - Unordered Maps & Sets -description: "A data structure that supports quick insertion and deletion by maintaining keys in sorted order." + - unordered +description: "Data structures that maintain keys in sorted order." frequency: 2 --- import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { standard: [ new Problem("CSES", "Concert Tickets", "1091", "Easy", false, ["iterators"], "just do upper_bound"), new Problem("CSES", "Traffic Lights", "1163", "Normal", false, ["set"], "just insert into set one at a time"), ], - } + sample: [ + new Problem("CSES", "Bit Inversions", "1188", "Normal", false, []), + ], + general: [ + new Problem("Silver", "Milk Measurement", "763", "Normal", false, []), + new Problem("Silver", "Convention II", "859", "Normal", false, []), + new Problem("Gold", "Snow Boots", "813", "Normal", false, []), + new Problem("CF", "Jury Marks", "contest/831/problem/C", "Hard", false, [], "Hard, would recommend skipping (1700 on CF)"), + new Problem("CF", "Mahmoud & Ehab & Function", "contest/862/problem/E", "Hard", false, [], "Hard, do not attempt until Gold/Plat (2100 on CF)"), + new Problem("CF", "Tournament", "contest/878/problem/C", "Very Hard", false, [], "First solve problem for $n$-th tournament only. Extremely hard, do not attempt (2700 on CF)"), + ] }; @@ -129,7 +138,7 @@ System.out.println(map.lowerKey(3)); // ERROR ## Multisets -Lastly, there is the **multiset**, which is essentially a sorted set that allows multiple copies of the same element. +A **multiset** is a sorted set that allows multiple copies of the same element. @@ -189,6 +198,54 @@ static void remove(int x){ +## Priority Queues + +A **priority queue** supports the following operations: insertion of elements, deletion of the element considered highest priority, and retrieval of the highest priority element, all in $O(\log N)$ time according to the number of elements in the priority queue. Like sets, priority is based on a **comparator function**. + +Of course, all of these functions are supported by multisets, but priority queues are simpler (so they are much faster). + + + + + +### [C++](http://www.cplusplus.com/reference/queue/priority_queue/) + +```cpp +priority_queue pq; +pq.push(7); // [7] +pq.push(2); // [2, 7] +pq.push(1); // [1, 2, 7] +pq.push(5); // [1, 2, 5, 7] +cout << pq.top() << endl; // 7 +pq.pop(); // [1, 2, 5] +pq.pop(); // [1, 2] +pq.push(6); // [1, 2, 6] +``` + + + + + +### Java + +In Java, we delete and retrieve the element of **lowest** rather than highest priority. + +```java +PriorityQueue pq = new PriorityQueue(); +pq.add(7); // [7] +pq.add(2); // [7, 2] +pq.add(1); // [7, 2, 1] +pq.add(5); // [7, 5, 2, 1] +System.out.println(pq.peek()); // 1 +pq.poll(); // [7, 5, 2] +pq.poll(); // [7, 5] +pq.add(6); // [7, 6, 5] +``` + + + + + ## Using Iterators @@ -198,18 +255,116 @@ static void remove(int x){ next(), prev(), ++, -- + - - - - - -
-## Standard +## Easy - \ No newline at end of file + + +## Example: Using Iterators + + + + + +```cpp +#include +using namespace std; + +#define sz(x) (x).size() + +string s; +int m; +multiset ans, ret; + +void modify(int x) { + if (x == 0 || x == sz(s)) return; + auto it = ans.find(x); + if (it != end(ans)) { + int a = *prev(it), b = *next(it); + ret.erase(ret.find(x-a)), ret.erase(ret.find(b-x)); + ret.insert(b-a); + ans.erase(it); + } else { + it = ans.insert(x); + int a = *prev(it), b = *next(it); + ret.erase(ret.find(b-a)); + ret.insert(x-a), ret.insert(b-x); + } +} + +int main() { + ios_base::sync_with_stdio(0); cin.tie(0); + cin >> s >> m; + ans.insert(0); ans.insert(sz(s)); + for (int i = 0; i < sz(s)-1; ++i) + if (s[i] != s[i+1]) ans.insert(i+1); + for (auto it = ans.begin(); next(it) != ans.end(); it ++) + ret.insert(*next(it)-*it); + for (int i = 0; i < m; ++i) { + int x; cin >> x; + modify(x-1); modify(x); + cout << *ret.rbegin() << " "; + } +} +``` + +
+ +Note that `multiset` has a high constant factor, so replacing `ret` with an array and a `priority_queue` reduces the runtime by a factor of 2. + +```cpp +#include +using namespace std; + +#define sz(x) (x).size() + +string s; +int m; +set ans; +priority_queue ret; +int cnt[200005]; + +void ad(int x) { cnt[x] ++; ret.push(x); } +void modify(int x) { + if (x == 0 || x == sz(s)) return; + auto it = ans.find(x); + if (it != end(ans)) { + int a = *prev(it), b = *next(it); ans.erase(it); + cnt[x-a] --, cnt[b-x] --; ad(b-a); + } else { + it = ans.insert(x).first; + int a = *prev(it), b = *next(it); + cnt[b-a] --, ad(x-a), ad(b-x); + } +} + +int main() { + ios_base::sync_with_stdio(0); cin.tie(0); + cin >> s >> m; + ans.insert(0); ans.insert(sz(s)); + for (int i = 0; i < sz(s)-1; ++i) + if (s[i] != s[i+1]) ans.insert(i+1); + for (auto it = ans.begin(); next(it) != ans.end(); it ++) + ad(*next(it)-*it); + for (int i = 0; i < m; ++i) { + int x; cin >> x; + modify(x-1); modify(x); + while (!cnt[ret.top()]) ret.pop(); + cout << ret.top() << " "; + } +} +``` + +
+ + + +## Problems + + diff --git a/content/3_Silver/Prefix_Sums.mdx b/content/3_Silver/Prefix_Sums.mdx index cce5c29..feb8a9b 100644 --- a/content/3_Silver/Prefix_Sums.mdx +++ b/content/3_Silver/Prefix_Sums.mdx @@ -10,8 +10,7 @@ frequency: 3 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("YS", "Static Range Sum", "static_range_sum", "Easy", false, [], "equivalent to [CSES Range Sum Queries I](https://cses.fi/problemset/task/1646)"), ], @@ -47,7 +46,6 @@ export const metadata = { new Problem("Google KickStart", "Candies (Test Set 1)", "https://codingcompetitions.withgoogle.com/kickstart/round/000000000019ff43/0000000000337b4d", "Easy", false, ["Prefix Sums"], ""), new Problem("AC", "Multiple of 2019", "https://atcoder.jp/contests/abc164/tasks/abc164_d", "Hard", false, ["Prefix Sums"], "Make use of the fact that adding 0's to the end of a number does not affect whether it is a multiple of 2019 (because 10 and 2019 are coprime)."), ], - } }; @@ -59,7 +57,7 @@ export const metadata = { ## Introduction - + Let's say we have a one-indexed integer array $\texttt{arr}$ of size $N$ and we want to compute the value of $$ @@ -206,13 +204,13 @@ These are also known as [partial sums](https://mathworld.wolfram.com/PartialSum. ### Problems - + ## Max Subarray Sum Now we'll look at some extensions. - + This problem has a solution known as [Kadane's Algorithm](https://en.wikipedia.org/wiki/Maximum_subarray_problem#Kadane's_algorithm). Please don't use that solution; try to solve it with prefix sums. @@ -226,11 +224,11 @@ Consider the desired maximum subarray. As you go along from left to right, the p Similar to prefix sums, you can also take prefix minimum or maximum; but *you cannot* answer min queries over an arbitrary range with prefix minimum. (This is because minimum doesn't have an inverse operation, the way subtraction is to addition.) On the other hand, XOR is its own inverse operation, meaning that the XOR of any number with itself is zero. - + ## 2D Prefix Sums - + Now, what if we wanted to process $Q$ queries for the sum over a subrectangle of a $N$ rows by $M$ columns matrix in two dimensions? Let's assume both rows and columns are 1-indexed, and we use the following matrix as an example: @@ -475,7 +473,7 @@ as expected. Since no matter the size of the submatrix we are summing, we only need to access four values of the 2D prefix sum array, this runs in $O(1)$ per query after an $O(NM)$ preprocessing. - + ## More Complex Applications @@ -508,4 +506,4 @@ $$ Which is what we were looking for! - + diff --git a/content/3_Silver/Sliding.mdx b/content/3_Silver/Sliding.mdx deleted file mode 100644 index 78880e4..0000000 --- a/content/3_Silver/Sliding.mdx +++ /dev/null @@ -1,91 +0,0 @@ ---- -id: sliding -title: "Sliding Window" -author: Darren Yao, Benjamin Qi -prerequisites: - - stacks-queues - - intro-ordered -description: "Moving a subarray across an array to efficently compute information." -frequency: 2 ---- - -import { Problem } from "../models"; - -export const metadata = { - problems: { - sample: [ - new Problem("CSES", "Sum of Two Values", "1141", "Easy", false, []), - ], - slide: [ - new Problem("CSES", "Playlist", "1141", "Easy", false, [],"classic example of 2P"), - ], - general: [ - new Problem("CSES", "Subarray Sums I", "1660", "Easy", false, [], ""), - new Problem("CSES", "Sliding Median", "1076", "Easy", false, [], ""), - new Problem("CSES", "Sliding Cost", "1077", "Hard", false, [], ""), - new Problem("CSES", "Max Subarray Sum II", "1644", "Normal", false, [], ""), - new Problem("Silver", "Diamond Collector", "643", "Easy", false, ["2P", "Sorting"], ""), - new Problem("Silver", "Sleepy Cow Herding", "918", "Normal", false, ["2P", "Sorting"], ""), - new Problem("Gold", "Haybale Feast", "767", "Normal", false, ["Set", "Sliding Window"]), - new Problem("CF", "Books", "problemset/problem/279/B", "Normal", false, []), - new Problem("CF", "Cellular Network", "problemset/problem/702/C", "Normal", false, []), - new Problem("CF", "USB vs. PS/2", "problemset/problem/762/B", "Normal", false, []), - new Problem("CF", "K-Good Segment", "problemset/problem/616/D", "Normal", false, []), - new Problem("CF", "Garland", "problemset/problem/814/C", "Normal", false, []), - new Problem("CF", "Jury Meeting", "problemset/problem/853/B", "Normal", false, []), - new Problem("Plat", "Fort Moo", "600", "Very Hard", false, ["Sliding Window"]), - ], - qs: [ - new Problem("YS","Queue Composite","queue_operate_all_composite","Hard",true,[],""), - ], - } -}; - - -## Two Pointers - - - -Two pointers refers to iterating two monotonic pointers across an array to search for a pair of indices satisfying some condition in linear time. - - - - - - -### Implementation - - - -## Sliding Window - - - -Let's envision a **sliding window** (or constant size subarray) of size $K$ moving left to right along an array, $a$. - -For each position of the window, we want to compute some information. For example, we could store an ordered set of integers representing the integers inside the window. If the window currently spans the range $i \dots j$, we observe that moving the range forward to $i+1 \dots j+1$ only removes $a_i$ and adds $a_{j+1}$ to the window. We can support these two operations and query for the minimum / maximum in the set in $O(\log N)$. - -To compute the sum in the range, instead of using a set, we can store a variable $s$ representing the sum. As we move the window forward, we update $s$ by subtracting $a_i$ from $s$ and adding $a_{j+1}$ to $s$. - - - - - - -### Implementation - - - -### Problems - - - -## Sliding Window Minimum in $O(N)$ - - - Mentions two ways to solve this (both are important)! - - -In particular, the second method allows us to solve the following generalization in linear time as well: - - diff --git a/content/3_Silver/Sorting_2_Old.mdx b/content/3_Silver/Sorting_2_Old.mdx index 73eb90b..e8df3d0 100644 --- a/content/3_Silver/Sorting_2_Old.mdx +++ b/content/3_Silver/Sorting_2_Old.mdx @@ -214,4 +214,4 @@ Comments: Comparator 1 sorts array $a$ in decreasing order. Comparator 2 sorts a ## Problems - \ No newline at end of file + \ No newline at end of file diff --git a/content/3_Silver/Sorting_Custom.mdx b/content/3_Silver/Sorting_Custom.mdx index d3d5899..bb574e8 100644 --- a/content/3_Silver/Sorting_Custom.mdx +++ b/content/3_Silver/Sorting_Custom.mdx @@ -5,13 +5,13 @@ frequency: 3 author: Darren Yao, Siyong Huang, Michael Cao, Benjamin Qi prerequisites: - pairs-tuples -description: "Both Java and C++ have built-in functions for sorting. However, if we use custom objects, or if we want to sort elements in a different order, then we'll need to use a custom comparator." + - lambda +description: "If we use custom objects or if we want to sort elements in an order other than the default, then we'll need to define a custom comparator." --- import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("Silver", "Wormhole Sort", "992", "Normal", false, [], ""), ], @@ -25,7 +25,6 @@ export const metadata = { new Problem("Silver", "Triangles", "1015", "Hard", false, [], ""), new Problem("Silver", "Meetings", "967", "Very Hard", false, [], ""), ], - } }; @@ -36,7 +35,7 @@ export const metadata = { ## Example: Wormhole Sort - + There are multiple ways to solve this problem. We won't discuss the full solution here, but all of them start by sorting the edges in nondecreasing order of weight. For example, the sample contains the following edges: @@ -279,7 +278,7 @@ int main() { ``` -We can also use [lambda expressions](https://www.geeksforgeeks.org/lambda-expression-in-c/) in C++11 or above. +We can also use lambda expressions in C++11 or above: ```cpp sort(begin(v),end(v),[](const Edge& x, const Edge& y) { return x.w < y.w; }); @@ -573,4 +572,4 @@ public class Sol { ## Problems - \ No newline at end of file + \ No newline at end of file diff --git a/content/3_Silver/Sorting_Methods.mdx b/content/3_Silver/Sorting_Methods.mdx index 9b56771..bebe63d 100644 --- a/content/3_Silver/Sorting_Methods.mdx +++ b/content/3_Silver/Sorting_Methods.mdx @@ -10,12 +10,10 @@ frequency: 1 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { bubble: [ new Problem("Silver", "Out of Sorts", "834", "Very Hard", false, []), ], - } }; @@ -32,7 +30,7 @@ There are many sorting algorithms, here are some sources to learn about the popu ## Bubble Sort - + ### Tutorial diff --git a/content/3_Silver/Sorting_Old.mdx b/content/3_Silver/Sorting_Old.mdx index da6a384..0dcbbef 100644 --- a/content/3_Silver/Sorting_Old.mdx +++ b/content/3_Silver/Sorting_Old.mdx @@ -10,8 +10,7 @@ description: "Both Java and C++ have built-in functions for sorting. However, if import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("Silver", "Wormhole Sort", "992", "Normal", false, [], ""), ], @@ -23,12 +22,11 @@ export const metadata = { new Problem("Silver", "Mooyo Mooyo", "860", "Easy", false, [], "Not a sorting problem, but you can use sorting to simulate gravity. - Write a custom comparator which puts zeroes at the front and use `stable_sort` to keep the relative order of other elements the same."), new Problem("Silver", "Meetings", "967", "Very Hard", false, [], ""), ], - } }; ## Example: Wormhole Sort - + There are multiple ways to solve this problem. We won't discuss the full solution here, but all of them start by sorting the edges in nondecreasing order of weight. diff --git a/content/3_Silver/Stacks_Queues.mdx b/content/3_Silver/Stacks_Queues.mdx deleted file mode 100644 index 084d39c..0000000 --- a/content/3_Silver/Stacks_Queues.mdx +++ /dev/null @@ -1,270 +0,0 @@ ---- -id: stacks-queues -title: Introduction to Stacks & Queues -author: Darren Yao -description: "Two data structures to efficently add and remove the first and last element." -prerequisites: - - intro-ds ---- - -import { Problem } from "../models"; - -export const metadata = { - problems: { - nearest: [ - new Problem("CSES", "Nearest Smaller Values", "1645", "Easy", false, [], ""), - ], - general: [ - new Problem("LC", "Max Histogram Area", "largest-rectangle-in-histogram", "Normal", false, [],""), - new Problem("Old Gold", "Concurrently Balanced Strings", "194", "Normal", false, [],""), - new Problem("YS","Persistent Queue","persistent_queue","Normal",false,["DFS"],""), - new Problem("Gold", "Modern Art 2","743", "Hard", false, [], ""), - new Problem("Gold", "Dishwashing","922", "Hard", false, [], ""), - ], - } -}; - -## Additional Reading - - - - - - - - -## Stacks - -A stack is a **Last In First Out** (LIFO) data structure that supports three operations, all in $O(1)$ time. Think of it like a real-world stack of papers (or cards). - - - - - -### [C++](http://www.cplusplus.com/reference/stack/stack/) - - - `push`: adds an element to the top of the stack - - `pop`: removes an element from the top of the stack - - `top`: retrieves the element at the top without removing it - -```cpp -stack s; -s.push(1); // [1] -s.push(13); // [1, 13] -s.push(7); // [1, 13, 7] -cout << s.top() << endl; // 7 -s.pop(); // [1, 13] -cout << s.size() << endl; // 2 -``` - - - - - -### Java - - - `push`: adds an element to the top of the stack - - `pop`: removes an element from the top of the stack - - `peek`: retrieves the element at the top without removing it - -```java -Stack s = new Stack(); -s.push(1); // [1] -s.push(13); // [1, 13] -s.push(7); // [1, 13, 7] -System.out.println(s.peek()); // 7 -s.pop(); // [1, 13] -System.out.println(s.size()); // 2 -``` - - - - - -## Queues - -A queue is a First In First Out (FIFO) data structure that supports three operations, all in $O(1)$ time. - - - - - -### [C++](http://www.cplusplus.com/reference/queue/queue/) - - - `push`: insertion at the back of the queue - - `pop`: deletion from the front of the queue - - `front`: which retrieves the element at the front without removing it. - -```cpp -queue q; -q.push(1); // [1] -q.push(3); // [3, 1] -q.push(4); // [4, 3, 1] -q.pop(); // [4, 3] -cout << q.front() << endl; // 3 -``` - - - - - -### Java - - - `add`: insertion at the back of the queue - - `poll`: deletion from the front of the queue - - `peek`: which retrieves the element at the front without removing it - -Java doesn't actually have a `Queue` class; it's only an interface. The most commonly used implementation is the `LinkedList`, declared as follows: - -```java -Queue q = new LinkedList(); -q.add(1); // [1] -q.add(3); // [3, 1] -q.add(4); // [4, 3, 1] -q.poll(); // [4, 3] -System.out.println(q.peek()); // 3 -``` - - - - - -## Deques - -A **deque** (usually pronounced "deck") stands for double ended queue and is a combination of a stack and a queue, in that it supports $O(1)$ insertions and deletions from both the front and the back of the deque. Not very common in Bronze / Silver. - - - - - -### [C++](http://www.cplusplus.com/reference/deque/deque/) - -The four methods for adding and removing are `push_back`, `pop_back`, `push_front`, and `pop_front`. - -```cpp -deque d; -d.push_front(3); // [3] -d.push_front(4); // [4, 3] -d.push_back(7); // [4, 3, 7] -d.pop_front(); // [3, 7] -d.push_front(1); // [1, 3, 7] -d.pop_back(); // [1, 3] -``` - - - - - -### Java - -In Java, the deque class is called `ArrayDeque`. The four methods for adding and removing are `addFirst` , `removeFirst`, `addLast`, and `removeLast`. - -```java -ArrayDeque deque = new ArrayDeque(); -deque.addFirst(3); // [3] -deque.addFirst(4); // [4, 3] -deque.addLast(7); // [4, 3, 7] -deque.removeFirst(); // [3, 7] -deque.addFirst(1); // [1, 3, 7] -deque.removeLast(); // [1, 3] -``` - - - - - -## Priority Queues - - - - - -### [C++](http://www.cplusplus.com/reference/queue/priority_queue/) - -A priority queue supports the following operations: insertion of elements, deletion of the element considered highest priority, and retrieval of the highest priority element, all in $O(\log n)$ time according to the number of elements in the priority queue. Priority is based on a comparator function. The priority queue is one of the most important data structures in competitive programming, so make sure you understand how and when to use it. - -```cpp -priority_queue pq; -pq.push(7); // [7] -pq.push(2); // [2, 7] -pq.push(1); // [1, 2, 7] -pq.push(5); // [1, 2, 5, 7] -cout << pq.top() << endl; // 7 -pq.pop(); // [1, 2, 5] -pq.pop(); // [1, 2] -pq.push(6); // [1, 2, 6] -``` - - - - - - -### Java - -In Java, we delete and retrieve the element of **lowest** priority. - -```java -PriorityQueue pq = new PriorityQueue(); -pq.add(7); // [7] -pq.add(2); // [7, 2] -pq.add(1); // [7, 2, 1] -pq.add(5); // [7, 5, 2, 1] -System.out.println(pq.peek()); // 1 -pq.poll(); // [7, 5, 2] -pq.poll(); // [7, 5] -pq.add(6); // [7, 6, 5] -``` - - - - - - - -## Monotonic Stack - - - -Consider the following problem: - -> Given an array, $a$, of $N$ ($1 \le N \le 10^5$) integers, for every index $i$, find the rightmost index $j$ such that $j < i$ and $a_i > a_j$. - -To solve this, let's store a stack of pairs of `` and iterate over the array from left to right. For some index $i$, we will compute $ans_i$, the rightmost index for $i$, as follows: - -- Keep popping the top element off the stack as long as $value \ge a_i$. This is because we know that the pair containing $value$ will never be the solution to any index $j > i$, since $a_i$ is less than or equal to than $value$ and has an index further to the right. -- If $value < a_i$, set $ans[i]$ to $index$, because a stack stores the most recently added values first (or in this case, the rightmost ones), $index$ will contain the rightmost value which is less than $a_i$. Then, pop the top element off the stack, because $index$ can't be the solution for two elements. - -The stack we used is called a **monotonic stack** because we keep popping off the top element of the stack which maintains it's monotonicity (the same property needed for algorithms like binary search) because the elements in the stack are increasing. - -(add code) - - - -### Further Reading - - - - - - -## Problems - - - - \ No newline at end of file diff --git a/content/4_Gold/BFS.mdx b/content/4_Gold/BFS.mdx index d960192..deae5d0 100644 --- a/content/4_Gold/BFS.mdx +++ b/content/4_Gold/BFS.mdx @@ -10,8 +10,7 @@ frequency: 2 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("CSES", "Message Route", "1667", "Easy", false, ["BFS"]), ], @@ -25,10 +24,9 @@ export const metadata = { example: [ new Problem("Gold", "Cow Navigation", "695", "Normal", false, ["BFS"]), ] - } }; - + ## Resources @@ -181,7 +179,7 @@ class Main { In the gold division, the problem statement will never directly be, "Given an unweighted graph, find the shortest path between node $u$ and $v$." Instead, the difficulty in many BFS problems are modifying the problem into a graph on which we can run BFS and get the answer. - + In this problem, Bessie stands on a grid and wants to go from the lower left corner to upper-right corner in as few moves as possible. An initial idea could be to model the grid as a graph, where adjacent cells are connected by edges, and run a BFS to find the shortest path. @@ -212,4 +210,4 @@ Don't forget that once Bessie reaches the goal, she will ignore further commands ## Problems - + diff --git a/content/4_Gold/Cyc.mdx b/content/4_Gold/Cyc.mdx index a1b211e..24a9399 100644 --- a/content/4_Gold/Cyc.mdx +++ b/content/4_Gold/Cyc.mdx @@ -10,8 +10,7 @@ frequency: 0 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { und: [ new Problem("CSES", "Round Trip", "1669", "Easy", false, ["Cycle"]), ], @@ -21,7 +20,6 @@ export const metadata = { general: [ new Problem("CSES", "Graph Girth", "1707", "Easy", false, ["Cycle"]), ], - } }; @@ -29,7 +27,7 @@ export const metadata = { ## Undirected Graphs - + (explanation?) @@ -41,7 +39,7 @@ An algorithm known as **BFS-Cycle** returns an integer that is at most one more ## Directed Graphs - + The same general idea is implemented below to find any cycle in a directed graph (if one exists). Note that this is almost identical to the DFS algorithm for topological sorting. @@ -107,6 +105,6 @@ int main() ## Problems - + VT-HSPC 2019? \ No newline at end of file diff --git a/content/4_Gold/DP.mdx b/content/4_Gold/DP.mdx index b80c822..9a6e1d0 100644 --- a/content/4_Gold/DP.mdx +++ b/content/4_Gold/DP.mdx @@ -11,8 +11,7 @@ frequency: 4 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { usacoEasy: [ new Problem("Gold", "Hoof Paper Scissors", "694", "Easy", false, ["DP"], "dp[first i games][# changes][last gesture] -> max games won"), new Problem("Gold", "Time is Mooney", "993", "Easy", true, ["DP", "Graphs"], "dp[time][city] -> money"), @@ -50,7 +49,6 @@ export const metadata = { 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"), ], - } } Dynamic Programming is an important algorithmic technique in competitive programming that appears at all levels of competition. @@ -83,31 +81,31 @@ Sometimes it's a good idea to write a slower polynomial-time solution and then o These are easier USACO problems which use DP, and don't require many optimizations or complex states. - + ## Knapsack Common variations on Knapsack, followed by more challenging problems which feature variations on the state and additional algorithms. - + ## Paths in a Grid (and related) Interesting applications of "number of paths on a grid," some of which don't directly present a grid in the problem, but can be modelled as one. Such as Longest Common Subsequence. - + ## Longest Increasing Subsequence 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 - + ## Harder USACO Problems Finish with some more challenging Dynamic Programming problems! Some of these can be very difficult, so skip around if you want. - + ## Other DP Problemsets diff --git a/content/4_Gold/DP_Trees.mdx b/content/4_Gold/DP_Trees.mdx index c4aa8e3..65aa7e6 100644 --- a/content/4_Gold/DP_Trees.mdx +++ b/content/4_Gold/DP_Trees.mdx @@ -10,8 +10,7 @@ frequency: 2 --- import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("CSES", "Tree Matching", "1130", "Easy", false, ["DP"], ""), ], @@ -29,10 +28,9 @@ export const metadata = { new Problem("CSES", "Creating Offices", "1752", "Hard", false, ["Greedy"], "equivalent to BOI - Cat in a Tree"), new Problem("Plat", "Cow At Large", "793", "Hard", false, [], "This is not too hard to fakesolve. First write an (optimized?) O(N^2) DP to pass test cases 1-6. This won't work for test cases 7-11, but in these test cases all trees have at most 20 leaves. Therefore it suffices to compress tree edges (repeatedly remove vertices of degree 2) and run the same solution. For a legit DP solution, see Eric Zhang's comment here: https://codeforces.com/blog/entry/57170?#comment-410179"), ], - } } - + ## Tutorial @@ -45,7 +43,7 @@ export const metadata = { ## Solving for All Roots - + (dfs twice) @@ -99,7 +97,6 @@ template struct SubtreeDP { T p = T(); trav(t,adj[i]) p += getSub(t,i); ps(p.v); } - } }; int main() { @@ -132,7 +129,7 @@ Don't just dive into trying to figure out a DP state and transitions -- make som - + diff --git a/content/4_Gold/DSU.mdx b/content/4_Gold/DSU.mdx index fa43afc..d7390ad 100644 --- a/content/4_Gold/DSU.mdx +++ b/content/4_Gold/DSU.mdx @@ -10,8 +10,7 @@ frequency: 3 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("YS", "Union Find", "unionfind", "Intro|Easy", false, []), ], @@ -20,10 +19,9 @@ export const metadata = { new Problem("Gold", "Mootube", "789", "Normal", false, [], "Answer queries in decreasing order of $k$. Maintain size of each connected component. Same as [CSES Road Construction](https://cses.fi/problemset/task/1676)"), new Problem("Gold", "Favorite Colors", "1042", "Very Hard", false, ["DSU"], "Small to large merging is mentioned in the editorial, but we were unable to break solutions that just merged naively. Alternatively, just merge linked lists in $O(1)$ time."), ], - } }; - + ## Resources @@ -102,4 +100,4 @@ boolean merge(int a, int b) { ## Problems - + diff --git a/content/4_Gold/Faster_Hash.mdx b/content/4_Gold/Faster_Hash.mdx index dc99137..3e64bc1 100644 --- a/content/4_Gold/Faster_Hash.mdx +++ b/content/4_Gold/Faster_Hash.mdx @@ -10,12 +10,13 @@ prerequisites: import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { three: [ new Problem("Gold", "3SUM", "994", "Normal", false, [], ""), ], - } + four: [ + new Problem("CSES", "Sum of Four Values", "1642", "Normal", false, [], ""), + ], }; @@ -97,7 +98,7 @@ then the actual size of `g` is always at least `1<<16` (regardless of calls to ` ### Solving ThreeSum - + You're supposed to use array since values are small :| @@ -106,9 +107,9 @@ You're supposed to use array since values are small :| using namespace std; void setIO(string name) { - ios_base::sync_with_stdio(0); cin.tie(0); - freopen((name+".in").c_str(),"r",stdin); - freopen((name+".out").c_str(),"w",stdout); + ios_base::sync_with_stdio(0); cin.tie(0); + freopen((name+".in").c_str(),"r",stdin); + freopen((name+".out").c_str(),"w",stdout); } @@ -120,27 +121,31 @@ long long ans[5000][5000]; vector A; int main() { - setIO("threesum"); - cin >> N >> Q; - A.resize(N); for (int i = 0; i < N; ++i) cin >> A[i]; - for (int i = 0; i < N; ++i) { - gp_hash_table g({},{},{},{},{1<<13}); - // initialize with certain capacity, must be power of 2 - for (int j = i+1; j < N; ++j) { - int res = -A[i]-A[j]; - auto it = g.find(res); - if (it != end(g)) ans[i][j] = it->second; - g[A[j]] ++; - } - } - for (int i = N-1; i >= 0; --i) for (int j = i+1; j < N; ++j) - ans[i][j] += ans[i+1][j]+ans[i][j-1]-ans[i+1][j-1]; - for (int i = 0; i < Q; ++i) { - int a,b; cin >> a >> b; - cout << ans[a-1][b-1] << "\n"; - } - // you should actually read the stuff at the bottom + setIO("threesum"); + cin >> N >> Q; + A.resize(N); for (int i = 0; i < N; ++i) cin >> A[i]; + for (int i = 0; i < N; ++i) { + gp_hash_table g({},{},{},{},{1<<13}); + // initialize with certain capacity, must be power of 2 + for (int j = i+1; j < N; ++j) { + int res = -A[i]-A[j]; + auto it = g.find(res); + if (it != end(g)) ans[i][j] = it->second; + g[A[j]] ++; + } + } + for (int i = N-1; i >= 0; --i) for (int j = i+1; j < N; ++j) + ans[i][j] += ans[i+1][j]+ans[i][j-1]-ans[i+1][j-1]; + for (int i = 0; i < Q; ++i) { + int a,b; cin >> a >> b; + cout << ans[a-1][b-1] << "\n"; + } + // you should actually read the stuff at the bottom } ``` - \ No newline at end of file + + +## Problems + + \ No newline at end of file diff --git a/content/4_Gold/Intro_NT.mdx b/content/4_Gold/Intro_NT.mdx index c51458e..6d1abf5 100644 --- a/content/4_Gold/Intro_NT.mdx +++ b/content/4_Gold/Intro_NT.mdx @@ -11,8 +11,7 @@ frequency: 1 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("CF", "VK Cup Wildcard R1 C - Prime Factorization", "problemset/problem/162/C", "Intro|Very Easy", false, []), ], @@ -25,7 +24,6 @@ export const metadata = { new Problem("Gold", "Cow Poetry", "897", "Normal", false, ["Knapsack", "Exponentiation"], "First consider the case where there are only two lines with the same class."), new Problem("Gold", "Exercise", "1043", "Normal", false, ["Knapsack", "Prime Factorization"], "Prime factorize $K$."), ], - } }; @@ -39,7 +37,7 @@ export const metadata = { ## Prime Factorization - + A number $a$ is called a **divisor** or a **factor** of a number $b$ if $b$ is divisible by $a$, which means that there exists some integer $k$ such that $b = ka$. Conventionally, $1$ and $n$ are considered divisors of $n$. A number $n > 1$ is **prime** if its only divisors are $1$ and $n$. Numbers greater than \(1\) that are not prime are **composite**. @@ -226,4 +224,4 @@ See the module in the [Advanced](../adv/extend-euclid) section. ## Problems - + diff --git a/content/4_Gold/MST.mdx b/content/4_Gold/MST.mdx index e5f025a..59e678a 100644 --- a/content/4_Gold/MST.mdx +++ b/content/4_Gold/MST.mdx @@ -11,8 +11,7 @@ frequency: 2 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { standard: [ new Problem("Kattis", "MST", "minspantree", "Easy", false, ["MST"], ""), new Problem("CSES", "Road Reparation", "1675", "Easy", false, ["MST"], ""), @@ -24,10 +23,9 @@ export const metadata = { new Problem("HR", "Spanning Tree Fraction", "https://www.hackerrank.com/contests/w31/challenges/spanning-tree-fraction/problem", "Normal", false, ["MST", "Binary Search"], ""), new Problem("Plat", "Fencedin", "625", "Hard", false, ["Kruskal"], ""), ], - } }; - + ## Resources @@ -48,4 +46,4 @@ export const metadata = { ## USACO Problems - + diff --git a/content/4_Gold/PURS.mdx b/content/4_Gold/PURS.mdx index c30f488..a14fb53 100644 --- a/content/4_Gold/PURS.mdx +++ b/content/4_Gold/PURS.mdx @@ -10,8 +10,7 @@ frequency: 3 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { seg: [ new Problem("CSES", "Range Minimum Queries II", "1649", "Intro|Easy", false, ["PURQ"], ""), new Problem("YS", "Point Set Range Composite", "point_set_range_composite", "Easy", false, ["PURQ"], "Order of operations matters!"), @@ -44,10 +43,9 @@ export const metadata = { new Problem("Old Gold", "Cow Hopscotch", "532", "Hard", false, [], ""), new Problem("Plat", "Out of Sorts", "840", "Hard", false, [], ""), ], - } }; - +
@@ -60,7 +58,7 @@ Both **segment trees** and **binary indexed trees** can accomplish this. ## Segment Tree - + A **segment tree** allows you to do point update and range query in $O(\log N)$ time each for **any** associative operation, not just summation. @@ -106,7 +104,6 @@ template struct Seg { // comb(ID,b) = b if (r&1) rb = comb(seg[--r],rb); } return comb(ra,rb); - } }; ``` @@ -208,10 +205,10 @@ Covered in [platinum](../plat/seg-ext). ## Practice Problems - + ## USACO Problems Haircut, Balanced Photo, and Circle Cross are just variations on inversion counting. - + diff --git a/content/4_Gold/Queues.mdx b/content/4_Gold/Queues.mdx new file mode 100644 index 0000000..af8f927 --- /dev/null +++ b/content/4_Gold/Queues.mdx @@ -0,0 +1,126 @@ +--- +id: queues +title: Queues +author: Darren Yao +description: "Two data structures to efficently add and remove the first and last element." +prerequisites: + - intro-ds + - sliding +--- + +import { Problem } from "../models"; + +export const problems = { + ys: [ + new Problem("YS","Persistent Queue","persistent_queue","Normal",false,["DFS"],""), + new Problem("YS","Queue Composite","queue_operate_all_composite","Hard",true,[],""), + ], + sam: [ + new Problem("LC", "Sliding Window Maximum", "sliding-window-maximum", "Easy", false, [], ""), + ], +}; + +## Queues + +A queue is a First In First Out (FIFO) data structure that supports three operations, all in $O(1)$ time. + + + + + +### [C++](http://www.cplusplus.com/reference/queue/queue/) + + - `push`: insertion at the back of the queue + - `pop`: deletion from the front of the queue + - `front`: which retrieves the element at the front without removing it. + +```cpp +queue q; +q.push(1); // [1] +q.push(3); // [3, 1] +q.push(4); // [4, 3, 1] +q.pop(); // [4, 3] +cout << q.front() << endl; // 3 +``` + + + + + +### Java + + - `add`: insertion at the back of the queue + - `poll`: deletion from the front of the queue + - `peek`: which retrieves the element at the front without removing it + +Java doesn't actually have a `Queue` class; it's only an interface. The most commonly used implementation is the `LinkedList`, declared as follows: + +```java +Queue q = new LinkedList(); +q.add(1); // [1] +q.add(3); // [3, 1] +q.add(4); // [4, 3, 1] +q.poll(); // [4, 3] +System.out.println(q.peek()); // 3 +``` + + + + + +## Deques + +A **deque** (usually pronounced "deck") stands for double ended queue and is a combination of a stack and a queue, in that it supports $O(1)$ insertions and deletions from both the front and the back of the deque. Not very common in Bronze / Silver. + + + + + +### [C++](http://www.cplusplus.com/reference/deque/deque/) + +The four methods for adding and removing are `push_back`, `pop_back`, `push_front`, and `pop_front`. + +```cpp +deque d; +d.push_front(3); // [3] +d.push_front(4); // [4, 3] +d.push_back(7); // [4, 3, 7] +d.pop_front(); // [3, 7] +d.push_front(1); // [1, 3, 7] +d.pop_back(); // [1, 3] +``` + + + + + +### Java + +In Java, the deque class is called `ArrayDeque`. The four methods for adding and removing are `addFirst` , `removeFirst`, `addLast`, and `removeLast`. + +```java +ArrayDeque deque = new ArrayDeque(); +deque.addFirst(3); // [3] +deque.addFirst(4); // [4, 3] +deque.addLast(7); // [4, 3, 7] +deque.removeFirst(); // [3, 7] +deque.addFirst(1); // [1, 3, 7] +deque.removeLast(); // [1, 3] +``` + + + + + +## Sliding Window Minimum in $O(N)$ + + + + + + Mentions two ways to solve this (both are important)! + + +## Problems + + \ No newline at end of file diff --git a/content/4_Gold/SP.mdx b/content/4_Gold/SP.mdx index 1d3d014..0a07a80 100644 --- a/content/4_Gold/SP.mdx +++ b/content/4_Gold/SP.mdx @@ -4,15 +4,14 @@ title: "Shortest Paths with Non-Negative Edge Weights" author: Benjamin Qi prerequisites: - bfs - - stacks-queues + - intro-ordered description: "Introduces Dijkstra's Algorithm for a single source shortest path as well as Floyd-Warshall for All-Pairs Shortest Path." frequency: 3 --- import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("CSES", "Shortest Routes I", "1671", "Easy", false, ["SP"], "equivalent to [Kattis SSSP Non-Negative](https://open.kattis.com/problems/shortestpath1)"), ], @@ -33,12 +32,11 @@ export const metadata = { apsp: [ new Problem("Gold", "Moortal Cowmbat", "971", "Hard", false, ["APSP", "DP"], ""), ], - } }; ## Single-Source Shortest Path - + ### Tutorial @@ -78,11 +76,11 @@ Can be done in $O(M+N\log N)$ with [Fibonacci heap](https://en.wikipedia.org/wik ### Problems - + ## All Pairs Shortest Path (APSP) - + Use the *Floyd-Warshall* algorithm. @@ -112,6 +110,6 @@ just to be safe. ### Problems - + (more?) \ No newline at end of file diff --git a/content/4_Gold/SRQ.mdx b/content/4_Gold/SRQ.mdx index ee333f9..0139ebf 100644 --- a/content/4_Gold/SRQ.mdx +++ b/content/4_Gold/SRQ.mdx @@ -8,12 +8,11 @@ frequency: 1 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { rmqSample: [ new Problem("YS", "Static RMQ", "staticrmq", "Easy", false, [], "equivalent to [CSES Range Minimum Queries I](https://cses.fi/problemset/task/1647)"), ], - diviSample: [ + diviSample: [ new Problem("ojuz", "JOI Secret", "JOI14_secret", "Easy", false, [], ""), ], general: [ @@ -21,7 +20,6 @@ export const metadata = { new Problem("DMOJ", "Continued Fractions", "dmopc19c7p4", "Hard", false, [], ""), new Problem("Plat", "Non-Decreasing Subsequences", "997", "Very Hard", false, [], ""), ], - } }; Given a static array $A[1],A[2],\ldots,A[N]$, you want to answer queries in the form $A[l]\ominus A[l+1]\ominus \cdots \ominus A[r]$ where $\ominus$ denotes any associative operation. @@ -32,7 +30,7 @@ With $O(N\log N)$ time preprocessing, we can get $O(1)$ queries. First we'll consider the special case when $\ominus$ denotes `min`. - + ### Resources @@ -55,7 +53,7 @@ First we'll consider the special case when $\ominus$ denotes `min`. ## Divide & Conquer - + **Divide & conquer** can refer to many different techniques. In this case, we use it to answer $Q$ queries offline in $O((N+Q)\log N)$ time. @@ -86,4 +84,4 @@ A data structure known as **sqrt-tree** can speed up preprocessing time to $O(N\ ## Problems - \ No newline at end of file + \ No newline at end of file diff --git a/content/4_Gold/Sliding.mdx b/content/4_Gold/Sliding.mdx new file mode 100644 index 0000000..cef38e5 --- /dev/null +++ b/content/4_Gold/Sliding.mdx @@ -0,0 +1,61 @@ +--- +id: sliding +title: "Sliding Window" +author: Darren Yao, Benjamin Qi +prerequisites: + - intro-ordered + - 2P +description: "Maintaining data over consecutive subarrays." +frequency: 2 +--- + +import { Problem } from "../models"; + +export const problems = { + constantSam: [ + new Problem("LC", "Sliding Window Maximum", "sliding-window-maximum", "Easy", false, [], ""), + ], + constant: [ + new Problem("CSES", "Max Subarray Sum II", "1644", "Normal", false, ["prefix-sums"], ""), + new Problem("CSES", "Sliding Median", "1076", "Normal", false, [], ""), + new Problem("CSES", "Sliding Cost", "1077", "Hard", false, [], ""), + ], + general: [ + new Problem("CSES", "Playlist", "1141", "Easy", false, ["2P"], ""), + new Problem("Gold", "Haybale Feast", "767", "Easy", false, ["Set", "Sliding Window"]), + new Problem("Plat", "Fort Moo", "600", "Hard", false, ["Sliding Window"]), + ] +}; + +## Sliding Window + + + +From CPH: + +> A sliding window is a constant-size subarray that moves from left to right +through the array. + +For each position of the window, we want to compute some information. For example, we could store an ordered set of integers representing the integers inside the window. If the window currently spans the range $i \dots j$, we observe that moving the range forward to $i+1 \dots j+1$ only removes $a_i$ and adds $a_{j+1}$ to the window. We can support these two operations and query for the minimum / maximum in the set in $O(\log N)$. + + + + + + + + +### Implementation + + + +### Problems + + + +## With Two Pointers + +In general, it is not required for the subarray to have constant size as long as both the left and right endpoints of the subarray only move to the right. + + \ No newline at end of file diff --git a/content/4_Gold/Springboards.mdx b/content/4_Gold/Springboards.mdx index dabff80..8031531 100644 --- a/content/4_Gold/Springboards.mdx +++ b/content/4_Gold/Springboards.mdx @@ -10,8 +10,7 @@ frequency: 1 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("Gold", "Springboards", "995", "Hard", false, [], ""), ], @@ -20,10 +19,9 @@ export const metadata = { new Problem("CF", "Karen & Cards", "contest/815/problem/D", "Very Hard", false, [], "For each a from p to 1, calculate the number of possible cards with that value of a."), new Problem("CF", "GP of Korea 19 - Interesting Drug", "gym/102059/problem/K", "Very Hard", false, [], "Genfuncs not required but possibly helpful"), ] - } }; - +
@@ -78,4 +76,4 @@ ll query(int x) { auto it = m.lb(x); - + diff --git a/content/4_Gold/Stacks.mdx b/content/4_Gold/Stacks.mdx new file mode 100644 index 0000000..4f69639 --- /dev/null +++ b/content/4_Gold/Stacks.mdx @@ -0,0 +1,123 @@ +--- +id: stacks +title: Stacks +author: Darren Yao +description: "Two data structures to efficently add and remove the first and last element." +prerequisites: + - intro-ds +--- + +import { Problem } from "../models"; + +export const problems = { + nearest: [ + new Problem("CSES", "Nearest Smaller Values", "1645", "Easy", false, [], ""), + ], + general: [ + new Problem("LC", "Max Histogram Area", "largest-rectangle-in-histogram", "Normal", false, [],""), + new Problem("Old Gold", "Concurrently Balanced Strings", "194", "Normal", false, [],""), + new Problem("Gold", "Modern Art 2","743", "Hard", false, [], ""), + new Problem("Gold", "Dishwashing","922", "Hard", false, [], ""), + ], +}; + + + + + + + + +## Stacks + +A stack is a **Last In First Out** (LIFO) data structure that supports three operations, all in $O(1)$ time. Think of it like a real-world stack of papers (or cards). + + + + + +### [C++](http://www.cplusplus.com/reference/stack/stack/) + + - `push`: adds an element to the top of the stack + - `pop`: removes an element from the top of the stack + - `top`: retrieves the element at the top without removing it + +```cpp +stack s; +s.push(1); // [1] +s.push(13); // [1, 13] +s.push(7); // [1, 13, 7] +cout << s.top() << endl; // 7 +s.pop(); // [1, 13] +cout << s.size() << endl; // 2 +``` + + + + + +### Java + + - `push`: adds an element to the top of the stack + - `pop`: removes an element from the top of the stack + - `peek`: retrieves the element at the top without removing it + +```java +Stack s = new Stack(); +s.push(1); // [1] +s.push(13); // [1, 13] +s.push(7); // [1, 13, 7] +System.out.println(s.peek()); // 7 +s.pop(); // [1, 13] +System.out.println(s.size()); // 2 +``` + + + + + + +## Application: Nearest Smaller Element + + + +Consider the following problem: + +> Given an array, $a$, of $N$ ($1 \le N \le 10^5$) integers, for every index $i$, find the rightmost index $j$ such that $j < i$ and $a_i > a_j$. + + + + + + +To solve this, let's store a stack of pairs of `` and iterate over the array from left to right. For some index $i$, we will compute $ans_i$, the rightmost index for $i$, as follows: + +- Keep popping the top element off the stack as long as $value \ge a_i$. This is because we know that the pair containing $value$ will never be the solution to any index $j > i$, since $a_i$ is less than or equal to than $value$ and has an index further to the right. +- If $value < a_i$, set $ans[i]$ to $index$, because a stack stores the most recently added values first (or in this case, the rightmost ones), $index$ will contain the rightmost value which is less than $a_i$. Then, pop the top element off the stack, because $index$ can't be the solution for two elements. + +The stack we used is called a **monotonic stack** because we keep popping off the top element of the stack which maintains it's monotonicity (the same property needed for algorithms like binary search) because the elements in the stack are increasing. + +### Implementation + + + +## Problems + + + + \ No newline at end of file diff --git a/content/4_Gold/String_Hashing.mdx b/content/4_Gold/String_Hashing.mdx index 8b8faa0..31d1468 100644 --- a/content/4_Gold/String_Hashing.mdx +++ b/content/4_Gold/String_Hashing.mdx @@ -10,8 +10,7 @@ prerequisites: import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { ex: [ new Problem("Gold", "Cownomics", "741", "Easy", false, [], ""), ], @@ -25,7 +24,6 @@ export const metadata = { adj: [ new Problem("CF", "Berland SU Computer Network", "contest/847/problem/L", "Normal", false, [], ""), ] - } }; ## Tutorial @@ -45,7 +43,7 @@ My implementation can be found [here](https://github.com/bqi343/USACO/blob/maste ## Example: Cownomics (Gold) - + - Use two pointers; for a fixed $l$, keep extending $r$ to the right until the positions $l\ldots r$ explain spotiness. - Hashing gives you a way to quickly check whether two substrings of different cow types are equal. So for a single $[l,r]$ pair you can check whether it works in $O(N\log N)$ time (and you only need to check $O(M)$ of these pairs in total). @@ -55,7 +53,7 @@ My implementation can be found [here](https://github.com/bqi343/USACO/blob/maste (elaborate) - + --> ## Hacking @@ -66,4 +64,4 @@ My implementation can be found [here](https://github.com/bqi343/USACO/blob/maste ## Problems - \ No newline at end of file + \ No newline at end of file diff --git a/content/4_Gold/TopoSort.mdx b/content/4_Gold/TopoSort.mdx index 4621229..f6eb257 100644 --- a/content/4_Gold/TopoSort.mdx +++ b/content/4_Gold/TopoSort.mdx @@ -11,8 +11,7 @@ frequency: 1 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("CSES", "Course Schedule", "1679", "Easy", false, []), ], @@ -26,14 +25,13 @@ export const metadata = { new Problem("Gold", "Milking Order", "838", "Normal", false, ["TopoSort", "Binary Search"]), new Problem("CSES", "Course Schedule II", "1681", "Hard", false, [], "equivalent to [Minimal Labels](https://codeforces.com/contest/825/problem/E)"), ], - } }; To review, a **directed** graph consists of edges that can only be traversed in one direction. Additionally, a **acyclic** graph defines a graph which does not contain cycles, meaning you are unable to traverse across one or more edges and return to the node you started on. Putting these definitions together, a **directed acyclic** graph, sometimes abbreviated as DAG, is a graph which has edges which can only be traversed in one direction and does not contain cycles. ## Topological Sort - + A [topological sort](https://en.wikipedia.org/wiki/Topological_sorting) of a directed acyclic graph is a linear ordering of its vertices such that for every directed edge $u\to v$ from vertex $u$ to vertex $v$, $u$ comes before $v$ in the ordering. @@ -136,7 +134,7 @@ void compute() { One useful property of directed acyclic graphs is, as the name suggests, that no cycles exist. If we consider each node in the graph as a state, we can perform dynamic programming on the graph if we process the states in an order that guarantees for every edge $u\to v$ that $u$ is processed before $v$. Fortunately, this is the exact definition of a topological sort! - + In this task, we must find the longest path in a DAG. @@ -459,4 +457,4 @@ public class Main { ## Problems - + diff --git a/content/4_Gold/Tree_Euler.mdx b/content/4_Gold/Tree_Euler.mdx index deea958..5c43b7c 100644 --- a/content/4_Gold/Tree_Euler.mdx +++ b/content/4_Gold/Tree_Euler.mdx @@ -12,8 +12,7 @@ frequency: 2 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("CSES", "Subtree Queries", "1137", "Easy", false, ["Euler-Tree"], "equivalent to https://judge.yosupo.jp/problem/vertex_add_subtree_sum"), new Problem("CSES", "Path Queries", "1138", "Easy", false, ["Euler-Tree","PURS"], "equivalent to https://judge.yosupo.jp/problem/vertex_add_path_sum"), @@ -29,12 +28,11 @@ export const metadata = { new Problem("ojuz", "IOI - Regions", "IOI09_regions", "Hard", false, ["Euler-Tree", "Binary Search"], ""), new Problem("Plat", "Snow-Cow", "973", "Hard", false, ["Euler-Tree","PURS"], ""), ] - } }; ## Introduction - + If we can preprocess a rooted tree such that every subtree corresponds to a contiguous range on an array, we can do updates and range queries on it! @@ -50,7 +48,7 @@ If we can preprocess a rooted tree such that every subtree corresponds to a cont ## LCA - + ### Tutorial @@ -65,4 +63,4 @@ If we can preprocess a rooted tree such that every subtree corresponds to a cont ## Problems - \ No newline at end of file + \ No newline at end of file diff --git a/content/5_Plat/2DRQ.mdx b/content/5_Plat/2DRQ.mdx index 7befc5f..1e5b088 100644 --- a/content/5_Plat/2DRQ.mdx +++ b/content/5_Plat/2DRQ.mdx @@ -8,8 +8,7 @@ description: "Extending Range Queries to 2D (and beyond)." frequency: 1 --- -export const metadata = { - problems: { +export const problems = { bitSam: [ new Problem("CSES", "Forest Queries II", "1739", "Easy", false, ["2D BIT"], "[thecodingwizard's implementation](https://github.com/thecodingwizard/competitive-programming/blob/master/cses/Forest%20Queries%20II.cpp)"), ], @@ -29,7 +28,6 @@ export const metadata = { new Problem("ojuz", "IOI 2013 - Game", "IOI13_game", "Very Hard", false, ["2D Seg"], "Alternatively, use BBST in place of sparse segment tree (see Advanced - Treaps)"), new Problem("ojuz", "JOI - Golf", "JOI17_golf", "Very Hard", false, ["Seg"], ""), ], - } }; See [my implementations](https://github.com/bqi343/USACO/tree/master/Implementations/content/data-structures/2D%20Range%20Queries%20(15.2)). @@ -44,7 +42,7 @@ See [my implementations](https://github.com/bqi343/USACO/tree/master/Implementat ## 2D BIT - + ### Tutorial @@ -55,7 +53,7 @@ See [my implementations](https://github.com/bqi343/USACO/tree/master/Implementat ### Problems - + @@ -67,7 +65,7 @@ Lazy propagation on segment trees does not extend to higher dimensions. However, ## 2D Offline Sum Queries - + The intended complexity is $O(N\log^2 N)$ with a good constant factor. This requires updating points and querying rectangle sums $N$ times for points with coordinates in the range $[1,N]$. However The 2D BITs mentioned above use $O(N^2)$ memory, which is too much. Since we know all of the updates and queries beforehand, we can reduce the memory usage while maintaining a decent constant factor. @@ -93,7 +91,7 @@ It's a bit difficult to pass the above problem within the time limit. Make sure ### Problems - + ## 2D Segment Tree @@ -124,4 +122,4 @@ To resolve this, reduce the memory usage of sparse segment tree while maintaing Can also try the USACO problems from above. - \ No newline at end of file + \ No newline at end of file diff --git a/content/5_Plat/BCC_2CC.mdx b/content/5_Plat/BCC_2CC.mdx index d944287..865ebaf 100644 --- a/content/5_Plat/BCC_2CC.mdx +++ b/content/5_Plat/BCC_2CC.mdx @@ -10,8 +10,7 @@ frequency: 1 --- import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sam2: [ new Problem("YS", "Two-Edge-Connected Components", "two_edge_connected_components", "Easy", false, [], ""), ], @@ -31,7 +30,6 @@ export const metadata = { new Problem("DMOJ", "Investment", "tle17c1p6", "Hard", false, [], ""), new Problem("ojuz", "CEOI - Pipes", "CEOI15_pipes", "Hard", false, [], ""), ], - } }; @@ -40,13 +38,13 @@ export const metadata = { ## 2-Edge-Connected Components - + (implementation) ### With DSU - + The analysis for the above problem mentions an $O(m\alpha(n))$ solution. Although this is not a two-connected component problem, we can in fact use DSU to generate two-connected components. @@ -91,7 +89,6 @@ struct TwoEdgeCC { void gen() { F0R(i,N) if (par[i] == -1) dfs(i); // independently for each connected component DSU.init(N); trav(t,extra) ad(t.f,t.s); // add non-spanning edges - } }; ``` @@ -99,13 +96,13 @@ struct TwoEdgeCC { ### Problems - + - SRM 787 1000 ## [Biconnected Components](https://en.wikipedia.org/wiki/Biconnected_component) - + note that BCCs contain EDGES not VERTICES @@ -125,4 +122,4 @@ Related topics include ### Problems - \ No newline at end of file + \ No newline at end of file diff --git a/content/5_Plat/Bin_Jump.mdx b/content/5_Plat/Bin_Jump.mdx index 1ba8f46..884db3d 100644 --- a/content/5_Plat/Bin_Jump.mdx +++ b/content/5_Plat/Bin_Jump.mdx @@ -8,8 +8,7 @@ frequency: 3 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("CSES", "Company Queries I", "1687", "Easy", false, ["Binary Jumping"], ""), ], @@ -31,16 +30,15 @@ export const metadata = { new Problem("Plat", "Gathering", "866", "Hard", false, ["LCA"], "interactive!!"), new Problem("Plat", "Exercise", "901", "Very Hard", false, ["LCA"], ""), ] - } }; ## Binary Jumping - + ## Lowest Common Ancestor - + ### Tutorial @@ -59,4 +57,4 @@ export const metadata = { ### Problems - \ No newline at end of file + \ No newline at end of file diff --git a/content/5_Plat/Bitsets.mdx b/content/5_Plat/Bitsets.mdx index 77203a8..d478af6 100644 --- a/content/5_Plat/Bitsets.mdx +++ b/content/5_Plat/Bitsets.mdx @@ -10,8 +10,7 @@ frequency: 2 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { school: [ new Problem("CSES", "School Excursion", "1706", "Easy", false, ["Knapsack", "Bitset"], ""), ], @@ -29,7 +28,6 @@ export const metadata = { new Problem("CSES", "BOI - Nautilus", "https://cses.fi/247/submit/B", "Normal", false, ["Bitset"], ""), new Problem("ojuz", "IZhO - Bootfall", "IZhO17_bootfall", "Hard", false, ["Knapsack", "Bitset"], ""), ], - } }; ## Tutorial @@ -42,7 +40,7 @@ tl;dr some operations are 32x-64x faster compared to a boolean array. See the [C ## Knapsack - + Of course, the first step is to generate the sizes of each connected component. @@ -103,7 +101,7 @@ int main() { ## Cowpatibility (Gold) - + Label the cows from $0\ldots N-1$. For two cows $x$ and $y$ set `adj[x][y]=1` if they share a common flavor. Then the number of pairs of cows that are compatible (counting each pair where $x$ and $y$ are distinct twice) is equal to the sum of `adj[x].count()` over all $x$. It remains to compute `adj[x]` for all $x$. @@ -189,7 +187,7 @@ Apparently no test case contains more than $25000$ distinct colors, so we don't ## Lots of Triangles - + First, we read in the input data. `cross(a,b,c)` is positive iff `c` lies to the left of the line from `a` to `b`. @@ -350,10 +348,10 @@ Operations such as `_Find_first()` and `_Find_next()` mentioned in Errichto's bl Regarding the last application: - + In USACO Camp, this problem appeared with $N\le 10^5$ and a large time limit ... ## Additional Problems - + diff --git a/content/5_Plat/Centroid.mdx b/content/5_Plat/Centroid.mdx index ce1ff91..255e44e 100644 --- a/content/5_Plat/Centroid.mdx +++ b/content/5_Plat/Centroid.mdx @@ -18,8 +18,7 @@ TODO: import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { general: [ new Problem("CF", "Ciel the Commander", "problemset/problem/321/C", "Easy", false, ["Centroid"], ""), new Problem("Plat", "New Barns", "817", "Normal", true, ["Centroid"], ""), @@ -34,7 +33,6 @@ export const metadata = { new Problem("ojuz", "JOI - Synchronization", "JOI13_synchronization", "Hard", false, ["Centroid", "Small to Large"], "Looks like $O(N \log^3 N)$ is very fast!"), new Problem("Plat", "At Large", "793", "Very Hard", false, ["Centroid"], "tight time limit"), ] - } }; ## Centroid Decomposition @@ -134,6 +132,6 @@ public void centroid(int n) ### Problems - + *Note:* Unfortunately, it seems like constant factor is especially important for DMOJ. :| diff --git a/content/5_Plat/Convex_Hull.mdx b/content/5_Plat/Convex_Hull.mdx index e433f79..4917c08 100644 --- a/content/5_Plat/Convex_Hull.mdx +++ b/content/5_Plat/Convex_Hull.mdx @@ -10,8 +10,7 @@ frequency: 2 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("Kattis", "Convex Hull", "convexhull", "Easy", false, ["convex"], ""), ], @@ -32,12 +31,11 @@ export const metadata = { new Problem("Plat", "Circular Barn", "626", "Hard", false, ["DP", "convex"], ""), new Problem("Plat", "Falling Portals", "998", "Very Hard", false, ["convex"], ""), ], - } }; ## [Convex Hull](https://en.wikipedia.org/wiki/Convex_hull_algorithms) - + ### Tutorial @@ -49,17 +47,17 @@ export const metadata = { - [Wikipedia](https://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Convex_hull/Monotone_chain) - [My Implementation](https://github.com/bqi343/USACO/blob/master/Implementations/content/geometry%20(13)/Polygons/ConvexHull%20(13.2).h) - + ## Rotating Caliphers - + - + ## Convex Hull Trick @@ -68,6 +66,6 @@ export const metadata = { - + https://codeforces.com/contest/1083/problem/E \ No newline at end of file diff --git a/content/5_Plat/DP_Bitmasks.mdx b/content/5_Plat/DP_Bitmasks.mdx index 2522634..b895ab9 100644 --- a/content/5_Plat/DP_Bitmasks.mdx +++ b/content/5_Plat/DP_Bitmasks.mdx @@ -11,8 +11,7 @@ frequency: 2 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { general: [ new Problem("AC", "Matching", "https://atcoder.jp/contests/dp/tasks/dp_o?lang=en", "Easy", false, ["Bitmasks"], ""), new Problem("CSES", "Hamiltonian Flights", "1690", "Easy", false, ["Bitmasks"], ""), @@ -29,7 +28,6 @@ export const metadata = { new Problem("CF", "Guards in the Storehouse", "problemset/problem/845/F", "Normal", false, [], ""), new Problem("Plat", "Compound Escape", "949", "Very Hard", false, [], ""), ], - } }; @@ -50,7 +48,7 @@ You can often use this to solve subtasks. ## Problems - + ## DP on Broken Profile @@ -60,4 +58,4 @@ You can often use this to solve subtasks. (fill in? more probs?) - + diff --git a/content/5_Plat/DP_Ranges.mdx b/content/5_Plat/DP_Ranges.mdx index 3cb0eae..1aa9d05 100644 --- a/content/5_Plat/DP_Ranges.mdx +++ b/content/5_Plat/DP_Ranges.mdx @@ -10,8 +10,7 @@ frequency: 2 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { general: [ new Problem("Gold", "248", "647", "Easy", false, ["Range DP"]), new Problem("CSES", "Empty String", "1080", "Normal", false, ["Range DP"]), @@ -19,7 +18,6 @@ export const metadata = { new Problem("Plat", "Greedy Pie Eaters", "972", "Hard", false, ["Range DP"]), new Problem("Plat", "Subsequence Reversal", "698", "Hard", false, ["Range DP"]), ] - } }; ## Tutorial @@ -28,6 +26,6 @@ export const metadata = { ## Problems - + * TC SRM 787 500 diff --git a/content/5_Plat/Eulerian_Tours.mdx b/content/5_Plat/Eulerian_Tours.mdx index 7dd21fe..11f3784 100644 --- a/content/5_Plat/Eulerian_Tours.mdx +++ b/content/5_Plat/Eulerian_Tours.mdx @@ -12,8 +12,7 @@ Has not appeared on a recent USACO contest. import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sam: [ new Problem("CSES", "Mail Delivery (Undirected)", "1691", "Easy", false, ["Euler Tour"], ""), new Problem("CSES", "Teleporters (Directed)", "1693", "Easy", false, ["Euler Tour"], ""), @@ -23,12 +22,11 @@ export const metadata = { new Problem("CF", "Johnny and Megan's Necklace", "contest/1361/problem/C", "Normal", false, ["Euler Tour"], ""), new Problem("CF", "Data Center Drama", "contest/528/problem/C", "Normal", false, ["Euler Tour"], ""), ] - } }; ### Standard - + ### Tutorial @@ -36,4 +34,4 @@ export const metadata = { ### Problems - + diff --git a/content/5_Plat/Eulers_Formula.mdx b/content/5_Plat/Eulers_Formula.mdx index 1ba6acb..c6debb1 100644 --- a/content/5_Plat/Eulers_Formula.mdx +++ b/content/5_Plat/Eulers_Formula.mdx @@ -10,8 +10,7 @@ frequency: 1 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { e1: [ new Problem("DMOJ", "Land of the Rainbow Gold", "apio17p1", "Hard", false, [],""), ], @@ -21,17 +20,16 @@ export const metadata = { other: [ new Problem("Kattis", "Island Archipelago", "https://utipc20s.kattis.com/problems/utipc20s.islandarchipelago", "Very Hard", false, [],""), ], - } }; ## Example 1 - + ## Example 2 - + Extension: - \ No newline at end of file + \ No newline at end of file diff --git a/content/5_Plat/Flows.mdx b/content/5_Plat/Flows.mdx index ac7769f..9a0472e 100644 --- a/content/5_Plat/Flows.mdx +++ b/content/5_Plat/Flows.mdx @@ -10,8 +10,7 @@ frequency: 1 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { maxSam: [ new Problem("CSES", "Download Speed", "1694", "Easy", false, ["Max Flow"], ""), ], @@ -35,12 +34,11 @@ export const metadata = { new Problem("CF", "Goods Transportation", "problemset/problem/724/E", "Hard", false, [], ""), new Problem("AC", "ARC E - MUL", "http://arc085.contest.atcoder.jp/tasks/arc085_c", "Hard", false, [], ""), ] - } }; ## Maximum Flow - + ### Tutorial @@ -51,15 +49,15 @@ export const metadata = { ### Problems - + ## Bipartite Matching - + ## Dinic's Algorithm - + Hopcroft-Karp Bipartite Matching? @@ -75,7 +73,7 @@ However, the standard implementation of Dinic's is (almost) always fast enough. ## Min-Cut Max Flow - + (show equivalence) @@ -89,4 +87,4 @@ https://maps20.kattis.com/problems/thewrathofkahn ## Problems - + diff --git a/content/5_Plat/Fracture.mdx b/content/5_Plat/Fracture.mdx index e8eef55..8272064 100644 --- a/content/5_Plat/Fracture.mdx +++ b/content/5_Plat/Fracture.mdx @@ -11,8 +11,7 @@ frequency: 1 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("Plat", "Robotic Cow Herd", "674", "Normal", false, [], ""), ], @@ -21,7 +20,6 @@ export const metadata = { new Problem("DMOJ", "CCO - Shopping Plans", "cco20p6", "Very Hard", false, [], "Generalization of RoboHerd."), new Problem("YS", "K-th Shortest Walk", "k_shortest_walk", "Very Hard", false, [], "(english description?), [Relevant Paper](https://www.ics.uci.edu/~eppstein/pubs/Epp-SJC-98.pdf), Can use to solve RoboHerd!"), ], - } }; @@ -147,7 +145,7 @@ int main() { ## Robotic Cow Herd - + As with the analysis, for each location you should @@ -308,4 +306,4 @@ int main() { ## Other Problems - \ No newline at end of file + \ No newline at end of file diff --git a/content/5_Plat/Geo_Pri.mdx b/content/5_Plat/Geo_Pri.mdx index f3bb57b..fecbf4a 100644 --- a/content/5_Plat/Geo_Pri.mdx +++ b/content/5_Plat/Geo_Pri.mdx @@ -7,8 +7,7 @@ description: Basic setup for geometry problems. import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { standard: [ new Problem("YS", "Sort Points by Argument", "sort_points_by_argument", "Intro", false, [], ""), new Problem("Kattis", "Segment Intersection", "segmentintersection", "Intro", false, [], ""), @@ -23,7 +22,6 @@ export const metadata = { new Problem("Kattis", "Max Collinear", "maxcolinear", "Easy", false, [], ""), new Problem("Kattis", "Birthday Cake", "birthdaycake", "Easy", false, [], ""), ] - } }; ## Primitives @@ -50,11 +48,11 @@ You should know basic operations like cross product and dot product.
- + ### Misc Problems - + - [Racing Off Track](https://open.kattis.com/contests/acpc17open/problems/racingofftrack) (link doesn't work ...) - [TopCoder Watchtower](https://community.topcoder.com/stat?c=problem_statement&pm=2014&rd=4685) diff --git a/content/5_Plat/HLD.mdx b/content/5_Plat/HLD.mdx index 3237ea3..f352860 100644 --- a/content/5_Plat/HLD.mdx +++ b/content/5_Plat/HLD.mdx @@ -11,8 +11,7 @@ frequency: 1 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("CSES", "Company Queries II", "1688", "Intro|Easy", false, ["LCA"], "Pure implementation; see Benq's library code, it has a function for LCA. Though this problem can be solved with binary lifting as well, you should do it with HLD to get practice."), ], @@ -28,10 +27,9 @@ export const metadata = { new Problem("ojuz", "JOI - Synchronization", "JOI13_synchronization", "Hard", false, ["HLD"], "$O(N\\log N)$ :D"), new Problem("ojuz", "JOI - Cats or Dogs", "JOI18_catdog", "Very Hard", false, ["HLD"], ""), ], - } }; - + ## Tutorial @@ -50,4 +48,4 @@ export const metadata = { ## Problems - + diff --git a/content/5_Plat/LC.mdx b/content/5_Plat/LC.mdx index 106b008..c29351a 100644 --- a/content/5_Plat/LC.mdx +++ b/content/5_Plat/LC.mdx @@ -10,8 +10,7 @@ frequency: 1 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("YS", "Line Add Get Min", "line_add_get_min", "Normal", false, [], ""), ], @@ -24,7 +23,6 @@ export const metadata = { new Problem("TOKI", "Mall & Transportation", "https://tlx.toki.id/contests/troc-13-div-1/problems/D", "Very Hard", false, [], ""), new Problem("Old Gold", "Fencing the Herd", "534", "Very Hard", false, [], ""), ] - } }; ## Half-Plane Intersection @@ -34,11 +32,11 @@ export const metadata = { expected linear!
- + ## LineContainer - + code @@ -48,6 +46,6 @@ export const metadata = { ## Problems - + https://atcoder.jp/contests/arc066/tasks/arc066_d \ No newline at end of file diff --git a/content/5_Plat/Lagrange.mdx b/content/5_Plat/Lagrange.mdx index c9e40b0..92af967 100644 --- a/content/5_Plat/Lagrange.mdx +++ b/content/5_Plat/Lagrange.mdx @@ -10,8 +10,7 @@ frequency: 1 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("Plat", "Tall Barn", "697", "Easy", false, [], ""), ], @@ -20,12 +19,11 @@ export const metadata = { new Problem("Kattis", "Blazing New Trails", "blazingnewtrails", "Normal", false, [], ""), new Problem("ojuz", "Aliens", "IOI16_aliens", "Hard", false, [], ""), ] - } }; adding lambda\*smth - + ## Tutorial @@ -35,4 +33,4 @@ adding lambda\*smth ## Problems - \ No newline at end of file + \ No newline at end of file diff --git a/content/5_Plat/Merging.mdx b/content/5_Plat/Merging.mdx index f94bd07..fbf68c0 100644 --- a/content/5_Plat/Merging.mdx +++ b/content/5_Plat/Merging.mdx @@ -11,8 +11,7 @@ frequency: 1 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sam: [ new Problem("CSES", "Distinct Colors", "1139", "Intro", false, ["Merging"]), ], @@ -23,7 +22,6 @@ export const metadata = { new Problem("Plat", "Disruption", "842", "Normal", false, ["Merging"]), new Problem("POI", "Tree Rotations", "https://szkopul.edu.pl/problemset/problem/sUe3qzxBtasek-RAWmZaxY_p/site/?key=statement", "Normal", false, ["Merging", "Indexed Set"], ""), ], - } }; ## Additional Reading @@ -38,7 +36,7 @@ export const metadata = { Obviously [linked lists](http://www.cplusplus.com/reference/list/list/splice/) can be merged in $O(1)$ time. But what about sets or vectors? - + Let's consider a tree rooted at node $1$, where each node has a color. @@ -122,7 +120,7 @@ A set doesn't have to be an `std::set`. Many data structures can be merged, such ## Problems - + diff --git a/content/5_Plat/Offline_Con.mdx b/content/5_Plat/Offline_Con.mdx index 54c8480..2685d06 100644 --- a/content/5_Plat/Offline_Con.mdx +++ b/content/5_Plat/Offline_Con.mdx @@ -10,8 +10,7 @@ frequency: 0 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { rollback: [ new Problem("YS", "Persistent Union Find", "persistent_unionfind", "Normal", false, [], ""), new Problem("YS", "Vertex Add Component Sum", "dynamic_graph_vertex_add_component_sum", "Hard", false, [], ""), @@ -20,7 +19,6 @@ export const metadata = { ins: [ new Problem("Old Gold", "Fencing the Herd", "534", "Hard", false, [], ""), ], - } }; ### DSU With Rollback @@ -29,7 +27,7 @@ no path compression (tutorial?) - + \ No newline at end of file + --> \ No newline at end of file diff --git a/content/5_Plat/RURQ.mdx b/content/5_Plat/RURQ.mdx index a8ce3c9..aeb9395 100644 --- a/content/5_Plat/RURQ.mdx +++ b/content/5_Plat/RURQ.mdx @@ -10,8 +10,7 @@ frequency: 1 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { bitSample: [ new Problem("SPOJ", "Horrible Queries", "HORRIBLE", "Easy", false, ["BIT-Range"], ""), ], @@ -34,12 +33,11 @@ export const metadata = { segTreeBeats: [ new Problem("YS", "Range Chmin Chmax Add Range Sum", "range_chmin_chmax_add_range_sum", "Very Hard", false, ["SegTreeBeats"], ""), ], - } }; ## BIT Revisited - + Binary Indexed Trees can support range increments in addition to range sum queries. @@ -54,11 +52,11 @@ Binary Indexed Trees can support range increments in addition to range sum queri ### Problems - + ## Lazy Segment Tree - + ### Tutorial @@ -71,7 +69,7 @@ Binary Indexed Trees can support range increments in addition to range sum queri ### Problems - + ## Lazy Segment Tree - Counting Minimums @@ -79,4 +77,4 @@ use segment tree that keeps track of minimum and # of minimums (describe) - \ No newline at end of file + \ No newline at end of file diff --git a/content/5_Plat/SCC.mdx b/content/5_Plat/SCC.mdx index 17eb72c..7bbc6b8 100644 --- a/content/5_Plat/SCC.mdx +++ b/content/5_Plat/SCC.mdx @@ -11,8 +11,7 @@ frequency: 1 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { ex: [ new Problem("CSES", "Planets & Kingdoms", "1683", "Easy", false, [], ""), ], @@ -27,12 +26,11 @@ export const metadata = { satEx: [ new Problem("CSES", "Giant Pizza", "1684", "Normal", false, [], "") ], - } }; ## SCCs - + ### Tutorial @@ -49,11 +47,11 @@ export const metadata = { ### Problems - + ## 2-SAT - + (impl) diff --git a/content/5_Plat/SPneg.mdx b/content/5_Plat/SPneg.mdx index 90c7e9a..2dccf2d 100644 --- a/content/5_Plat/SPneg.mdx +++ b/content/5_Plat/SPneg.mdx @@ -10,8 +10,7 @@ frequency: 0 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sam: [ new Problem("Kattis", "SSSP Negative", "shortestpath3", "Easy", false, [], ""), new Problem("Kattis", "APSP (with negative weights)", "allpairspath", "Easy", false, [], ""), @@ -24,10 +23,9 @@ export const metadata = { linear: [ new Problem("ojuz", "Restore Array", "RMI19_restore", "Normal", false, [], "similar to [Art](https://codeforces.com/gym/102394/problem/A)"), ], - } }; - +
@@ -46,7 +44,7 @@ Can also use [Shortest Path Faster Algorithm](https://en.wikipedia.org/wiki/Shor ### Problems - + ## Simple Linear Programming @@ -64,4 +62,4 @@ You can also use shortest path algorithms to solve the following problem (a very ### Problems - + diff --git a/content/5_Plat/Seg_Ext.mdx b/content/5_Plat/Seg_Ext.mdx index 8a06167..78a8058 100644 --- a/content/5_Plat/Seg_Ext.mdx +++ b/content/5_Plat/Seg_Ext.mdx @@ -10,8 +10,7 @@ frequency: 3 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { walkSam: [ new Problem("CSES", "Hotel Queries", "1143", "Easy", false, ["PURQ"], "walk"), ], @@ -35,12 +34,11 @@ export const metadata = { new Problem("Kattis", "Easy Query", "easyquery", "Hard", false, ["Wavelet"], ""), new Problem("DMOJ", "Ninjaclasher's Wrath 2", "globexcup19s4", "Hard", false, ["Wavelet"], ""), ], - } }; ## Walking on a Segment Tree - + You want to support queries of the following form on an array $a_1,\ldots,a_N$ (along with point updates). @@ -48,19 +46,19 @@ You want to support queries of the following form on an array $a_1,\ldots,a_N$ ( Of course, you can do this in $O(\log^2N)$ time with a max segment tree and binary searching on the first $i$ such that $\max(a_1,\ldots,a_i)\ge x$. But try to do this in $O(\log N)$ time. - + ## Combining - + (solution to above problem) - + ## Wavelet Tree - + ### Tutorial @@ -70,4 +68,4 @@ Of course, you can do this in $O(\log^2N)$ time with a max segment tree and bina ### Problems - + diff --git a/content/5_Plat/Slope.mdx b/content/5_Plat/Slope.mdx index cc080a5..a7948b0 100644 --- a/content/5_Plat/Slope.mdx +++ b/content/5_Plat/Slope.mdx @@ -11,8 +11,7 @@ frequency: 1 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { ex: [ new Problem("CF", "Problem Without a Legend", "contest/713/problem/C", "Easy", false, ["Slope Trick"], ""), ], @@ -34,7 +33,6 @@ export const metadata = { new Problem("CF", "April Fools' Problem", "contest/802/problem/O", "Very Hard", false, ["Slope Trick"], "binary search on top of slope trick"), new Problem("ICPC World Finals", "Conquer the World", "https://icpc.kattis.com/problems/conquertheworld", "Very Hard", false, ["Slope Trick", "Small to Large"], "ICPC world finals, 0 solves in contest - \"Potatoes\" on tree!!"), ], - } }; ## Tutorials @@ -61,13 +59,13 @@ Usually you can come up with a slower (usually $O(N^2)$) DP first and then optim The rest of this module assumes that you know the basic idea of this trick. In particular, you should be at least somewhat familiar with the $O(N\log N)$ time solution to the first problem in zscoder's tutorial: - + It's ok if you found the explanations confusing; the example below should help clarify. ## Buy Low Sell High - + ### Slow Solution @@ -212,7 +210,7 @@ int main() { ## Potatoes & Fertilizers - + ### Simplifying the Problem @@ -290,7 +288,7 @@ int main() { ## USACO Landscaping - + This looks similar to the previous task (we're moving dirt instead of fertilizer), so it's not too hard to guess that slope trick is applicable. @@ -367,4 +365,4 @@ We can solve this problem when $\sum A_i+\sum B_i$ is not so small with lazy bal ## Problems - \ No newline at end of file + \ No newline at end of file diff --git a/content/5_Plat/Sqrt.mdx b/content/5_Plat/Sqrt.mdx index 684b39a..7b88278 100644 --- a/content/5_Plat/Sqrt.mdx +++ b/content/5_Plat/Sqrt.mdx @@ -7,8 +7,7 @@ frequency: 1 --- import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { fst: [ new Problem("CF", "Tree Queries", "contest/1254/problem/D", "Hard", false, [], ""), new Problem("wcipeg", "COI 08-Otoci", "https://wcipeg.com/problem/coi08p2", "Hard", false, ["HLD"], "Editorial rebuilds HLD after certain # of updates ..."), @@ -22,7 +21,6 @@ export const metadata = { other: [ new Problem("Plat", "Train Tracking", "841", "Insane", false, [], ""), ] - } }; @@ -35,7 +33,7 @@ partitioning into sqrt blocks (each block can have some sort of data structure . optimization tips? (ez to get TLE with bad constant ..., can get AC with suboptimal complexity ...) - + ## Mo's @@ -50,7 +48,7 @@ optimization tips? (ez to get TLE with bad constant ..., can get AC with subopti ### Block Tree - + @@ -58,4 +56,4 @@ optimization tips? (ez to get TLE with bad constant ..., can get AC with subopti ### Train Tracking - + diff --git a/content/5_Plat/String_Search.mdx b/content/5_Plat/String_Search.mdx index aa46fda..03af5ad 100644 --- a/content/5_Plat/String_Search.mdx +++ b/content/5_Plat/String_Search.mdx @@ -8,8 +8,7 @@ description: Knuth-Morris-Pratt and Z Algorithms (and a few more related topics) frequency: 1 --- -export const metadata = { - problems: { +export const problems = { KMP: [ new Problem("Kattis", "String Matching", "problems/stringmatching", "Easy", false, ["Strings"], "Naive KMP works. Just be careful about I/O"), new Problem("POJ", "(USACO Gold 05) Cow Patterns", "http://poj.org/problem?id=3167", "Hard", false, ["Strings"], "Run KMP, except each state needs to be considered as not only a length, but also mapping of pattern to # of spots"), @@ -36,7 +35,6 @@ export const metadata = { pal: [ new Problem("ojuz", "Palindrome", "APIO14_palindrome", "Easy", false, [], ""), ] - } }; ## General @@ -59,7 +57,7 @@ Specifically, it computes the longest substring that is both a prefix and suffix - + ## Z Algorithm @@ -71,7 +69,7 @@ The **Z-Algorithm** is another linear time string comparison algorithm like KMP,
- + ## Manacher @@ -88,7 +86,7 @@ It can determine the longest palindrome centered at each character. If s[l, r] is a palindrome, then s[l+1, r-1] is as well. - + # Multiple Strings @@ -104,7 +102,7 @@ This means that every prefix of a string is an ancestor of that string's node.
- + ## Aho-Corasick @@ -122,7 +120,7 @@ Build the entire trie first, and then run a *BFS* to construct the fail array.
- + ## Palindromic Tree @@ -132,6 +130,6 @@ Build the entire trie first, and then run a *BFS* to construct the fail array.
- + DMOJ thing diff --git a/content/5_Plat/Suffix_Array.mdx b/content/5_Plat/Suffix_Array.mdx index da079c0..3059512 100644 --- a/content/5_Plat/Suffix_Array.mdx +++ b/content/5_Plat/Suffix_Array.mdx @@ -10,8 +10,7 @@ frequency: 1 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { sample: [ new Problem("YS", "Suffix Array", "suffixarray", "Easy", false, [], ""), ], @@ -28,7 +27,6 @@ export const metadata = { runSam: [ new Problem("YS", "Run Enumerate", "runenumerate", "Hard", false, [], ""), ] - } }; ## Resources @@ -41,7 +39,7 @@ export const metadata = { ## Suffix Array - + ### Implementations @@ -53,11 +51,11 @@ export const metadata = { ## LCP Array - + Quickly compute longest common prefix of two suffixes. - + ## Inverse Burrows-Wheeler @@ -67,7 +65,7 @@ Quickly compute longest common prefix of two suffixes. CSES Guide? - + ## Run Enumerate @@ -77,5 +75,5 @@ CSES Guide? (describe how to do easily w/ suffix array) - + diff --git a/content/5_Plat/Sweep_Line.mdx b/content/5_Plat/Sweep_Line.mdx index af58bb8..6a6726e 100644 --- a/content/5_Plat/Sweep_Line.mdx +++ b/content/5_Plat/Sweep_Line.mdx @@ -10,8 +10,7 @@ frequency: 1 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { closest: [ new Problem("Kattis", "Closest Pair", "closestpair2", "Normal", false, [], ""), ], @@ -24,7 +23,6 @@ export const metadata = { man: [ new Problem("CSA", "The Sprawl", "the-sprawl", "Hard", false, [], ""), ] - } }; (what's line sweep?) @@ -36,7 +34,7 @@ export const metadata = { ## Closest Pair - + (explanation? KACTL?) @@ -44,18 +42,18 @@ export const metadata = { (refer to previous module) - + (filling in the details?) ## Manhattan MST - + (KACTL code) explanation? topcoder prob has - + TC 760 ComponentsForever \ No newline at end of file diff --git a/content/6_Advanced/Extend_Euclid.mdx b/content/6_Advanced/Extend_Euclid.mdx index 64644c8..51d2c00 100644 --- a/content/6_Advanced/Extend_Euclid.mdx +++ b/content/6_Advanced/Extend_Euclid.mdx @@ -10,8 +10,7 @@ frequency: 1 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { kat: [ new Problem("Kattis","Modular Arithmetic", "modulararithmetic"), ], @@ -19,7 +18,6 @@ export const metadata = { new Problem("Kattis","Chinese Remainder", "chineseremainder"), new Problem("Kattis","Chinese Remainder (non-relatively prime moduli)", "generalchineseremainder"), ], - } }; ## Euclidean Algorithm @@ -140,7 +138,7 @@ Note that this works when $a,b$ are quite large (say, $\approx 2^{60}$) and we w
- + It seems that when multiplication / division is involved in this problem, $n^2 < \texttt{LLONG\_MAX}$. @@ -176,4 +174,4 @@ int main() {
- + diff --git a/content/6_Advanced/FFT-ext.mdx b/content/6_Advanced/FFT-ext.mdx index 2cce889..b4cf619 100644 --- a/content/6_Advanced/FFT-ext.mdx +++ b/content/6_Advanced/FFT-ext.mdx @@ -9,8 +9,7 @@ frequency: 0 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { ys: [ new Problem("YS", "Partition Function", "partition_function", "?", false, [], ""), new Problem("YS", "Bernoulli Number", "bernoulli_number", "?", false, [], ""), @@ -19,7 +18,6 @@ export const metadata = { new Problem("Plat", "Tree Depth", "974", "Hard", false, ["genfunc"], ""), new Problem("Plat", "Exercise", "1045", "Hard", false, ["permutation"], "genfuncs not required but possibly helpful"), ], - } }; ## More Complex Operations @@ -36,13 +34,13 @@ export const metadata = { ### Problems - + ## Counting No advanced knowledge about generating functions is required for either of these problems. - + However, these do: diff --git a/content/6_Advanced/Flow_LB.mdx b/content/6_Advanced/Flow_LB.mdx index a51310b..419b3c1 100644 --- a/content/6_Advanced/Flow_LB.mdx +++ b/content/6_Advanced/Flow_LB.mdx @@ -10,8 +10,7 @@ frequency: 0 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { hungry: [ new Problem("DMOJ", "Hungry Squirrels", "wac4p6", "Normal", false, [], ""), ], @@ -21,10 +20,9 @@ export const metadata = { new Problem("CF", "Incorrect Flow", "contest/708/problem/D", "Normal", false, [], ""), new Problem("AC", "Multi-Path Story", "https://atcoder.jp/contests/jag2013summer-day4/tasks/icpc2013summer_day4_i", "Normal", false, [], ""), ], - } }; - + ### Tutorial @@ -34,4 +32,4 @@ export const metadata = { ### Problems - \ No newline at end of file + \ No newline at end of file diff --git a/content/6_Advanced/LCT.mdx b/content/6_Advanced/LCT.mdx index e925a07..3058bfa 100644 --- a/content/6_Advanced/LCT.mdx +++ b/content/6_Advanced/LCT.mdx @@ -10,8 +10,7 @@ frequency: 1 import { Problem } from "../models"; -export const metadata = { - problems: { +export const problems = { lctSam: [ new Problem("YS", "Vertex Add Path Sum", "dynamic_tree_vertex_add_path_sum", "Normal", false, ["LCT"], ""), ], @@ -38,7 +37,6 @@ export const metadata = { new Problem("CF", "Old Driver Tree", "contest/1172/problem/E", "Hard", false, ["LCT"], ""), new Problem("DMOJ", "Dynamic Tree Test", "ds5", "Very Hard", false, ["LCT"], ""), ] - } }; ## Splay Tree @@ -54,7 +52,7 @@ export const metadata = { ## Link Cut Tree - Paths - + ### Tutorial @@ -65,7 +63,7 @@ export const metadata = { ### Problems - +