Prepare with a purpose
Practice problems across graph algorithms, dynamic programming, greedy methods, strings, and number theory, organized so students can work on the topics they need.
835 problems. My solutions.
Shared to help others learn.
I turned my C++ practice into a public learning resource, with solutions, explanations, and tests for students preparing for competitions, coursework, and technical interviews.
I worked through 835 problems from CSES, Codeforces, and AtCoder to sharpen my C++ and algorithmic problem-solving skills. I published my solutions on GitHub with the reasoning behind each approach, time and space complexity, and tests for the edge cases. What began as my own practice is now an open resource for students preparing for competitions and technical interviews, strengthening their algorithms coursework, or becoming more confident C++ programmers.
Practice problems across graph algorithms, dynamic programming, greedy methods, strings, and number theory, organized so students can work on the topics they need.
My notes explain why an approach works, what it costs, and where it can go wrong, helping students recognize the same idea in a new problem.
Every solution compiles on its own. Students can run the tests, explore edge cases, and study reusable data structures as they develop their own implementations.
C++17 solutions and reusable headers, with Python tooling for catalogue checks, test execution, and differential verification.
These worked examples show the ideas behind my solutions. Follow a diagram, trace the steps, and connect the reasoning to the C++ implementation below.
Start at city 1, always expand the cheapest unsettled route, and skip stale queue entries.
Explore the solutionAt each stone, compare the cost of jumping from one or two stones back.
Explore the solutionKeep partial sums in a Fenwick tree; updates and prefix queries follow the lowest set bit.
Explore the solutionProcess budgets backwards so each book can contribute at most once.
Explore the solutionSearch for the first time at which the machines can produce the target quantity.
Explore the solutionRearrange a[j] − a[i] = j − i into equal values of a[i] − i, then count previous matches.
Explore the solutionSix examples from my collection, covering different ways to approach a problem. Read the C++ here, then open my notes for the reasoning, complexity, and mistakes to watch for.
Start at city 1, always expand the cheapest unsettled route, and skip stale queue entries.
// Shortest Routes I | https://cses.fi/problemset/task/1671/
// Time: O((n + m) log(n + m)); extra space: O(n + m).
#include <iostream>
#include <vector>
#include <queue>
#include <functional>
#include <utility>
#include <limits>
void solve() {
int n, m;
std::cin >> n >> m;
std::vector<std::vector<std::pair<int, long long>>> graph(n);
for (int i = 0; i < m; ++i) {
int a, b;
long long cost;
std::cin >> a >> b >> cost;
graph[a - 1].emplace_back(b - 1, cost);
}
constexpr long long infinity = std::numeric_limits<long long>::max() / 4;
std::vector<long long> distance(n, infinity);
using State = std::pair<long long, int>;
std::priority_queue<State, std::vector<State>, std::greater<State>> queue;
distance[0] = 0;
queue.emplace(0, 0);
while (!queue.empty()) {
auto [cost, u] = queue.top(); queue.pop();
if (cost != distance[u]) continue;
for (auto [v, weight] : graph[u]) {
if (cost + weight < distance[v]) {
distance[v] = cost + weight;
queue.emplace(distance[v], v);
}
}
}
for (int i = 0; i < n; ++i) std::cout << distance[i] << (i + 1 == n ? '\n' : ' ');
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
solve();
}At each stone, compare the cost of jumping from one or two stones back.
// Frog 1 | https://atcoder.jp/contests/dp/tasks/dp_a
// Time: O(n); extra space: O(n).
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <limits>
void solve() {
int n; std::cin >> n;
std::vector<long long> height(n), best(n, std::numeric_limits<long long>::max() / 4);
for (auto& value : height) std::cin >> value;
best[0] = 0;
for (int i = 1; i < n; ++i) {
best[i] = best[i - 1] + std::abs(height[i] - height[i - 1]);
if (i >= 2) best[i] = std::min(best[i], best[i - 2] + std::abs(height[i] - height[i - 2]));
}
std::cout << best.back() << '\n';
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
solve();
}Keep partial sums in a Fenwick tree; updates and prefix queries follow the lowest set bit.
// Dynamic Range Sum Queries | https://cses.fi/problemset/task/1648/
// Time: O((n + q) log n); extra space: O(n).
#include <iostream>
#include <vector>
void solve() {
int n, q;
std::cin >> n >> q;
std::vector<long long> values(n + 1), tree(n + 1);
auto add = [&](int index, long long delta) {
for (; index <= n; index += index & -index) tree[index] += delta;
};
auto prefix = [&](int index) {
long long answer = 0;
for (; index > 0; index -= index & -index) answer += tree[index];
return answer;
};
for (int i = 1; i <= n; ++i) { std::cin >> values[i]; add(i, values[i]); }
while (q--) {
int type, a; long long b;
std::cin >> type >> a >> b;
if (type == 1) { add(a, b - values[a]); values[a] = b; }
else std::cout << prefix(static_cast<int>(b)) - prefix(a - 1) << '\n';
}
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
solve();
}Process budgets backwards so each book can contribute at most once.
// Book Shop | https://cses.fi/problemset/task/1158/
// Time: O(n * x); extra space: O(n + x).
#include <iostream>
#include <vector>
#include <algorithm>
void solve() {
int n, budget;
std::cin >> n >> budget;
std::vector<int> price(n), pages(n), best(budget + 1);
for (auto& value : price) std::cin >> value;
for (auto& value : pages) std::cin >> value;
for (int book = 0; book < n; ++book) {
for (int money = budget; money >= price[book]; --money) {
best[money] = std::max(best[money], best[money - price[book]] + pages[book]);
}
}
std::cout << best[budget] << '\n';
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
solve();
}Search for the first time at which the machines can produce the target quantity.
// Factory Machines | https://cses.fi/problemset/task/1620/
// Time: O(n log(min(k) * t)); extra space: O(n).
#include <iostream>
#include <vector>
#include <algorithm>
void solve() {
int n;
long long target;
std::cin >> n >> target;
std::vector<long long> times(n);
for (auto& time : times) std::cin >> time;
long long low = 0;
long long high = *std::min_element(times.begin(), times.end()) * target;
auto enough = [&](long long duration) {
long long made = 0;
for (long long time : times) {
long long produced = duration / time;
if (produced >= target - made) return true;
made += produced;
}
return false;
};
while (low < high) {
long long middle = low + (high - low) / 2;
if (enough(middle)) high = middle;
else low = middle + 1;
}
std::cout << low << '\n';
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
solve();
}Rearrange a[j] − a[i] = j − i into equal values of a[i] − i, then count previous matches.
// Same Differences | https://codeforces.com/problemset/problem/1520/D
// Time: O(n log n) per case; extra space: O(n).
#include <iostream>
#include <map>
void solve() {
int tests; std::cin >> tests;
while (tests-- > 0) {
int n; std::cin >> n; std::map<long long,long long> frequency; long long answer=0;
for (int i=0;i<n;++i) { long long value; std::cin >> value; answer+=frequency[value-i]++; }
std::cout << answer << '\n';
}
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
solve();
}I include tests alongside the solutions so students can check their understanding and catch mistakes. These results are recorded in the repository from local runs on Linux with GCC 13.3.0 and Python 3.12.14.
Warnings treated as errors.
Distinct sample and edge-case fixtures.
Reusable structures checked against simple models.
101 solutions; deterministic seed 2110.
Large inputs, long chains, and integer limits.
Catalogue integrity and semantic output checks.
The verification notes include the commands, test coverage, and boundary cases behind these results. All 835 solutions were included in the recorded sanitizer and library-assertion checks. Students can reproduce the runs and add tests of their own.
I made the collection public so other students can learn from the work I put into it. Choose a topic, try a problem, and use my explanation to work through the parts that are still unclear. The repository also includes a learning roadmap, C++ notes, and reusable data structures.
