This commit is contained in:
Nathan Wang 2020-07-19 20:13:38 -07:00
commit f48a57122b
54 changed files with 895 additions and 613 deletions

View file

@ -2,10 +2,11 @@
id: code-con id: code-con
title: Code Conventions title: Code Conventions
author: Nathan Wang, Benjamin Qi, Michael Cao, Nathan Chen 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: prerequisites:
- expected - expected
- modules - modules
- cpp-tips
--- ---
The code we provide should follow the conventions below. Please note that you do _not_ have to copy our conventions; there is no "right" convention for coding! The code we provide should follow the conventions below. Please note that you do _not_ have to copy our conventions; there is no "right" convention for coding!
@ -97,7 +98,7 @@ The "template" refers to code that is assumed to be in every file.
Templates in C++ can take advantange of more powerful features than the other contest languages, and they can be more customized to each competitor. Don't be afraid to write your own template or don't use one at all! Regardless, The USACO Guide will assume the use of the below template in any C++ Code. Templates in C++ can take advantange of more powerful features than the other contest languages, and they can be more customized to each competitor. Don't be afraid to write your own template or don't use one at all! Regardless, The USACO Guide will assume the use of the below template in any C++ Code.
See [C++ Tips & Tricks](./cpp-tips) for explanations of the following code. <!-- See [C++ Tips & Tricks](./cpp-tips) for explanations of the following code. -->
```cpp ```cpp
#include <bits/stdc++.h> #include <bits/stdc++.h>

View file

@ -19,6 +19,12 @@ You should read *all* the problems first (don't give up on any problems prematur
Problem difficulties can be out of order, so keep that in mind before focusing down 3 hours on problem 1 and not getting anywhere. Do a good amount of thinking on each problem before deciding which ones to focus on and which to put aside. Problem difficulties can be out of order, so keep that in mind before focusing down 3 hours on problem 1 and not getting anywhere. Do a good amount of thinking on each problem before deciding which ones to focus on and which to put aside.
<Info title="Pro Tip">
Historically, the first platinum problem has never been the hardest (though you shouldn't count on this).
</Info>
### Time allocation ### Time allocation
It's the worst feeling in the world to sink a couple hours into a problem before realizing that a different problem would've been easy pickings; we can easily avoid this situation with proper time allocation. You have to use your own judgement in deciding what is likely solvable and what should be quit. Generally, don't spend "too long" on one problem, and stay away from problems that look like they test something you don't know well. It's the worst feeling in the world to sink a couple hours into a problem before realizing that a different problem would've been easy pickings; we can easily avoid this situation with proper time allocation. You have to use your own judgement in deciding what is likely solvable and what should be quit. Generally, don't spend "too long" on one problem, and stay away from problems that look like they test something you don't know well.

View file

@ -5,16 +5,20 @@ author: Benjamin Qi
description: Contests that I participate in as well as a few tools. description: Contests that I participate in as well as a few tools.
--- ---
See [clist.by](https://clist.by/coder/bqi343/) for an extensive list of contests. Make sure to [upsolve](https://en.wiktionary.org/wiki/upsolve) after the contest ends! Make sure to [upsolve](https://en.wiktionary.org/wiki/upsolve) after the contest ends!
## Contests that I regularly participate in ## Contests that I regularly participate in
<Resources>
<Resource source="CLIST" title="My Profile" url="https://clist.by/coder/bqi343/" starred>extensive list of contests</Resource>
<Resource source="kenkoooo" title="AtCoder Visualizer" url="https://kenkoooo.com/atcoder/#/table/Benq" starred>keep track of which problems you've done</Resource>
</Resources>
- [AtCoder](https://beta.atcoder.jp/contests/archive) - [AtCoder](https://beta.atcoder.jp/contests/archive)
- probably the highest quality, although difficulty isn't *always* reasonable - probably the highest quality, although difficulty isn't *always* reasonable
- Contests - Contests
- Beginner / Regular: 4 or 6 problems, ~100 min - Beginner / Regular: 4 or 6 problems, ~100 min
- Grand: 6 problems, 110 - 150 min - Grand: 6 problems, 110 - 150 min
- [Visualizer](https://kenkoooo.com/atcoder/#/table/Benq)
- [Codeforces](http://codeforces.com/problemset) - [Codeforces](http://codeforces.com/problemset)
- Contests - Contests
- Div 1/2/3/(4?): 5-6 problems (with some variations), 2 to 2.5 hrs - Div 1/2/3/(4?): 5-6 problems (with some variations), 2 to 2.5 hrs
@ -29,26 +33,21 @@ See [clist.by](https://clist.by/coder/bqi343/) for an extensive list of contests
## Other Websites ## Other Websites
- [Google Kickstart](https://codingcompetitions.withgoogle.com/kickstart) <Resources>
- Feb - Nov <Resource title="Kattis" url="https://open.kattis.com/">misc ICPC contests</Resource>
- [Kattis](https://open.kattis.com/) <Resource title="TOKI" url="https://tlx.toki.id/">Indonesian</Resource>
- misc ICPC contests <Resource title="Kickstart" url="https://codingcompetitions.withgoogle.com/kickstart">Feb - Nov</Resource>
- [HackerEarth](http://hackerearth.com/) <Resource title="HackerEarth" url="http://hackerearth.com/">Monthly "Easy" - quality is not always good</Resource>
- Monthly "Easy" <Resource title="CodeChef" url="http://codechef.com/">Monthly Long, Lunchtime, Cookoff - quality is not always good</Resource>
- quality is not always good <Resource title="HackerRank" url="https://www.hackerrank.com/dashboard">apparently only "Hack the Interview" contests now</Resource>
- [Codechef](http://codechef.com/) <Resource title="CSAcademy" url="https://csacademy.com/contest/archive/">no regular contests anymore, archive is still worth a look</Resource>
- Lunchtime, Cookoff </Resources>
- quality is not always good
- [HackerRank](https://www.hackerrank.com/dashboard)
- Apparently there are only "Hack the Interview" contests now.
[CS Academy](https://csacademy.com/contest/archive/) does not hold regular contests anymore, but it's still worth looking at. <!-- - Contests
- Contests
- Div 2: 5 problems, 2 hrs - Div 2: 5 problems, 2 hrs
- Open: 7 problems, 2 hrs - Open: 7 problems, 2 hrs
- Archive - Archive
- short statements, good editorials - short statements, good editorials -->
## Onsite Finals (Individual) ## Onsite Finals (Individual)
@ -74,20 +73,25 @@ Only considering contests which allow C++ since the others aren't legit. (add mo
## Codeforces Tools ## Codeforces Tools
- [Stopstalk](https://www.stopstalk.com) <Resources>
- [Code Drills](http://code-drills.com/) <Resource title="CF-Predictor" url="https://chrome.google.com/webstore/detail/cf-predictor/ocfloejijfhhkkdmheodbaanephbnfhn" starred>estimate rating changes!</Resource>
- [CF Visualizer](http://cfviz.netlify.com/compare.html) <Resource title="Stopstalk" url="https://www.stopstalk.com">keep track of friends' progress</Resource>
- [CF Rating Predictor](https://chrome.google.com/webstore/detail/cf-predictor/ocfloejijfhhkkdmheodbaanephbnfhn) <Resource title="Code Drills" url="https://recommender.codedrills.io/">problem recommender (haven't used personally) </Resource>
- [CF Command Line](https://codeforces.com/blog/entry/66552) <Resource title="CF Visualizer" url="http://cfviz.netlify.com/compare.html">compare users </Resource>
- [CF Editor](https://codeforces.com/blog/entry/72952) <Resource title="CF Command Line Tool" url="https://codeforces.com/blog/entry/66552">parse problem statements, submit, etc from command line</Resource>
<Resource title="CF Editor" url="https://codeforces.com/blog/entry/72952">text editor using features from above</Resource>
</Resources>
<!-- - [CF Enhancer](https://chrome.google.com/webstore/detail/codeforces-enhancer/ocmandagmgmkcplckgnfgaokpgkfenmp) <!-- - [CF Enhancer](https://chrome.google.com/webstore/detail/codeforces-enhancer/ocmandagmgmkcplckgnfgaokpgkfenmp)
- no longer works --> - no longer works -->
## Contest Tools ## Contest Tools
- [2D Geo Visualizer](https://codeforces.com/blog/entry/70330) <Resources>
- [CSAcademy Graph Editor (+ Geo Visualizer + Diff Tool)](https://csacademy.com/app/graph_editor/) <Resource title="Wolfram Alpha" url="https://www.wolframalpha.com/" starred> </Resource>
- [Desmos Grapher](https://www.desmos.com/calculator) <Resource title="CSAcademy Graph Editor, Geo Visualizer" url="https://csacademy.com/app/graph_editor/" starred> </Resource>
- [Wolfram Alpha](https://www.wolframalpha.com/) <Resource title="Desmos Grapher" url="https://www.desmos.com/calculator" starred> </Resource>
- [OEIS](https://oeis.org/) <Resource title="Diff Checker" url="https://www.diffchecker.com/"> </Resource>
<Resource title="2D Geo Visualizer (C++)" url="https://codeforces.com/blog/entry/70330"></Resource>
<Resource title="OEIS" url="https://oeis.org/">integer sequences</Resource>
</Resources>

View file

@ -2,7 +2,7 @@
id: debugging id: debugging
title: Debugging title: Debugging
author: Benjamin Qi, Aaron Chew 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 ## Within Your Program

View file

@ -3,6 +3,8 @@ id: factors-choosing
title: "Factors to Consider When Choosing a Language" title: "Factors to Consider When Choosing a Language"
author: Benjamin Qi author: Benjamin Qi
description: Reasons why choice of language matters significantly outside of USACO Bronze. description: Reasons why choice of language matters significantly outside of USACO Bronze.
prerequisites:
- choosing-lang
--- ---
## Notes ## Notes

View file

@ -1,29 +1,33 @@
--- ---
id: lambda id: lambda
title: Lambda Functions in C++ title: Lambda Expressions
author: Benjamin Qi author: Benjamin Qi
description: "?" description: "Unnamed function objects capable of capturing variables in scope."
--- ---
<LanguageSection>
<CPPSection>
## Introduction ## Introduction
<Resources> <Resources>
<Resource <Resource source="CPP" url="https://en.cppreference.com/w/cpp/language/lambda" title="Lambda expressions">reference</Resource>
source="GFG" <Resource source="UMich" url="http://umich.edu/~eecs381/handouts/Lambda.pdf" title="Using C++ Lambdas" starred> </Resource>
url="lambda-expression-in-c" <Resource source="SO" url="https://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11" title="What is a lambda expression in C++11?"> </Resource>
title="Lambda Expressions in C++" <Resource source="Microsoft" url="https://docs.microsoft.com/en-us/cpp/cpp/lambda-expressions-in-cpp?view=vs-2019" title="Lambda Expressions in C++"> </Resource>
>
{' '}
</Resource>
<Resource source="SO" url="https://stackoverflow.com/questions/41121441/type-of-a-lambda-function-using-auto" title="Type of a lambda function, using auto">
</Resource>
<Resource source="CPP" url="https://en.cppreference.com/w/cpp/language/lambda" title="Lambda">reference</Resource>
</Resources> </Resources>
(describe more) Anything more beginner-friendly?
oops sort of confusing <IncompleteSection />
<Resources title="FAQ">
<Resource source="SO" url="https://stackoverflow.com/questions/41121441/type-of-a-lambda-function-using-auto" title="Type of a lambda function using auto?">
</Resource>
<Resource source="SO" url="https://stackoverflow.com/questions/11323811/what-is-meant-by-retain-state-in-c" title="What is meant by 'retain state' in c++?"> </Resource>
</Resources>
## Recursive Lambdas ## Recursive Lambdas
@ -32,41 +36,49 @@ oops sort of confusing
<Resource source="RIP Tutorial" url="https://riptutorial.com/cplusplus/example/8508/recursive-lambdas" title="Recursive Lambdas"> </Resource> <Resource source="RIP Tutorial" url="https://riptutorial.com/cplusplus/example/8508/recursive-lambdas" title="Recursive Lambdas"> </Resource>
</Resources> </Resources>
We can do stuff like the following in C++14: If we add the following from the link above in C++14:
```cpp ```cpp
namespace std { namespace std {
template<class Fun> template<class Fun>
class y_combinator_result { class y_combinator_result {
Fun fun_; Fun fun_;
public: public:
template<class T> template<class T>
explicit y_combinator_result(T &&fun): fun_(std::forward<T>(fun)) {} explicit y_combinator_result(T &&fun): fun_(std::forward<T>(fun)) {}
template<class ...Args> template<class ...Args>
decltype(auto) operator()(Args &&...args) { decltype(auto) operator()(Args &&...args) {
return fun_(std::ref(*this), std::forward<Args>(args)...); return fun_(std::ref(*this), std::forward<Args>(args)...);
} }
}; };
template<class Fun> template<class Fun>
decltype(auto) y_combinator(Fun &&fun) { decltype(auto) y_combinator(Fun &&fun) {
return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun)); return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun));
} }
} // namespace std } // namespace std
```
Then we can have code like the following!
```cpp
int main() { int main() {
cout << y_combinator([](auto gcd, int a, int b) -> int { cout << y_combinator([](auto gcd, int a, int b) -> int {
return b == 0 ? a : gcd(b, a % b); return b == 0 ? a : gcd(b, a % b);
})(20,30) << "\n"; // outputs 10 })(20,30) << "\n"; // outputs 10
} }
``` ```
Looks like [ecnerwal](https://codeforces.com/contest/1375/submission/86008510) uses these a lot ... Looks like [ecnerwal](https://codeforces.com/contest/1375/submission/86008510) uses these a lot ...
</CPPSection>
</LanguageSection>
<!-- <!--
import InputOutput from "../../additionalcontent/Input_Output.mdx"; import InputOutput from "../../additionalcontent/Input_Output.mdx";
import DebuggingCpp from "../../additionalContent/Debugging_Cpp.mdx"; import DebuggingCpp from "../../additionalContent/Debugging_Cpp.mdx";

View file

@ -98,7 +98,7 @@ A warning block like this will contain common errors that you should avoid.
<IncompleteSection> <IncompleteSection>
These will appear frequently within incomplete modules. Contact us if you want these to be completed (or would like to complete them yourself)! These will appear frequently.
</IncompleteSection> </IncompleteSection>

View file

@ -282,11 +282,11 @@ java
If you get the below result, you may have to add the JDK to your [PATH](https://docs.oracle.com/en/java/javase/14/install/installation-jdk-microsoft-windows-platforms.html#GUID-A7E27B90-A28D-4237-9383-A58B416071CA) variable. If you get the below result, you may have to add the JDK to your [PATH](https://docs.oracle.com/en/java/javase/14/install/installation-jdk-microsoft-windows-platforms.html#GUID-A7E27B90-A28D-4237-9383-A58B416071CA) variable.
``` ```
'java' is not recognized as an internal or external comman, 'java' is not recognized as an internal or external command,
operable program or batch file operable program or batch file
``` ```
If you get a list of command arguments for the `java` command, you're probably good to go. Otherwise, you're probably good to go.
<IncompleteSection> <IncompleteSection>

View file

@ -2,7 +2,7 @@
id: cpp-tips id: cpp-tips
title: C++ Tips & Tricks title: C++ Tips & Tricks
author: Benjamin Qi author: Benjamin Qi
description: "?" description: "Things you should know about my template."
--- ---
## `#include <bits/stdc++.h>` ## `#include <bits/stdc++.h>`

View file

@ -1,8 +1,8 @@
--- ---
id: usaco-camp id: usaco-camp
title: Making USACO Camp title: USACO Camp
author: Benjamin Qi author: Benjamin Qi
description: "" description: "Relevant Quora links (and more) regarding camp qualification."
--- ---
<Resources> <Resources>

View file

@ -2,7 +2,7 @@
id: complete-search id: complete-search
title: "Complete Search" title: "Complete Search"
author: Darren Yao 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 frequency: 4
--- ---

View file

@ -2,7 +2,7 @@
id: gen-perm id: gen-perm
title: "Generating Permutations" title: "Generating Permutations"
author: Darren Yao, Sam Zhang 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 frequency: 4
prerequisites: prerequisites:
- complete-search - complete-search

View file

@ -2,7 +2,7 @@
id: intro-ds id: intro-ds
title: Introduction to Data Structures title: Introduction to Data Structures
author: Darren Yao, Benjamin Qi 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 frequency: 4
--- ---
@ -10,15 +10,19 @@ import { Problem } from "../models";
export const problems = { export const problems = {
bubble: [ 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: [ easy: [
new Problem("CF", "Kayaking", "contest/863/problem/B", "Easy", false, [], ""),
new Problem("CSES", "Distinct Numbers", "1621", "Easy"), new Problem("CSES", "Distinct Numbers", "1621", "Easy"),
new Problem("CSES", "Stick Lengths", "1074", "Normal", false, [], "Spoiler: Optimal length is median"), new Problem("CSES", "Stick Lengths", "1074", "Normal", false, [], "Spoiler: Optimal length is median"),
new Problem("Silver", "Teleportation", "812", "Very Hard", false, [], ""),
], ],
}; };
<!--
new Problem("Silver", "Teleportation", "812", "Very Hard", false, [], ""),
-->
<Resources> <Resources>
<Resource source="IUSACO" title="4.1 - Dynamic Arrays">module is based off this</Resource> <Resource source="IUSACO" title="4.1 - Dynamic Arrays">module is based off this</Resource>
<Resource source="CPH" title="4.1 - Dynamic Arrays" starred>vectors, strings</Resource> <Resource source="CPH" title="4.1 - Dynamic Arrays" starred>vectors, strings</Resource>
@ -279,18 +283,27 @@ for(auto element : v) {
<Problems problems={problems.bubble} /> <Problems problems={problems.bubble} />
**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.
<Resources>
<Resource source="CPH" title="3.1 - Sorting Theory"> </Resource>
</Resources>
<!-- No bronze problem should require you to sort an array in $O(N\log N)$ time for Bronze, -->
You should know how to use built-in methods to sort a (possibly dynamic) array.
<LanguageSection> <LanguageSection>
<CPPSection> <CPPSection>
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. <Resources>
<Resource source="CPH" title="3.2 - Sorting in C++" starred>can stop before comparison operators, which are covered in silver</Resource>
<Resource source="CPP" title="std::sort" url="https://en.cppreference.com/w/cpp/algorithm/sort">reference</Resource>
<Resource source="CF" title="C++ Tricks" url="blog/entry/74684">first two related to sorting</Resource>
</Resources>
- [std::sort](https://en.cppreference.com/w/cpp/algorithm/sort) 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.
- [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
</CPPSection> </CPPSection>

View file

@ -2,7 +2,7 @@
id: intro-greedy id: intro-greedy
title: Introduction to Greedy Algorithms title: Introduction to Greedy Algorithms
author: Michael Cao, Darren Yao 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 frequency: 2
--- ---

View file

@ -2,7 +2,7 @@
id: pairs-tuples id: pairs-tuples
title: Pairs & Tuples title: Pairs & Tuples
author: Benjamin Qi, Nathan Wang, Darren Yao, Abutalib Namazov 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: prerequisites:
- intro-ds - intro-ds
--- ---
@ -55,18 +55,17 @@ If you sort one of $x_i$ and $y_i$ without considering the other, the points wil
Example: Example:
```cpp ```cpp
#include <iostream> #include <bits/stdc++.h>
using namespace std; using namespace std;
int main() { int main() {
pair<string, int> myPair1 = make_pair("Testing", 123); pair<string, int> myPair1 = make_pair("Testing", 123);
cout << myPair1.first << " " << myPair1.second << endl; // Testing 123 cout << myPair1.first << " " << myPair1.second << endl; // Testing 123
myPair1.first = "It is possible to edit pairs after declaring them"; myPair1.first = "It is possible to edit pairs after declaring them";
cout << myPair1.first << " " << myPair1.second << endl; cout << myPair1.first << " " << myPair1.second << endl;
pair<string, string> myPair2 = {"Testing", "curly braces"}; pair<string, string> myPair2 = {"Testing", "curly braces"};
cout << myPair2.first << " " << myPair2.second << endl; // Testing curly braces cout << myPair2.first << " " << myPair2.second << endl; // Testing curly braces
} }
/* Output /* Output
@ -99,23 +98,20 @@ This is not frequently used by competitive programmers, but it is good to know a
Example: Example:
```cpp ```cpp
#include <iostream> #include <bits/stdc++.h>
#include <tuple> /// needs additional library
#include <string>
using namespace std; using namespace std;
int main() { int main() {
int a = 3, b = 4, c = 5; int a = 3, b = 4, c = 5;
tuple<int, int, int> t = tie(a, b, c); tuple<int, int, int> t = tie(a, b, c);
cout << get<0>(t) << " " << get<1>(t) << " " << get<2>(t) << endl; cout << get<0>(t) << " " << get<1>(t) << " " << get<2>(t) << endl;
get<0>(t) = 7; get<0>(t) = 7;
cout << get<0>(t) << " " << get<1>(t) << " " << get<2>(t) << endl; cout << get<0>(t) << " " << get<1>(t) << " " << get<2>(t) << endl;
tuple<string, string, int> tp2 = make_tuple("Hello", "world", 100); tuple<string, string, int> tp2 = make_tuple("Hello", "world", 100);
string s1, s2; int x; string s1, s2; int x;
tie(s1, s2, x) = tp2; tie(s1, s2, x) = tp2;
cout << s1 << " " << s2 << " " << x << endl; cout << s1 << " " << s2 << " " << x << endl;
} }
/* Output /* Output
* 3 4 5 * 3 4 5
@ -139,12 +135,12 @@ Example from CPH:
using namespace std; using namespace std;
int main() { int main() {
vector<pair<int,int>> v; vector<pair<int,int>> v;
v.push_back({1,5}); v.push_back({1,5});
v.push_back({2,3}); v.push_back({2,3});
v.push_back({1,2}); v.push_back({1,2});
sort(v.begin(), v.end()); sort(v.begin(), v.end());
for (pair<int,int> p: v) cout << p.first << " " << p.second << "\n"; for (pair<int,int> p: v) cout << p.first << " " << p.second << "\n";
} }
/* Output: /* Output:

View file

@ -8,7 +8,7 @@ description: "Evaluating a program's time complexity, or how fast your program r
<Resources> <Resources>
<Resource source="IUSACO" title="3 - Algorithm Analysis">module is based off this</Resource> <Resource source="IUSACO" title="3 - Algorithm Analysis">module is based off this</Resource>
<Resource source="CPH" title="2 - Time Complexity" starred>Intro and examples</Resource> <Resource source="CPH" title="2 - Time Complexity" starred>Intro and examples</Resource>
<Resource source="PAPS" title="5 - Time Complexity" starred>More in-depth. In particular, 5.2 gives a formal definition of Big O.</Resource> <Resource source="PAPS" title="5 - Time Complexity">More in-depth. In particular, 5.2 gives a formal definition of Big O.</Resource>
</Resources> </Resources>
<br /> <br />
@ -326,11 +326,21 @@ for i in range(m):
## Constant Factor ## 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$.
<IncompleteSection /> <IncompleteSection>
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
</IncompleteSection>
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)$.)
<IncompleteSection>
fix math
</IncompleteSection>
For now, don't worry about how to optimize constant factors -- just be aware of them. For now, don't worry about how to optimize constant factors -- just be aware of them.

View file

@ -2,7 +2,7 @@
id: unordered id: unordered
title: Unordered Maps & Sets title: Unordered Maps & Sets
author: Darren Yao, Benjamin Qi 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 frequency: 2
prerequisites: prerequisites:
- pairs-tuples - pairs-tuples

40
content/3_Silver/2P.mdx Normal file
View file

@ -0,0 +1,40 @@
---
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("CF", "Books", "problemset/problem/279/B", "Easy", false, ["2P"]),
new Problem("CF", "Cellular Network", "problemset/problem/702/C", "Easy", false, []),
new Problem("CF", "USB vs. PS/2", "problemset/problem/762/B", "Easy", false, []),
new Problem("Silver", "Sleepy Cow Herding", "918", "Normal", false, ["2P", "Sorting"], ""),
new Problem("CF", "Garland", "problemset/problem/814/C", "Normal", false, []),
new Problem("CF", "Jury Meeting", "problemset/problem/853/B", "Normal", false, []),
],
};
<Problems problems={problems.sample} />
## Resources
<Resources>
<Resource source="CPH" title="8.1 - Two Pointers" starred>solutions to the problems above</Resource>
<Resource source="IUSACO" title="14.1 - Two Pointers"></Resource>
</Resources>
## Problems
<Problems problems={problems.ad} />

View file

@ -20,7 +20,6 @@ export const problems = {
new Problem("Silver", "Convention", "858", "Easy", false, [], "determine whether $M$ buses suffice if every cow waits at most $T$ minutes, use a greedy strategy (applies to next two problems as well)"), new Problem("Silver", "Convention", "858", "Easy", false, [], "determine whether $M$ buses suffice if every cow waits at most $T$ minutes, use a greedy strategy (applies to next two problems as well)"),
new Problem("Silver", "Angry Cows", "594", "Easy", false, [], "check in $O(N)$ how many haybales you can destroy with fixed radius $R$"), new Problem("Silver", "Angry Cows", "594", "Easy", false, [], "check in $O(N)$ how many haybales you can destroy with fixed radius $R$"),
new Problem("Silver", "Social Distancing", "1038", "Normal", false, [], "check in $O(N+M)$ how many cows you can place with distance $D$"), new Problem("Silver", "Social Distancing", "1038", "Normal", false, [], "check in $O(N+M)$ how many cows you can place with distance $D$"),
new Problem("Gold", "High Card Low Card", "573", "Normal", false, [], ""),
new Problem("Silver", "Loan Repayment", "991", "Hard", false, [], "requires some rather tricky analysis to speed up naive $O(N\log N)$ solution"), new Problem("Silver", "Loan Repayment", "991", "Hard", false, [], "requires some rather tricky analysis to speed up naive $O(N\log N)$ solution"),
new Problem("Gold", "Angry Cows", "597", "Hard", false, [], ""), new Problem("Gold", "Angry Cows", "597", "Hard", false, [], ""),
], ],

View file

@ -6,7 +6,7 @@ prerequisites:
- sorting-custom - sorting-custom
- intro-ordered - intro-ordered
- lambda - lambda
description: "More ways to write custom comparators in C++ and incorporating them into STL objects." description: "Incorporating custom comparators into STL objects."
frequency: 1 frequency: 1
--- ---
@ -17,7 +17,7 @@ frequency: 1
<br /> <br />
What if we want to use a C++ `set` with the `Edge` struct that was defined in "Sorting with Custom Comparators"? What if we want to use a C++ `set` with the `Edge` struct that was defined in [Sorting with Custom Comparators](./sorting-custom)?
## Operator Overloading ## Operator Overloading

View file

@ -4,7 +4,7 @@ title: Depth First Search (DFS)
author: Siyong Huang author: Siyong Huang
prerequisites: prerequisites:
- intro-graphs - intro-graphs
description: "A way to recursively traverse through a graph." description: "A way to recursively traverse a graph."
frequency: 4 frequency: 4
--- ---

View file

@ -26,10 +26,12 @@ export const problems = {
new Problem("Silver", "Why Did the Cow Cross the Road III", "716", "Normal", false, []), new Problem("Silver", "Why Did the Cow Cross the Road III", "716", "Normal", false, []),
new Problem("Silver", "Multiplayer Moo", "836", "Hard", false, []), new Problem("Silver", "Multiplayer Moo", "836", "Hard", false, []),
new Problem("Silver", "Snow Boots", "811", "Hard", false, []), new Problem("Silver", "Snow Boots", "811", "Hard", false, []),
new Problem("Silver", "Mooyo Mooyo", "860", "Hard", false, []), new Problem("Silver", "Mooyo Mooyo", "860", "Normal", false, [], ""),
], ],
}; };
<!-- Mooyo Mooyo: 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. -->
<Problems problems={problems.sample} /> <Problems problems={problems.sample} />
<br /> <br />

View file

@ -4,7 +4,7 @@ title: Functional Graphs
author: Siyong Huang author: Siyong Huang
prerequisites: prerequisites:
- dfs - 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 frequency: 1
--- ---
@ -16,14 +16,14 @@ export const problems = {
new Problem("CF", "Div 2 B - Badge", "contest/1020/problem/B", "Very Easy", false, ["Func Graph"], "Try to solve the problem in $O(N)$!"), new Problem("CF", "Div 2 B - Badge", "contest/1020/problem/B", "Very Easy", false, ["Func Graph"], "Try to solve the problem in $O(N)$!"),
], ],
general: [ general: [
new Problem("Silver", "The Bovine Shuffle", "764", "Normal", false, ["Func Graph"], "Try to solve the problem in $O(N)$!"), new Problem("Silver", "The Bovine Shuffle", "764", "Easy", false, ["Func Graph"], "Try to solve the problem in $O(N)$!"),
new Problem("CSES", "Planets Cycles", "1751", "Normal", false, ["Func Graph"], ""), new Problem("CSES", "Planets Cycles", "1751", "Normal", false, ["Func Graph"], ""),
new Problem("Silver", "Swapity Swapity Swap", "1014", "Normal", false, ["Permutation"], ""), new Problem("Silver", "Swapity Swapity Swap", "1014", "Normal", false, ["Permutation"], ""),
new Problem("Codeforces", "Cooperative Game", "https://codeforces.com/contest/1137/problem/D", "Normal", false, ["Func Graph, Floyd's Algorithm"], "Implement Floyd's Algorithm! (You only actually need 3 friends to solve the problem!)"), new Problem("CF", "Cooperative Game", "https://codeforces.com/contest/1137/problem/D", "Normal", false, ["Func Graph, Floyd's Algorithm"], "Implement Floyd's Algorithm! (You only actually need 3 friends to solve the problem!)"),
new Problem("POI", "Mafia", "https://szkopul.edu.pl/problemset/problem/w3YAoAT3ej27YeiaNWjK57_G/site/?key=statement", "Hard", false, ["Func Graph"], ""), new Problem("POI", "Mafia", "https://szkopul.edu.pl/problemset/problem/w3YAoAT3ej27YeiaNWjK57_G/site/?key=statement", "Hard", false, ["Func Graph"], ""),
new Problem("POI", "Spies", "https://szkopul.edu.pl/problemset/problem/r6tMTfvQFPAEfQioYMCQndQe/site/?key=statement", "Hard", false, [], ""), new Problem("POI", "Spies", "https://szkopul.edu.pl/problemset/problem/r6tMTfvQFPAEfQioYMCQndQe/site/?key=statement", "Hard", false, [], ""),
new Problem("POI", "Frog", "https://szkopul.edu.pl/problemset/problem/qDH9CkBHZKHY4vbKRBlXPrA7/site/?key=statement", "Hard", false, [], ""), 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."), new Problem("ojuz", "Space Pirate", "JOI14_space_pirate", "Insane", 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."),
], ],
}; };
@ -41,7 +41,7 @@ This is also commonly referred to as a **successor graph**.
### Resources ### Resources
<Resources> <Resources>
<Resource source="CPH" title="16.3, 16.4 - Successor Graphs"></Resource> <Resource source="CPH" title="16.3 Successor Graphs"></Resource>
</Resources> </Resources>
### Implementation ### Implementation
@ -82,13 +82,12 @@ int main()
</LanguageSection> </LanguageSection>
## Tortoise and Hare (Floyd's Algorithm) ## Floyd's Algorithm
**Floyd's Algorithm**, also commonly referred to as the **Tortoise and Hare Algorithm**, is capable of detecting cycles in a functional graph in $O(N)$ time and $O(1)$ memory (not counting the graph itself) **Floyd's Algorithm**, also commonly referred to as the **Tortoise and Hare Algorithm**, is capable of detecting cycles in a functional graph in $O(N)$ time and $O(1)$ memory (not counting the graph itself)
### Resources
<Resources> <Resources>
<Resource source="CPH" title="16.4 - Cycle Detection" starred></Resource>
<Resource source="Medium" title="The Tortoise and the Hare (Floyd's Algorithm)" url="https://medium.com/@tuvo1106/the-tortoise-and-the-hare-floyds-algorithm-87badf5f7d41"></Resource> <Resource source="Medium" title="The Tortoise and the Hare (Floyd's Algorithm)" url="https://medium.com/@tuvo1106/the-tortoise-and-the-hare-floyds-algorithm-87badf5f7d41"></Resource>
</Resources> </Resources>

View file

@ -25,24 +25,23 @@ export const problems = {
new Problem("CSES", "Movie Festival II", "1632", "Easy", false, [], ""), new Problem("CSES", "Movie Festival II", "1632", "Easy", false, [], ""),
new Problem("CSES", "Stick Division", "1161", "Hard", false, [], ""), new Problem("CSES", "Stick Division", "1161", "Hard", false, [], ""),
], ],
usaco: [
new Problem("Silver", "Paired Up", "738", "Easy", false, ["2P", "Sorting"]),
new Problem("Silver", "Lemonade Line", "835", "?", false, [], ""),
new Problem("Silver", "Why ... (helpcross)", "714", "?", false, [], "first step: sort!"),
new Problem("Silver", "Berry Picking", "990", "?", false, [], ""),
new Problem("Silver", "Rest Stops", "810", "?", false, [], ""),
new Problem("Silver", "High Card Wins", "571", "?", false, [], ""),
],
other: [ other: [
new Problem("CSA", "Sure Bet", "sure-bet", "?", false, [], ""), new Problem("Silver", "Paired Up", "738", "Easy", false, ["2P", "Sorting"]),
new Problem("CF", "Did you Mean...", "contest/860/problem/A", "?", false, [], ""), new Problem("Silver", "Lemonade Line", "835", "Easy", false, ["Sorting"], ""),
new Problem("CF", "Bus", "contest/864/problem/C", "?", false, [], ""), new Problem("Silver", "High Card Wins", "571", "Normal", false, [], ""),
new Problem("CF", "Permutation", "contest/864/problem/D", "?", false, [], ""), new Problem("Gold", "High Card Low Card", "573", "Normal", false, [], ""),
new Problem("CF", "Kayaking", "contest/863/problem/B", "?", false, [], "Huffman Coding?"), new Problem("Silver", "Berry Picking", "990", "Normal", false, [], ""),
new Problem("CF", "New Year and Three Musketeers", "contest/611/problem/E", "Hard", false, [], "needs maps"), new Problem("Silver", "Why ... (helpcross)", "714", "Normal", false, ["Sorting"], ""),
] new Problem("CSA", "Sure Bet", "sure-bet", "Normal", false, [], ""),
],
}; };
<!-- new Problem("Silver", "Rest Stops", "810", "?", false, [], ""), -->
<!-- new Problem("CF", "Did you Mean...", "contest/860/problem/A", "?", false, [], ""), -->
<!-- new Problem("CF", "Bus", "contest/864/problem/C", "?", false, [], ""), -->
<!-- new Problem("CF", "Permutation", "contest/864/problem/D", "?", false, [], ""), -->
<!-- new Problem("CF", "New Year and Three Musketeers", "contest/611/problem/E", "Hard", false, [], "needs maps"), -->
<Resources> <Resources>
<Resource source="IUSACO" title="9 - Greedy Algorithms">Module is based off this.</Resource> <Resource source="IUSACO" title="9 - Greedy Algorithms">Module is based off this.</Resource>
<Resource source="CPH" title="6 - Greedy Algorithms" starred></Resource> <Resource source="CPH" title="6 - Greedy Algorithms" starred></Resource>
@ -177,10 +176,6 @@ pw.close();
<Problems problems={problems.cses} /> <Problems problems={problems.cses} />
## USACO Problems
<Problems problems={problems.usaco} />
## Other Problems ## Other Problems
<Problems problems={problems.other} /> <Problems problems={problems.other} />

View file

@ -1,129 +0,0 @@
---
id: harder-ordered
title: "Harder Problems with Ordered Sets"
author: Benjamin Qi
prerequisites:
- custom-cpp-stl
description: "More advanced uses of ordered sets with example problems."
frequency: 2
---
import { Problem } from "../models";
export const 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)"),
]
};
## Example: Using Iterators
<Problems problems={problems.sample} />
<Spoiler title="Solution">
```cpp
#include <bits/stdc++.h>
using namespace std;
#define sz(x) (x).size()
string s;
int m;
multiset<int> 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() << " ";
}
}
```
<br />
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 <bits/stdc++.h>
using namespace std;
#define sz(x) (x).size()
string s;
int m;
set<int> ans;
priority_queue<int> 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() << " ";
}
}
```
</Spoiler>
<IncompleteSection />
## Problems
<Problems problems={problems.general} />

View file

@ -0,0 +1,15 @@
---
id: harder-ordered
title: "Harder Problems with Ordered Sets"
author: Benjamin Qi
prerequisites:
- custom-cpp-stl
description: "More advanced uses of ordered sets with example problems."
frequency: 2
---
import { Problem } from "../models";
export const problems = {
};

View file

@ -4,7 +4,7 @@ title: "Introduction to Ordered Sets"
author: Darren Yao, Benjamin Qi author: Darren Yao, Benjamin Qi
prerequisites: prerequisites:
- unordered - unordered
description: "A data structure that supports quick insertion and deletion by maintaining keys in sorted order." description: "Data structures that maintain keys in sorted order."
frequency: 2 frequency: 2
--- ---
@ -15,8 +15,25 @@ export const problems = {
new Problem("CSES", "Concert Tickets", "1091", "Easy", false, ["iterators"], "just do upper_bound"), 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"), 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)"),
]
}; };
<Warning>
This is **not** built into Python. The Python [OrderedDict](https://docs.python.org/3/library/collections.html#collections.OrderedDict) stores keys in the same order as they were inserted in, **not** in sorted order.
</Warning>
<Resources> <Resources>
<Resource source="IUSACO" title="4.3 - Sets & Maps">module is based off this</Resource> <Resource source="IUSACO" title="4.3 - Sets & Maps">module is based off this</Resource>
<Resource source="CPH" title="4.2 to 4.4 - Data Structures" starred>sets, maps, set iterators</Resource> <Resource source="CPH" title="4.2 to 4.4 - Data Structures" starred>sets, maps, set iterators</Resource>
@ -26,15 +43,16 @@ export const problems = {
In **ordered** sets and maps, the entries are sorted in order of key. Insertions, deletions, and searches are all $O(\log N)$, where $N$ is the number of elements in the set or map. Accessing or removing the next key higher or lower than some input $k$ is also supported. In **ordered** sets and maps, the entries are sorted in order of key. Insertions, deletions, and searches are all $O(\log N)$, where $N$ is the number of elements in the set or map. Accessing or removing the next key higher or lower than some input $k$ is also supported.
(**not** the same as [OrderedDict](https://docs.python.org/3/library/collections.html#collections.OrderedDict) in Python ...)
## Ordered Sets ## Ordered Sets
<LanguageSection> <LanguageSection>
<CPPSection> <CPPSection>
As well as those supported by `unordered_set`, the ordered set also allows four additional operations: `begin()`, which returns an iterator to the lowest element in the set, `end()`, which returns an iterator to the highest element in the set, `lower_bound`, which returns an iterator to the least element greater than or equal to some element `k`, and `upper_bound`, which returns an iterator to the least element strictly greater than some element `k`. In addition to the `unordered_set` operations mentioned in the prerequisite module, the ordered `set` also allows:
- `lower_bound`: returns an iterator to the least element greater than or equal to some element `k`
- `upper_bound`: returns an iterator to the least element strictly greater than some element `k`.
```cpp ```cpp
set<int> s; set<int> s;
@ -77,7 +95,7 @@ System.out.println(set.higher(23); // ERROR, no such element exists
</LanguageSection> </LanguageSection>
One limitation of the ordered set is that we can't efficiently access the $k^{th}$ largest element in the set, or find the number of elements in the set greater than some arbitrary $x$. These operations can be handled using a data structure called an **order statistic tree** (see Gold - Point Update Range Sum). One limitation of the ordered set is that we can't efficiently access the $k^{th}$ largest element in the set, or find the number of elements in the set greater than some arbitrary $x$. These operations can be handled using a data structure called an [order statistic tree](../gold/PURS#order-statistic-tree).
## Ordered Maps ## Ordered Maps
@ -85,7 +103,10 @@ One limitation of the ordered set is that we can't efficiently access the $k^{th
<CPPSection> <CPPSection>
The ordered map supports all of the operations that an `unordered_map` supports, and additionally supports `lower_bound` and `upper_bound`, returning the iterator pointing to the lowest entry not less than the specified key, and the iterator pointing to the lowest entry strictly greater than the specified key respectively. In addition to the `unordered_map` operations mentioned in the prerequisite module, the ordered `map` also allows:
- `lower_bound`: returns the iterator pointing to the lowest entry not less than the specified key
- `upper_bound`: returns the iterator pointing to the lowest entry strictly greater than the specified key respectively.
```cpp ```cpp
map<int, int> m; map<int, int> m;
@ -133,7 +154,10 @@ A **multiset** is a sorted set that allows multiple copies of the same element.
<CPPSection> <CPPSection>
In addition to all of the regular set operations, the multiset `count()` method returns the number of times an element is present in the multiset. However, this method takes time **linear** in the number of matches so you shouldn't use it in a contest. The `begin()`, `end()`, `lower_bound()`, and `upper_bound()` operations work the same way they do in the normal sorted set. **Warning:** If you want to remove a value *once*, make sure to use `multiset.erase(multiset.find(val))` rather than `multiset.erase(val)`. The latter will remove *all* instances of `val`. In addition to all of the regular set operations,
- the `count()` method returns the number of times an element is present in the multiset. However, this method takes time **linear** in the number of matches so you shouldn't use it in a contest.
- If you want to remove a value *once*, make sure to use `multiset.erase(multiset.find(val))` rather than `multiset.erase(val)`. The latter will remove *all* instances of `val`.
```cpp ```cpp
@ -187,11 +211,26 @@ static void remove(int x){
</LanguageSection> </LanguageSection>
## Using Iterators
<LanguageSection>
<CPPSection>
next(), prev(), ++, --
</CPPSection>
</LanguageSection>
<IncompleteSection />
## Priority Queues ## 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**. 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). Of course, all of these functions are supported by multisets, but priority queues are simpler and faster.
<LanguageSection> <LanguageSection>
@ -235,22 +274,118 @@ pq.add(6); // [7, 6, 5]
</LanguageSection> </LanguageSection>
## Using Iterators ## Introductory Problems
<Problems problems={problems.standard} />
## Harder Example: Bit Inversions
<Problems problems={problems.sample} />
### Solution
<Spoiler title="Solution">
<LanguageSection> <LanguageSection>
<CPPSection> <CPPSection>
next(), prev(), ++, -- ```cpp
#include <bits/stdc++.h>
using namespace std;
#define sz(x) (x).size()
string s;
int m;
multiset<int> 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() << " ";
}
}
```
<br />
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 <bits/stdc++.h>
using namespace std;
#define sz(x) (int)(x).size()
string s;
int m;
set<int> ans;
priority_queue<int> 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() << " ";
}
}
```
</CPPSection> </CPPSection>
</LanguageSection> </LanguageSection>
<IncompleteSection /> </Spoiler>
## Standard ## Harder Problems
<Problems problems={problems.standard} /> <Problems problems={problems.general} />

View file

@ -1,89 +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 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
<Problems problems={problems.sample} />
Two pointers refers to iterating two monotonic pointers across an array to search for a pair of indices satisfying some condition in linear time.
<Resources>
<Resource source="CPH" title="8.1 - Two Pointers"></Resource>
<Resource source="IUSACO" title="14.1 - Two Pointers"></Resource>
</Resources>
### Implementation
<IncompleteSection />
## Sliding Window
<Problems problems={problems.slide} />
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$.
<Resources>
<Resource source="Medium" title="Introduction to Sliding Window Algorithms" url="https://levelup.gitconnected.com/an-introduction-to-sliding-window-algorithms-5533c4fe1cc7"> </Resource>
<Resource source="GFG" title="Window Sliding Technique" url="window-sliding-technique"> </Resource>
</Resources>
### Implementation
<IncompleteSection />
### Problems
<Problems problems={problems.general} />
## Sliding Window Minimum in $O(N)$
<Resources>
<Resource source="cp-algo" title="Minimum stack / Minimum queue" url="data_structures/stack_queue_modification.html" starred>Mentions two ways to solve this (both are important)!</Resource>
</Resources>
In particular, the second method allows us to solve the following generalization in linear time as well:
<Problems problems={problems.qs} />

View file

@ -6,7 +6,7 @@ author: Darren Yao, Siyong Huang, Michael Cao, Benjamin Qi
prerequisites: prerequisites:
- pairs-tuples - pairs-tuples
- lambda - lambda
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." 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"; import { Problem } from "../models";
@ -20,7 +20,6 @@ export const problems = {
new Problem("Silver", "Lifeguards", "786", "Easy", false, [], "Similar to above."), new Problem("Silver", "Lifeguards", "786", "Easy", false, [], "Similar to above."),
new Problem("Silver", "Rental Service", "787", "Easy", false, [], ""), new Problem("Silver", "Rental Service", "787", "Easy", false, [], ""),
new Problem("Silver", "Mountains", "896", "Easy", false, [], ""), new Problem("Silver", "Mountains", "896", "Easy", false, [], ""),
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("Gold", "Splitting the Field", "645", "Normal", false, [], ""), new Problem("Gold", "Splitting the Field", "645", "Normal", false, [], ""),
new Problem("Silver", "Triangles", "1015", "Hard", false, [], ""), new Problem("Silver", "Triangles", "1015", "Hard", false, [], ""),
new Problem("Silver", "Meetings", "967", "Very Hard", false, [], ""), new Problem("Silver", "Meetings", "967", "Very Hard", false, [], ""),
@ -28,7 +27,8 @@ export const problems = {
}; };
<Resources> <Resources>
<Resource source="IUSACO" title="8 - Sorting & Comparators"></Resource> <Resource source="IUSACO" title="8 - Sorting & Comparators">partially based off this</Resource>
<Resource source="CPH" title="3.2 - User-Defined Structs, Comparison Functions">short overflow of what this module will cover</Resource>
</Resources> </Resources>
<br /> <br />
@ -55,7 +55,7 @@ After sorting, it should look like
2 3 10 2 3 10
``` ```
With C++, the easiest method is to use nested pairs or a `vector` of `array<int,3>` or `vector<int>`. With C++, the easiest method is to use a `vector` of nested `pair`s:
```cpp ```cpp
#include <bits/stdc++.h> #include <bits/stdc++.h>
@ -76,6 +76,8 @@ int main() {
} }
``` ```
or a `vector` of `array<int,3>`s or `vector<int>`s:
```cpp ```cpp
int main() { int main() {
int M = 4; int M = 4;
@ -91,10 +93,10 @@ int main() {
In Python, we can use a list of lists. In Python, we can use a list of lists.
But in Java, we can't immediately sort an arraylist of arraylists. What should we do? But in Java, we can't sort an `ArrayList` of `ArrayList`s without writing some additional code. What should we do?
- If we only stored the edge weights and sorted them, we would have a sorted list of edge weights, but it would be impossible to tell which weights corresponded to which edges. - If we only stored the edge weights and sorted them, we would have a sorted list of edge weights, but it would be impossible to tell which weights corresponded to which edges.
- However, if we create a **class** (or struct) representing the edges and define a **custom comparator** to sort them by weight, we can sort the edges in ascending order while also keeping track of their endpoints. - However, if we create a **class** representing the edges and define a **custom comparator** to sort them by weight, we can sort the edges in ascending order while also keeping track of their endpoints.
## Classes ## Classes
@ -105,6 +107,10 @@ First, we need to define a **class** that represents what we want to sort. In ou
<CPPSection> <CPPSection>
### C++
A C++ `struct` is the same as a class in C++, but all members are public by default.
```cpp ```cpp
#include <bits/stdc++.h> #include <bits/stdc++.h>
using namespace std; using namespace std;
@ -113,6 +119,13 @@ struct Edge {
int a,b,w; int a,b,w;
}; };
/* alternatively,
class Edge {
public:
int a,b,w;
};
*/
int main() { int main() {
int M = 4; int M = 4;
vector<Edge> v; vector<Edge> v;
@ -188,10 +201,6 @@ Normally, sorting functions rely on moving objects with a lower value in front o
<CPPSection> <CPPSection>
<Resources>
<Resource source="CPH" title="3.2 - User-Defined Structs, Comparison Functions" starred></Resource>
</Resources>
What a comparator does is compare two objects as follows, based on our comparison criteria: What a comparator does is compare two objects as follows, based on our comparison criteria:
- If object $x$ is less than object $y$, return `true` - If object $x$ is less than object $y$, return `true`
@ -201,7 +210,7 @@ Essentially, the comparator determines whether object $x$ belongs to the left of
In addition to returning the correct answer, comparators should also satisfy the following conditions: In addition to returning the correct answer, comparators should also satisfy the following conditions:
- The function must be consistent with respect to reversing the order of the arguments: if $x \neq y$ and `compare(x, y)`is `true`, then `compare(y, x)` should be `false` and vice versa. - The function must be consistent with respect to reversing the order of the arguments: if $x \neq y$ and `compare(x, y)` is `true`, then `compare(y, x)` should be `false` and vice versa.
- The function must be transitive. If `compare(x, y)` is true and `compare(y, z)` is true, then `compare(x, z)` should also be true. If the first two compare functions both return `false`, the third must also return `false`. - The function must be transitive. If `compare(x, y)` is true and `compare(y, z)` is true, then `compare(x, z)` should also be true. If the first two compare functions both return `false`, the third must also return `false`.
### Method 1: Overloading the Less Than Operator ### Method 1: Overloading the Less Than Operator
@ -209,7 +218,7 @@ In addition to returning the correct answer, comparators should also satisfy the
This is the easiest to implement. However, it only works for objects (not primitives) and it doesn't allow you to define multiple ways to compare the same type of class. This is the easiest to implement. However, it only works for objects (not primitives) and it doesn't allow you to define multiple ways to compare the same type of class.
In the context of Wormhole Sort (note the use of In the context of Wormhole Sort (note the use of
[const T&](https://stackoverflow.com/questions/11805322/why-should-i-use-const-t-instead-of-const-t-or-t)): [const Edge&](https://stackoverflow.com/questions/11805322/why-should-i-use-const-t-instead-of-const-t-or-t)):
```cpp ```cpp
#include <bits/stdc++.h> #include <bits/stdc++.h>
@ -278,7 +287,7 @@ int main() {
``` ```
We can also use lambda expressions in C++11 or above: We can also use [lambda expressions](../intro/lambda) in C++11 or above:
```cpp ```cpp
sort(begin(v),end(v),[](const Edge& x, const Edge& y) { return x.w < y.w; }); sort(begin(v),end(v),[](const Edge& x, const Edge& y) { return x.w < y.w; });

View file

@ -1,6 +1,6 @@
--- ---
id: intro-dp id: intro-dp
title: "Introduction to Dynamic Programming" title: "Introduction to Dynamic Programming (DP)"
author: Michael Cao author: Michael Cao
prerequisites: prerequisites:
- complete-search - complete-search
@ -51,11 +51,17 @@ export const problems = {
], ],
} }
Dynamic Programming is an important algorithmic technique in competitive programming that appears at all levels of competition. **Dynamic Programming** (DP) is an important algorithmic technique in competitive programming that appears at all levels of competition.
By breaking down the full task into sub-problems, Dynamic Programming avoids the redundant computations of brute force solutions. <IncompleteSection>
Although it is not too difficult to grasp the general ideas behind Dynamic Programming, or DP, the technique can be used in a diverse range of problems and is a must-know idea for competitors in the USACO gold division. What do you mean by "all levels"? Certainly doesn't appear in silver ...
</IncompleteSection>
By breaking down the full task into sub-problems, DP avoids the redundant computations of brute force solutions.
Although it is not too difficult to grasp the general ideas behind DP, the technique can be used in a diverse range of problems and is a must-know idea for competitors in the USACO gold division.
## Introductory Resources ## Introductory Resources

View file

@ -133,49 +133,51 @@ Don't just dive into trying to figure out a DP state and transitions -- make som
<Spoiler title="Ostap & Tree"> <Spoiler title="Ostap & Tree">
Solution described by editorial is terrible, but we can do better! This runs in $O(NK)$ time. (proof?)
```cpp ```cpp
vmi yes[101], no[101]; vmi yes[101], no[101];
int n,k; int n,k;
vi adj[MX]; vi adj[MX];
void dfs(int x, int y) { void dfs(int x, int y) {
yes[x] = no[x] = {1}; // black, not black yes[x] = no[x] = {1}; // black, not black
// dist of closest good vertex // dist of closest good vertex
// or dist of farthest bad vertex // or dist of farthest bad vertex
auto ad = [](vmi& a, int b, mi c) { auto ad = [](vmi& a, int b, mi c) {
while (sz(a) <= b) a.pb(0); while (sz(a) <= b) a.pb(0);
a[b] += c; a[b] += c;
}; };
trav(t,adj[x]) if (t != y) { trav(t,adj[x]) if (t != y) {
dfs(t,x); dfs(t,x);
yes[t].insert(begin(yes[t]),0); yes[t].insert(begin(yes[t]),0);
no[t].insert(begin(no[t]),0); no[t].insert(begin(no[t]),0);
if (sz(no[t]) > k+1) no[t].pop_back(); if (sz(no[t]) > k+1) no[t].pop_back();
vmi YES, NO; vmi YES, NO;
F0R(i,sz(yes[x])) F0R(j,sz(yes[t])) ad(YES,min(i,j),yes[x][i]*yes[t][j]); F0R(i,sz(yes[x])) F0R(j,sz(yes[t])) ad(YES,min(i,j),yes[x][i]*yes[t][j]);
F0R(i,sz(no[x])) F0R(j,sz(no[t])) ad(NO,max(i,j),no[x][i]*no[t][j]); F0R(i,sz(no[x])) F0R(j,sz(no[t])) ad(NO,max(i,j),no[x][i]*no[t][j]);
auto yesNo = [&](vmi good, vmi bad) { auto yesNo = [&](vmi good, vmi bad) {
F0R(i,sz(good)) F0R(j,sz(bad)) { F0R(i,sz(good)) F0R(j,sz(bad)) {
if (i+j <= k) ad(YES,i,good[i]*bad[j]); if (i+j <= k) ad(YES,i,good[i]*bad[j]);
else ad(NO,j,good[i]*bad[j]); else ad(NO,j,good[i]*bad[j]);
} }
}; };
yesNo(yes[x],no[t]); yesNo(yes[t],no[x]); yesNo(yes[x],no[t]); yesNo(yes[t],no[x]);
swap(yes[x],YES); swap(no[x],NO); swap(yes[x],YES); swap(no[x],NO);
} }
} }
int main() { int main() {
setIO(); re(n,k); setIO(); re(n,k);
F0R(i,n-1) { F0R(i,n-1) {
int a,b; re(a,b); int a,b; re(a,b);
adj[a].pb(b), adj[b].pb(a); adj[a].pb(b), adj[b].pb(a);
} }
dfs(1,0); dfs(1,0);
mi ans = 0; mi ans = 0;
trav(t,yes[1]) ans += t; trav(t,yes[1]) ans += t;
ps(ans); ps(ans);
// you should actually read the stuff at the bottom // you should actually read the stuff at the bottom
} }
``` ```

View file

@ -14,6 +14,9 @@ export const problems = {
three: [ three: [
new Problem("Gold", "3SUM", "994", "Normal", false, [], ""), new Problem("Gold", "3SUM", "994", "Normal", false, [], ""),
], ],
four: [
new Problem("CSES", "Sum of Four Values", "1642", "Normal", false, [], ""),
],
}; };
<Resources> <Resources>
@ -104,9 +107,9 @@ You're supposed to use array since values are small :|
using namespace std; using namespace std;
void setIO(string name) { void setIO(string name) {
ios_base::sync_with_stdio(0); cin.tie(0); ios_base::sync_with_stdio(0); cin.tie(0);
freopen((name+".in").c_str(),"r",stdin); freopen((name+".in").c_str(),"r",stdin);
freopen((name+".out").c_str(),"w",stdout); freopen((name+".out").c_str(),"w",stdout);
} }
@ -118,27 +121,31 @@ long long ans[5000][5000];
vector<int> A; vector<int> A;
int main() { int main() {
setIO("threesum"); setIO("threesum");
cin >> N >> Q; cin >> N >> Q;
A.resize(N); for (int i = 0; i < N; ++i) cin >> A[i]; A.resize(N); for (int i = 0; i < N; ++i) cin >> A[i];
for (int i = 0; i < N; ++i) { for (int i = 0; i < N; ++i) {
gp_hash_table<int,int> g({},{},{},{},{1<<13}); gp_hash_table<int,int> g({},{},{},{},{1<<13});
// initialize with certain capacity, must be power of 2 // initialize with certain capacity, must be power of 2
for (int j = i+1; j < N; ++j) { for (int j = i+1; j < N; ++j) {
int res = -A[i]-A[j]; int res = -A[i]-A[j];
auto it = g.find(res); auto it = g.find(res);
if (it != end(g)) ans[i][j] = it->second; if (it != end(g)) ans[i][j] = it->second;
g[A[j]] ++; g[A[j]] ++;
} }
} }
for (int i = N-1; i >= 0; --i) for (int j = i+1; j < N; ++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]; ans[i][j] += ans[i+1][j]+ans[i][j-1]-ans[i+1][j-1];
for (int i = 0; i < Q; ++i) { for (int i = 0; i < Q; ++i) {
int a,b; cin >> a >> b; int a,b; cin >> a >> b;
cout << ans[a-1][b-1] << "\n"; cout << ans[a-1][b-1] << "\n";
} }
// you should actually read the stuff at the bottom // you should actually read the stuff at the bottom
} }
``` ```
<IncompleteSection /> <IncompleteSection />
## Problems
<Problems problems={problems.four} />

View file

@ -31,10 +31,12 @@ export const problems = {
<Resource source="AoPS" title="Alcumus" url="https://artofproblemsolving.com/alcumus/problem" starred>practice problems, set focus to number theory!</Resource> <Resource source="AoPS" title="Alcumus" url="https://artofproblemsolving.com/alcumus/problem" starred>practice problems, set focus to number theory!</Resource>
<Resource source="AoPS" title ="Intro to NT" url="https://artofproblemsolving.com/store/item/intro-number-theory?gtmlist=Bookstore_AoPS_Side">good book :D</Resource> <Resource source="AoPS" title ="Intro to NT" url="https://artofproblemsolving.com/store/item/intro-number-theory?gtmlist=Bookstore_AoPS_Side">good book :D</Resource>
<Resource source="CPH" title="21.1, 21.2 - Number Theory">primes and factors, modular arithmetic</Resource> <Resource source="CPH" title="21.1, 21.2 - Number Theory">primes and factors, modular arithmetic</Resource>
<Resource source="PAPS" title="16 - Number Theory">same as below</Resource> <Resource source="PAPS" title="16.1, 16.2, 16.4 - Number Theory"></Resource>
<Resource source="CF" title="CodeNCode - Number Theory Course" url="blog/entry/77137">lots of advanced stuff you don't need to know at this level</Resource>
</Resources> </Resources>
<!-- <Resource source="CF" title="CodeNCode - Number Theory Course" url="blog/entry/77137">lots of advanced stuff you don't need to know at this level</Resource>
-->
## Prime Factorization ## Prime Factorization
<Problems problems={problems.sample} /> <Problems problems={problems.sample} />
@ -204,7 +206,13 @@ We'll only consider **prime** moduli here. Division can be performed using modul
#### With Exponentiation #### With Exponentiation
To find the modular inverse of some number, simply raise it to the power of $\mathrm{MOD} - 2$, where $\mathrm{MOD}$ is the modulus being used, using the function described above. (The reasons for raising the number to $\mathrm{MOD} - 2$ can be explained with **Fermat's Little Theorem**, but we will not explain the theorem here). To find the modular inverse of some number, simply raise it to the power of $\mathrm{MOD} - 2$, where $\mathrm{MOD}$ is the modulus being used, using the function described above. The reasons for raising the number to $\mathrm{MOD} - 2$ can be explained with **Fermat's Little Theorem**.
<IncompleteSection>
explain theorem?
</IncompleteSection>
The modular inverse is the equivalent of the reciprocal in real-number arithmetic; to divide $a$ by $b$, multiply $a$ by the modular inverse of $b$. The modular inverse is the equivalent of the reciprocal in real-number arithmetic; to divide $a$ by $b$, multiply $a$ by the modular inverse of $b$.
@ -212,8 +220,6 @@ Because it takes $\mathcal{O}(\log \mathrm{MOD})$ time to compute a modular inve
Also, one must always ensure that they do not attempt to divide by 0. Be aware that after applying modulo, a nonzero number can become zero, so be very careful when dividing by non-constant values. Also, one must always ensure that they do not attempt to divide by 0. Be aware that after applying modulo, a nonzero number can become zero, so be very careful when dividing by non-constant values.
<IncompleteSection />
#### With Extended Euclidean Algorithm #### With Extended Euclidean Algorithm
<Optional> <Optional>

View file

@ -3,8 +3,8 @@ id: mst
title: "Minimum Spanning Trees" title: "Minimum Spanning Trees"
author: Benjamin Qi author: Benjamin Qi
prerequisites: prerequisites:
- Gold - Shortest Paths with Non-Negative Edge Weights - sp
- Gold - Disjoint Set Union - dsu
description: "A subset of the edges of a connected, undirected, edge-weighted graph that connects all the vertices to each other of minimum total weight, where no cycles are allowed." description: "A subset of the edges of a connected, undirected, edge-weighted graph that connects all the vertices to each other of minimum total weight, where no cycles are allowed."
frequency: 2 frequency: 2
--- ---

View file

@ -4,7 +4,7 @@ title: "Point Update Range Sum"
author: Benjamin Qi author: Benjamin Qi
prerequisites: prerequisites:
- prefix-sums - prefix-sums
description: "Introducing Segment Trees, Binary Indexed Trees, and Indexed Sets (C++ only)." description: "Introduces Segment Tree, Binary Indexed Tree, and Order Statistic Tree (C++ only)."
frequency: 3 frequency: 3
--- ---
@ -147,7 +147,7 @@ Suppose that we want a data structure that supports all the operations as a `set
- `order_of_key(x)`: counts the number of elements in the set that are strictly less than `x`. - `order_of_key(x)`: counts the number of elements in the set that are strictly less than `x`.
- `find_by_order(k)`: similar to `find`, returns the iterator corresponding to the `k`-th lowest element in the set (0-indexed). - `find_by_order(k)`: similar to `find`, returns the iterator corresponding to the `k`-th lowest element in the set (0-indexed).
### Indexed Set ### Order Statistic Tree
Luckily, such a built-in data structure already exists in C++. Luckily, such a built-in data structure already exists in C++.

133
content/4_Gold/Queues.mdx Normal file
View file

@ -0,0 +1,133 @@
---
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, [], ""),
],
};
<Resources>
<Resource source="CPH" title="4.5 - Queues, Deques"></Resource>
<Resource source="PAPS" title="3.2, 6.3 - Queues"></Resource>
</Resources>
## Queues
A queue is a First In First Out (FIFO) data structure that supports three operations, all in $O(1)$ time.
<LanguageSection>
<CPPSection>
### [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<int> 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
```
</CPPSection>
<JavaSection>
### 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<Integer> q = new LinkedList<Integer>();
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
```
</JavaSection>
</LanguageSection>
## 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.
<LanguageSection>
<CPPSection>
### [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<int> 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]
```
(important: you can also access like array ...)
</CPPSection>
<JavaSection>
### Java
In Java, the deque class is called `ArrayDeque`. The four methods for adding and removing are `addFirst` , `removeFirst`, `addLast`, and `removeLast`.
```java
ArrayDeque<Integer> deque = new ArrayDeque<Integer>();
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]
```
</JavaSection>
</LanguageSection>
## Sliding Window Minimum in $O(N)$
<Problems problems={problems.sam} />
<Resources>
<Resource source="CPH" title="8.3 - Sliding Window Minimum"></Resource>
<Resource source="cp-algo" title="Minimum stack / Minimum queue" url="data_structures/stack_queue_modification.html" starred>Mentions two ways to solve this (both are important)!</Resource>
</Resources>
## Problems
<Problems problems={problems.ys} />

View file

@ -113,3 +113,5 @@ just to be safe.
<Problems problems={problems.apsp} /> <Problems problems={problems.apsp} />
(more?) (more?)
<IncompleteSection />

View file

@ -22,9 +22,11 @@ export const problems = {
], ],
}; };
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. Given a static array $A[1],A[2],\ldots,A[N]$, you want to answer queries in the form
$$
With $O(N\log N)$ time preprocessing, we can get $O(1)$ queries. A[l]\ominus A[l+1]\ominus \cdots \ominus A[r]
$$
where $\ominus$ denotes any associative operation. With $O(N\log N)$ time preprocessing, we can get $O(1)$ time queries!
## [Range Minimum Query](https://en.wikipedia.org/wiki/Range_minimum_query) ## [Range Minimum Query](https://en.wikipedia.org/wiki/Range_minimum_query)

View file

@ -0,0 +1,73 @@
---
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, [], ""),
],
sam: [
new Problem("CSES", "Playlist", "1141", "Easy", false, ["2P"], ""),
],
general: [
new Problem("CF", "K-Good Segment", "problemset/problem/616/D", "Easy", false, []),
new Problem("Gold", "Haybale Feast", "767", "Easy", false, ["Set", "Sliding Window"]),
new Problem("Plat", "Fort Moo", "600", "Hard", false, ["Sliding Window"]),
]
};
## Sliding Window
<Problems problems={problems.constantSam} />
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)$.
<!-- 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$.
-->
<Resources>
<Resource source="GFG" title="Window Sliding Technique" url="window-sliding-technique"> </Resource>
</Resources>
### Implementation
<IncompleteSection />
### Problems
<Problems problems={problems.constant} />
## 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.
<Problems problems={problems.sam} />
### Solution
<Resources>
<Resource source="Medium" title="Introduction to Sliding Window Algorithms" url="https://levelup.gitconnected.com/an-introduction-to-sliding-window-algorithms-5533c4fe1cc7"> </Resource>
</Resources>
### Problems
<Problems problems={problems.general} />

View file

@ -3,7 +3,7 @@ id: springboards
title: "Max Suffix Query with Insertions Only" title: "Max Suffix Query with Insertions Only"
author: Benjamin Qi author: Benjamin Qi
prerequisites: prerequisites:
- harder-ordered - intro-ordered
description: "A solution to USACO Gold - Springboards." description: "A solution to USACO Gold - Springboards."
frequency: 1 frequency: 1
--- ---

View file

@ -1,6 +1,6 @@
--- ---
id: stacks-queues id: stacks
title: Introduction to Stacks & Queues title: Stacks
author: Darren Yao author: Darren Yao
description: "Two data structures to efficently add and remove the first and last element." description: "Two data structures to efficently add and remove the first and last element."
prerequisites: prerequisites:
@ -16,18 +16,14 @@ export const problems = {
general: [ general: [
new Problem("LC", "Max Histogram Area", "largest-rectangle-in-histogram", "Normal", false, [],""), new Problem("LC", "Max Histogram Area", "largest-rectangle-in-histogram", "Normal", false, [],""),
new Problem("Old Gold", "Concurrently Balanced Strings", "194", "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", "Modern Art 2","743", "Hard", false, [], ""),
new Problem("Gold", "Dishwashing","922", "Hard", false, [], ""), new Problem("Gold", "Dishwashing","922", "Hard", false, [], ""),
], ],
}; };
## Additional Reading
<Resources> <Resources>
<Resource source="CPH" title="4.5 - Stacks, Queues, Priority Queues"></Resource> <Resource source="CPH" title="4.5 - Stacks"></Resource>
<Resource source="PAPS" title="3.2 to 3.4 - C++ STL"></Resource> <Resource source="PAPS" title="3.3, 6.2 - Stacks"></Resource>
<Resource source="PAPS" title="6.2, 6.3, 6.5 - Stacks, Queues, Priority Queues"></Resource>
<Resource source="CP1" title="2.2 - Data Structures with Built-in Libraries"> </Resource> <Resource source="CP1" title="2.2 - Data Structures with Built-in Libraries"> </Resource>
</Resources> </Resources>
@ -79,101 +75,8 @@ System.out.println(s.size()); // 2
</LanguageSection> </LanguageSection>
## Queues
A queue is a First In First Out (FIFO) data structure that supports three operations, all in $O(1)$ time. ## Application: Nearest Smaller Element
<LanguageSection>
<CPPSection>
### [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<int> 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
```
</CPPSection>
<JavaSection>
### 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<Integer> q = new LinkedList<Integer>();
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
```
</JavaSection>
</LanguageSection>
## 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.
<LanguageSection>
<CPPSection>
### [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<int> 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]
```
</CPPSection>
<JavaSection>
### Java
In Java, the deque class is called `ArrayDeque`. The four methods for adding and removing are `addFirst` , `removeFirst`, `addLast`, and `removeLast`.
```java
ArrayDeque<Integer> deque = new ArrayDeque<Integer>();
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]
```
</JavaSection>
</LanguageSection>
## Monotonic Stack
<Problems problems={problems.nearest} /> <Problems problems={problems.nearest} />
@ -181,24 +84,22 @@ 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$. > 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 `<value, index>` 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: <Resources>
<Resource source="CPH" title="8.2 - Nearest Smaller Element"></Resource>
<Resource source="Medium" title="Monotonic Stack" url="https://medium.com/@vishnuvardhan623/monotonic-stack-e9dcc4fa8c3e"></Resource>
</Resources>
To solve this, let's store a stack of pairs of `<value, index>` 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. - 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. - 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. 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) ### Implementation
<IncompleteSection /> <IncompleteSection />
### Further Reading
<Resources>
<Resource source="CPH" title="8.2 - Nearest Smaller Element"></Resource>
<Resource source="Medium" title="Monotonic Stack" url="https://medium.com/@vishnuvardhan623/monotonic-stack-e9dcc4fa8c3e"></Resource>
</Resources>
## Problems ## Problems
<Problems problems={problems.general} /> <Problems problems={problems.general} />

View file

@ -3,8 +3,8 @@ id: toposort
title: "Topological Sort" title: "Topological Sort"
author: Benjamin Qi, Michael Cao, Nathan Chen author: Benjamin Qi, Michael Cao, Nathan Chen
prerequisites: prerequisites:
- Gold - Breadth First Search - bfs
- Gold - Introduction to Dynamic Programming - intro-dp
description: "An ordering of vertices in a directed acyclic graph that ensures that a node is visited before a node it has a directed edge to." description: "An ordering of vertices in a directed acyclic graph that ensures that a node is visited before a node it has a directed edge to."
frequency: 1 frequency: 1
--- ---
@ -58,7 +58,7 @@ The BFS version, known as [Kahn's Algorithm](https://en.wikipedia.org/wiki/Topol
<LanguageSection> <LanguageSection>
<CppSection> <CPPSection>
```cpp ```cpp
int in_degree[100000]; int in_degree[100000];
@ -89,7 +89,7 @@ void compute() {
} }
``` ```
</CppSection> </CPPSection>
<JavaSection> <JavaSection>
@ -152,7 +152,7 @@ Note that the implementation of this idea below uses Kahn's algorithm for topolo
<LanguageSection> <LanguageSection>
<CppSection> <CPPSection>
```cpp ```cpp
#include <bits/stdc++.h> #include <bits/stdc++.h>
@ -254,7 +254,7 @@ int main() { //See "Intro - Fast I/O" for more information about the first two l
} }
``` ```
</CppSection> </CPPSection>
<JavaSection> <JavaSection>

View file

@ -9,11 +9,19 @@ description: "?"
frequency: 1 frequency: 1
--- ---
<!--
TODO:
- Add more resources
-->
import { Problem } from "../models"; import { Problem } from "../models";
export const problems = { export const problems = {
general: [ general: [
new Problem("CF", "Ciel the Commander", "problemset/problem/321/C", "Easy", false, ["Centroid"], ""), new Problem("CF", "Ciel the Commander", "problemset/problem/321/C", "Easy", false, ["Centroid"], ""),
new Problem("Plat", "New Barns", "817", "Normal", true, ["Centroid"], ""),
new Problem("CF", "Sherlock's bet to Moriarty", "contest/776/problem/F", "Normal", false, ["Centroid"], ""), new Problem("CF", "Sherlock's bet to Moriarty", "contest/776/problem/F", "Normal", false, ["Centroid"], ""),
new Problem("CF", "Digit Tree", "contest/715/problem/C", "Normal", false, ["Centroid", "NT"], ""), new Problem("CF", "Digit Tree", "contest/715/problem/C", "Normal", false, ["Centroid", "NT"], ""),
new Problem("CF", "Double Tree", "contest/1140/problem/G", "Normal", false, ["Centroid", "DP"], ""), new Problem("CF", "Double Tree", "contest/1140/problem/G", "Normal", false, ["Centroid", "DP"], ""),
@ -82,9 +90,43 @@ void centroid(int n = 1)
</CPPSection> </CPPSection>
<JavaSection /> <JavaSection>
<PySection /> <!-- Modified from above. I can't guarauntee it compiles and functions as expected -->
```java
boolean[] r = new boolean[MN];//removed
int[] s = new int[MN];//subtree size
public int dfs(int n, int p)
{
s[n] = 1;
for(int x : a[n])
if(x != p && !r[x])
s[n] += dfs(x, n);
return s[n];
}
public int get_centroid(int n, int ms, int p)//n = node, ms = size of tree, p = parent
{
for(int x : a[n])
if(x != p && !r[x])
if(s[x]*2 > ms)
return get_centroid(x, ms, n);
return n;
}
public void centroid(int n)
{
int C = get_centroid(n, dfs(n, 0), 0);
//do something
r[C] = 1;
for(int x : a[C])
if(!r[x])
centroid(x);
}
```
</JavaSection>
</LanguageSection> </LanguageSection>

View file

@ -22,6 +22,7 @@ export const problems = {
new Problem("CSES", "Elevator Rides", "1653", "Normal", false, ["Bitmasks"], ""), new Problem("CSES", "Elevator Rides", "1653", "Normal", false, ["Bitmasks"], ""),
new Problem("ojuz", "IZhO Bank", "IZhO14_bank", "Normal", false, ["Bitmasks"], ""), new Problem("ojuz", "IZhO Bank", "IZhO14_bank", "Normal", false, ["Bitmasks"], ""),
new Problem("YS", "Max Indep Set", "maximum_independent_set", "Normal", false, ["Bitmasks", "Meet in Middle"], ""), new Problem("YS", "Max Indep Set", "maximum_independent_set", "Normal", false, ["Bitmasks", "Meet in Middle"], ""),
new Problem("CF", "Wise Men", "contest/1326/problem/F2", "Very Hard", false, ["Bitmasks", "DP", "SOS"], "Solve the case where for each binary string s, a 1 means that the adjacent men know each other, and the 0 means nothing: they can know each other or not."),
], ],
broken: [ broken: [
new Problem("CF", "Guards in the Storehouse", "problemset/problem/845/F", "Normal", false, [], ""), new Problem("CF", "Guards in the Storehouse", "problemset/problem/845/F", "Normal", false, [], ""),
@ -42,6 +43,7 @@ You can often use this to solve subtasks.
<Resource source="CPH" title="10 (Bit Manipulation), 19.2 (Hamiltonian Paths)"> </Resource> <Resource source="CPH" title="10 (Bit Manipulation), 19.2 (Hamiltonian Paths)"> </Resource>
<Resource source="CF" title="DP Over Subsets" url="blog/entry/337"> </Resource> <Resource source="CF" title="DP Over Subsets" url="blog/entry/337"> </Resource>
<Resource source="HE" title="DP and Bit Masking" url="https://www.hackerearth.com/practice/algorithms/dynamic-programming/bit-masking/tutorial/"> </Resource> <Resource source="HE" title="DP and Bit Masking" url="https://www.hackerearth.com/practice/algorithms/dynamic-programming/bit-masking/tutorial/"> </Resource>
<Resource source="CF" title="SOS Dynamic Programming" url="blog/entry/45223"> Sum over Subsets DP </Resource>
</Resources> </Resources>
## Problems ## Problems

View file

@ -202,7 +202,7 @@ Naively, this would take up $O(N^2)$ memory, but *path compression* enables it t
<Problems problems={problems.tree} /> <Problems problems={problems.tree} />
### Generate Suffix Array ### Generate Suffix Array from Suffix Tree
A suffix array can be generated by the suffix tree by taking the dfs traversal of the suffix tree. A suffix array can be generated by the suffix tree by taking the dfs traversal of the suffix tree.
@ -215,12 +215,12 @@ A suffix array can be generated by the suffix tree by taking the dfs traversal o
```cpp ```cpp
int N, sa[MN];//length of string, suffix array int N, sa[MN];//length of string, suffix array
struct edge struct Edge
{ {
public: public:
int n, l, r;//node, edge covers s[l..r] int n, l, r;//node, edge covers s[l..r]
explicit operator bool() const {return n!=-1;} explicit operator bool() const {return n!=-1;}
} c[MN*2][26]; } c[MN*2][26]; // edges of a suffix tree
void dfs(int n=0, int d=0) void dfs(int n=0, int d=0)
{ {
@ -237,9 +237,74 @@ void dfs(int n=0, int d=0)
``` ```
</CPPSection> </CPPSection>
<JavaSection /> </LanguageSection>
<PySection /> ### Generate Suffix Tree from Suffix Array
Of course, the above operation can be reversed as well.
Each element in the suffix array corresponds to a leaf in the suffix tree.
The LCP array stores information about the Lowest Common Ancestor of two adjacent elements in the suffix array.
Using these two pieces of information, we can construct the suffix tree from the suffix array in linear time.
<LanguageSection>
<CPPSection>
```cpp
//untested
int N, sa[MN], lcp[MN];//length of string, suffix array, lcp array: lcp[i] stores longest common prefix of sa[i] and sa[i+1]
struct Edge
{
public:
int n, l, r; //node, edge covers s[l..r]
explicit operator bool() const {return n!=-1;}
} c[MN*2][26]; // edges of suffix tree
void build_tree()
{
}
```
</CPPSection>
</LanguageSection>
### Generate Suffix Tree from Suffix Automaton
One interesting thing about Suffix Trees and Suffix Automata is that the link tree of a Suffix Automaton is equivalent to the Suffix Tree of the reversed string.
Since Suffix Automata are much easier to create than Suffix Trees, we can use this as an alternate method to build a Suffix Tree, all in linear time too!
<LanguageSection>
<CPPSection>
<!-- https://codeforces.com/edu/course/2/lesson/2/2/practice/contest/269103/submission/85759835 - This submission contains both -->
```cpp
char s[MN]; //string
int ord[MN]; // nodes representing prefixes of the string s
int u[MN*2]; // whether the node has already been created
int l[MN*2]; // link in suffix automaton
Edge c[MN*2][27]; // edge of suffix tree (not automaton; structure of automaton is not necessary to build stree)
void build_tree()
{
s[N] = 26; // terminator
for(int i=N;i>=0;--i) ord[i]=append(ord[i+1], s[i]);
for(int i=0,x,r,l;i<=N;++i)
{
x=ord[i], r=N+1;
for(;x&&!u[x];x=l[x])
{
l=r-d[x]+d[l[x]];
c[l[x]][s[l]]={x, l, r};
r=l;
u[x]=1;
}
}
}
```
</CPPSection>
</LanguageSection> </LanguageSection>

View file

@ -58,4 +58,20 @@ export const Authors: Author[] = [
codeforces: "darren_yao", codeforces: "darren_yao",
github: "darren-yao", github: "darren-yao",
}, },
{
photo: 'michael',
name: 'Siyong Huang',
title: 'Content Author',
blurb: '',
codeforces: "frodakcin",
github: "frodakcin",
},
{
photo: 'nathanc',
name: 'Nathan Chen',
title: 'Content Author',
blurb: '',
codeforces: "nchn27",
github: "nchn27",
},
]; ];

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View file

@ -97,18 +97,23 @@ const MODULE_ORDERING: {[key in SectionID]: Chapter[]} = {
] ]
}, },
{ {
name: "Binary Search", name: "Sorting",
items: [ items: [
"binary-search-sorted", "binary-search-sorted",
"binary-search-ans", "sorting-custom",
"greedy",
] ]
}, },
{ {
name: "Sorting", name: "Two Pointers",
items: [ items: [
"sorting-methods", "2P",
"sorting-custom", ]
"greedy", },
{
name: "Binary Search",
items: [
"binary-search-ans",
] ]
}, },
{ {
@ -116,14 +121,6 @@ const MODULE_ORDERING: {[key in SectionID]: Chapter[]} = {
items: [ items: [
"intro-ordered", "intro-ordered",
"custom-cpp-stl", "custom-cpp-stl",
"harder-ordered",
]
},
{
name: "Stacks & Queues",
items: [
"stacks-queues",
"sliding",
] ]
}, },
{ {
@ -136,6 +133,14 @@ const MODULE_ORDERING: {[key in SectionID]: Chapter[]} = {
}, },
], ],
"gold": [ "gold": [
{
name: "Data Structures",
items: [
"stacks",
"sliding",
"queues",
]
},
{ {
name: "Dynamic Programming", name: "Dynamic Programming",
items: [ items: [

View file

@ -22,9 +22,9 @@ export const IncompleteSection = ({ children }) => {
This section is not complete. This section is not complete.
</h3> </h3>
<div className="mt-2 text-sm leading-5 text-red-700 no-bottom-margin"> <div className="mt-2 text-sm leading-5 text-red-700 no-bottom-margin">
{children}
Feel free to file a request to complete this using the "Contact Us" Feel free to file a request to complete this using the "Contact Us"
button. button. <br />
<i>{children}</i>
</div> </div>
</div> </div>
</div> </div>

View file

@ -53,6 +53,7 @@ const sources = {
}; };
export const sourceTooltip = { export const sourceTooltip = {
AoPS: 'Art of Problem Solving',
CPH: "Book - Competitive Programmer's Handbook", CPH: "Book - Competitive Programmer's Handbook",
PAPS: 'Book - Principles of Algorithmic Problem Solving', PAPS: 'Book - Principles of Algorithmic Problem Solving',
IUSACO: 'Book - An Introduction to the USA Computing Olympiad', IUSACO: 'Book - An Introduction to the USA Computing Olympiad',

View file

@ -319,8 +319,8 @@ export default function IndexPage(props: PageProps) {
</div> </div>
<div className="ml-3"> <div className="ml-3">
<p className="text-sm leading-5 text-yellow-700 text-left"> <p className="text-sm leading-5 text-yellow-700 text-left">
This guide is not a syllabus. Topics on this guide reflect{' '} This guide is not an official syllabus. Topics on this guide
<i>past</i> problems, not future problems. reflect <i>past</i> problems, not future problems.
</p> </p>
</div> </div>
</div> </div>
@ -507,15 +507,14 @@ export default function IndexPage(props: PageProps) {
<div> <div>
<div> <div>
<dt className="text-lg leading-6 font-medium text-gray-900"> <dt className="text-lg leading-6 font-medium text-gray-900">
Is this a Syllabus? Is this an official syllabus?
</dt> </dt>
<dd className="mt-2"> <dd className="mt-2">
<p className="text-base leading-6 text-gray-500"> <p className="text-base leading-6 text-gray-500">
<b>No. This guide is NOT a syllabus.</b> USACO does not <b>No, USACO does not have an official syllabus.</b>
have an official syllabus. This guide merely lists topics This guide merely lists topics that have{' '}
that have <i>historically</i> appeared in USACO contests; <i>historically</i> appeared in USACO contests; it makes
it makes no guarantees about the topics in future USACO no guarantees about the topics in future USACO contests.
contests.
</p> </p>
</dd> </dd>
</div> </div>