From a594005f13f3421ef2873b621a31c2ac7708ec55 Mon Sep 17 00:00:00 2001 From: caoash Date: Tue, 16 Jun 2020 20:32:29 -0500 Subject: [PATCH 1/3] wrote data structures gold --- content/3_Bronze/Rect_Geo.md | 4 ++ content/5_Gold/DS.md | 91 ++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 content/5_Gold/DS.md diff --git a/content/3_Bronze/Rect_Geo.md b/content/3_Bronze/Rect_Geo.md index aa42c02..71057c9 100644 --- a/content/3_Bronze/Rect_Geo.md +++ b/content/3_Bronze/Rect_Geo.md @@ -20,9 +20,13 @@ Rectangle newRect = new Rectangle(x, y, width, height); ``` The `Rectangle` class supports numerous useful methods. + - `firstRect.intersects(secondRect)` checks if two rectangles intersect. + - `firstRect.union(secondRect)` returns a rectangle representing the union of two rectangles. + - `firstRect.contains(x, y)` checks whether the integer point (x,y) exists in firstRect. + - `firstRect.intersect(secondRect)` returns a rectangle representing the intersection of two rectangles. This class can often lessen the implementation needed in a lot of bronze problems and codeforces problems. diff --git a/content/5_Gold/DS.md b/content/5_Gold/DS.md new file mode 100644 index 0000000..5c05e55 --- /dev/null +++ b/content/5_Gold/DS.md @@ -0,0 +1,91 @@ + +--- +id: data-structures-gold +title: "Data Structures (Gold)" +author: Michael Cao +prerequisites: + - + - Bronze - Data Structures + - (?) Silver - Data Structures +--- + +More advanced applications of data structures introduced in earlier divisions using USACO Gold Problems. + + + +# 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 problem, 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. + +## Further Reading +- "Nearest Smallest Element" from CPH 8 +- [CP Algorithms (Min Stack)](https://cp-algorithms.com/data_structures/stack_queue_modification.html) +- [Medium](https://medium.com/@vishnuvardhan623/monotonic-stack-e9dcc4fa8c3e) + +## Problems +- [Concurrently Balanced Strings (Old Gold)](http://www.usaco.org/index.php?page=viewproblem2&cpid=194) +- [Max Histogram Area (Leetcode)](https://leetcode.com/problems/largest-rectangle-in-histogram/) + +(add more once codeforces comes up) + +# Sliding Window (Deque) + +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. + +Let's store a `std::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 performing the operations $s$ -= $a_i$ and $s$ += $a_{j+1}$. + +## Further Reading +- "Sliding Window" from CPH 8 + - Read [this article]([https://cp-algorithms.com/data_structures/stack_queue_modification.html](https://cp-algorithms.com/data_structures/stack_queue_modification.html)) to learn about the "min queue" that CPH describes. +- [Medium]([https://levelup.gitconnected.com/an-introduction-to-sliding-window-algorithms-5533c4fe1cc7](https://levelup.gitconnected.com/an-introduction-to-sliding-window-algorithms-5533c4fe1cc7)) +- [G4G]([https://www.geeksforgeeks.org/window-sliding-technique/](https://www.geeksforgeeks.org/window-sliding-technique/)) + +## Problems +- [Haybale Feast (Gold)](http://usaco.org/index.php?page=viewproblem2&cpid=767) + - Direct application of sliding window. +- [Train Tracking 2 (Plat)]([http://www.usaco.org/current/data/sol_train_platinum_open18.html](http://www.usaco.org/current/data/sol_train_platinum_open18.html)) + - Not really sliding window but mentions it. + - Extremely difficult. + +(add more once codeforces comes up) + +# Merging Sets +Let's consider a tree, rooted at node $1$, where each node has a color (see [CSES Distinct Colors](https://cses.fi/problemset/task/1139)). + +For each node, let's store a set containing only that node, and we want to merge the sets in the nodes subtree together such that each node has a set consisting of all colors in the nodes subtree. Doing this allows us to solve a variety of problems, such as query the number of distinct colors in each subtree. Doing this naively, however, yields a runtime complexity of $O(N^2)$. + +However, with just a few lines of code, we can significantly speed this up. +```cpp +if(a.size() < b.size()){ //for two sets a and b + swap(a,b); +} +``` +In other words, by merging the smaller set into the larger one, the runtime complexity becomes $O(N\log N).$ +
+ Proof + +When merging two sets, you move from the smaller set to the larger set. If the size of the smaller set is $X$, then the size of the resulting set is at least $2X$. Thus, an element that has been moved $Y$ times will be in a set of size $2Y$, and since the maximum size of a set is $N$ (the root), each element will be moved at most $O(\log N$) times leading to a total complexity of $O(N\log N)$. +
+ +Additionally, a set doesn't have to be an `std::set`. Many data structures can be merged, such as `std::map` or even adjacency lists. + +[[info | Challenge]] +| Prove that if you instead merge sets that have size equal to the depths of the subtrees, then small to large merging does $O(N)$ insert calls. + +## Further Reading +- "Merging Data Structures" from CPH 18 + +## Problems +- [Favorite Colors (USACO Gold)](http://www.usaco.org/index.php?page=viewproblem2&cpid=1042) + - Merge Adjacency Lists From 602aa1c8e1f2cbf0d82e29eaa2397965ca63f4d3 Mon Sep 17 00:00:00 2001 From: caoash Date: Tue, 16 Jun 2020 20:34:09 -0500 Subject: [PATCH 2/3] fixed small spacing issue --- content/5_Gold/DS.md | 1 - 1 file changed, 1 deletion(-) diff --git a/content/5_Gold/DS.md b/content/5_Gold/DS.md index 5c05e55..98cd383 100644 --- a/content/5_Gold/DS.md +++ b/content/5_Gold/DS.md @@ -1,4 +1,3 @@ - --- id: data-structures-gold title: "Data Structures (Gold)" From 527ce9698e8365a2eaaaa257f5ec23bc56303159 Mon Sep 17 00:00:00 2001 From: Siyong Date: Tue, 16 Jun 2020 18:35:56 -0700 Subject: [PATCH 3/3] Update Sorting_Custom_2.md --- content/4_Silver/Sorting_Custom_2.md | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/content/4_Silver/Sorting_Custom_2.md b/content/4_Silver/Sorting_Custom_2.md index 9dbd6f5..b4e8be4 100644 --- a/content/4_Silver/Sorting_Custom_2.md +++ b/content/4_Silver/Sorting_Custom_2.md @@ -38,6 +38,10 @@ There are 2 main ways to have a custom comparator in c++. ```cpp +#include +using namespace std; +int randint(int low, int high) {return low+rand()%(high-low);} + struct Foo { int Bar; @@ -47,6 +51,7 @@ struct Foo const int N = 8; int main() { + srand(69); Foo a[N]; for(int i=0;i ```cpp +#include +using namespace std; +int randint(int low, int high) {return low+rand()%(high-low);} + struct Foo { int Bar; @@ -122,12 +131,14 @@ struct Foo const int N = 8; Foo a[N]; bool cmp1(Foo foo1, Foo foo2) {return foo1.Bar < foo2.Bar;} -function cmp2 = [](Foo foo1, Foo foo2) {return foo1.Bar < foo2.Bar;}; // lambda expression -// void(Foo,Foo) means that the function takes in two parameters of type Foo and returns void -// "function"" can be replaced with "auto" +function cmp2 = [](Foo foo1, Foo foo2) {return foo1.Bar < foo2.Bar;}; // lambda expression +// bool(Foo,Foo) means that the function takes in two parameters of type Foo and returns bool +// "function"" can be replaced with "auto" int main() { + srand(69); + printf("--- Method 1 ---\n"); for(int i=0;i ```cpp +#include +using namespace std; + const int N = 8; int a[N], b[N] = {4,8,2,3,4,1,2,4}; -int main() { +int main() +{ printf("--- Comparator 1 ---\n"); - iota(a, a+N, 0); // a={0,1,2,3,4,5,6,7} + iota(a, a+N, 0); sort(a, a+N, greater()); //sort a in decreasing order for(int i=0;i