Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@

## 주석과 문서화 (필수)
일관된 형식으로 친절하고 신호가 높은 문서를 작성하세요.
특히, 난이도가 높은 알고리즘/자료구조일수록 기억이 희미할 확률이 높으니 자세히 설명하세요.

### 1) 모듈 헤더 (재사용 가능한 각 컴포넌트마다)
상단 근처에 헤더 주석을 추가:
- what
- what: 단순히 알고리즘/자료구조의 이름을 적는 것이 아닌, 해당 구현체가 사용되는 맥락과 역할을 black box로 작성.
- time; memory
- constraint
- usage
Expand Down
4 changes: 2 additions & 2 deletions src/1-ds/erasable_pq.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
// what: erasable priority queue via lazy deletion.
// time: push/pop/erase O(log n); memory: O(n)
// constraint: erase/top/pop assume valid; duplicates ok.
// usage: epq<ll> pq; pq.push(x); pq.erase(x); ll v = pq.top(); pq.pop();
// usage: erase_pq<ll> pq; pq.push(x); pq.erase(x); ll v = pq.top(); pq.pop();
template <class T, class cmp = less<T>>
struct epq {
struct erase_pq {
priority_queue<T, vector<T>, cmp> q, del;
int size() { return (int)q.size() - (int)del.size(); }
bool empty() { return size() == 0; }
Expand Down
12 changes: 6 additions & 6 deletions src/1-ds/fenwick_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
// what: fenwick tree (point add, prefix/range sum).
// time: build O(n), update/query O(log n); memory: O(n)
// constraint: 0-indexed; kth needs all values >= 0.
// usage: fenw fw; fw.build(a); fw.add(p, x); fw.sum(l, r); fw.kth(k);
struct fenw {
// usage: fenwick fw; fw.build(a); fw.add(p, x); fw.sum(l, r); fw.kth(k);
struct fenwick {
int n;
vector<ll> a, t;
void init(int n_) {
Expand Down Expand Up @@ -52,8 +52,8 @@ struct fenw {
// what: fenwick tree (range add, point get).
// time: update/query O(log n); memory: O(n)
// constraint: 1-indexed; l <= r.
// usage: fenw_rp fw; fw.init(n); fw.add(l, r, x); ll v = fw.get(p);
struct fenw_rp { // 1-indexed
// usage: fenw_range fw; fw.init(n); fw.add(l, r, x); ll v = fw.get(p);
struct fenw_range { // 1-indexed
int n;
vector<ll> t;
void init(int n_) {
Expand All @@ -74,8 +74,8 @@ struct fenw_rp { // 1-indexed
// what: 2D fenwick tree (point add, rectangle sum).
// time: build O(n m), update/query O(log n log m); memory: O(n m)
// constraint: 0-indexed; no bounds check.
// usage: fenw2d fw; fw.build(a); fw.add(x, y, v); fw.sum(x1, y1, x2, y2);
struct fenw2d { // 0-indexed
// usage: fenw_2d fw; fw.build(a); fw.add(x, y, v); fw.sum(x1, y1, x2, y2);
struct fenw_2d { // 0-indexed
int n, m;
vector<vector<ll>> a, t;
void init(int n_, int m_) {
Expand Down
8 changes: 4 additions & 4 deletions src/1-ds/merge_sort_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ constexpr int MAX_MST = 1 << 17;
// what: merge sort tree for count of values > k on a range.
// time: build O(n log n), query O(log^2 n); memory: O(n log n)
// constraint: MAX_MST >= n; values fit in int; 0-indexed [l, r]; build once.
// usage: mseg st; st.build(a); st.query(l, r, k);
struct mseg {
// usage: merge_seg st; st.build(a); st.query(l, r, k);
struct merge_seg {
vector<int> t[MAX_MST << 1];
void build(const vector<int> &a) {
for (int i = 0; i < sz(a); i++)
Expand All @@ -27,8 +27,8 @@ struct mseg {
// what: iter merge sort tree for count of values > k on a range.
// time: build O(n log n), query O(log^2 n); memory: O(n log n)
// constraint: MAX_MST >= n; values fit in int; 0-indexed [l, r]; build once.
// usage: mseg_it st; st.build(a); st.query(l, r, k);
struct mseg_it {
// usage: merge_seg_it st; st.build(a); st.query(l, r, k);
struct merge_seg_it {
vector<int> t[MAX_MST << 1];
void build(const vector<int> &a) {
for (int i = 0; i < sz(a); i++)
Expand Down
40 changes: 20 additions & 20 deletions src/1-ds/segment_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
// what: segment tree (point set, range sum).
// time: build O(n), update/query O(log n); memory: O(n)
// constraint: 1-indexed [1, n]; a[0] unused.
// usage: segt st; st.build(a); st.set(p, v); st.query(l, r);
struct segt {
// usage: seg_tree st; st.build(a); st.set(p, v); st.query(l, r);
struct seg_tree {
int flag;
vector<ll> t;
void build(const vector<ll> &a) {
Expand All @@ -30,8 +30,8 @@ struct segt {
// what: iter segment tree (point set, range sum).
// time: build O(n), update/query O(log n); memory: O(n)
// constraint: 0-indexed [l, r).
// usage: segti st; st.build(a); st.set(p, v); st.query(l, r);
struct segti { // 0-indexed
// usage: seg_tree_it st; st.build(a); st.set(p, v); st.query(l, r);
struct seg_tree_it { // 0-indexed
int n;
vector<ll> t;
void build(const vector<ll> &a) {
Expand All @@ -56,8 +56,8 @@ struct segti { // 0-indexed
// what: segment tree for kth on freq array.
// time: update/query O(log n); memory: O(n)
// constraint: 1-indexed [1, n], values >= 0.
// usage: segk st; st.init(n); st.add(p, v); st.kth(k);
struct segk {
// usage: seg_tree_kth st; st.init(n); st.add(p, v); st.kth(k);
struct seg_tree_kth {
int flag;
vector<ll> t;
void init(int n) {
Expand All @@ -79,8 +79,8 @@ struct segk {
// what: segment tree with range add + range sum.
// time: update/query O(log n); memory: O(n)
// constraint: 1-indexed [1, n]; a[0] unused.
// usage: seglz st; st.build(a); st.add(l, r, v); st.query(l, r);
struct seglz {
// usage: seg_tree_lz st; st.build(a); st.add(l, r, v); st.query(l, r);
struct seg_tree_lz {
int flag;
vector<ll> t, lz;
void build(const vector<ll> &a) {
Expand Down Expand Up @@ -128,8 +128,8 @@ struct seglz {
// what: persistent segment tree (point set, range sum).
// time: build O(n), update/query O(log n); memory: O(n log n)
// constraint: 1-indexed [1, n]; a[0] unused.
// usage: pst st; st.build(n, a); st.set(p, v); st.query(l, r, ver);
struct pst {
// usage: seg_pst st; st.build(n, a); st.set(p, v); st.query(l, r, ver);
struct seg_pst {
struct node {
int l, r;
ll val;
Expand Down Expand Up @@ -201,13 +201,13 @@ struct pst {
// what: dynamic seg tree (sparse, point add, range sum).
// time: update/query O(log R); memory: O(k log R)
// constraint: range [MAXL, MAXR], missing child => 0.
// usage: dyseg st; st.add(p, v); st.query(l, r);
// usage: seg_sparse st; st.add(p, v); st.query(l, r);
constexpr int MAXL = 1, MAXR = 1000000;
struct dnode {
ll x;
int l, r;
};
struct dyseg {
struct seg_sparse {
vector<dnode> t = {{0, -1, -1}, {0, -1, -1}};
void add(int p, ll x, int v = 1, int nl = MAXL, int nr = MAXR) {
if (p < nl || nr < p) return;
Expand Down Expand Up @@ -242,8 +242,8 @@ struct dyseg {
// what: 2D segment tree (point set, rect sum).
// time: build O(n^2), update/query O(log^2 n); memory: O(n^2)
// constraint: 0-indexed square n x n.
// usage: seg2d st; st.build(a); st.set(x, y, v); st.query(x1, x2, y1, y2);
struct seg2d { // 0-indexed
// usage: seg_2d st; st.build(a); st.set(x, y, v); st.query(x1, x2, y1, y2);
struct seg_2d { // 0-indexed
int n;
vector<vector<ll>> t;
void build(const vector<vector<ll>> &a) {
Expand Down Expand Up @@ -287,18 +287,18 @@ struct seg2d { // 0-indexed

// what: 2D seg tree with coord comp (offline).
// time: prep O(q log q), update/query O(log^2 n); memory: O(q log q)
// constraint: call fmod/fqry first, then prep, then set/query.
// usage: seg2dc st(n); st.fmod(x, y); st.fqry(x1, x2, y1, y2); st.prep(); st.set(x, y, v); st.query(x1, x2, y1, y2);
struct seg2dc { // 0-indexed
// constraint: call mark_set/mark_qry first, then prep, then set/query.
// usage: seg2d_comp st(n); st.mark_set(x, y); st.mark_qry(x1, x2, y1, y2); st.prep(); st.set(x, y, v); st.query(x1, x2, y1, y2);
struct seg2d_comp { // 0-indexed
int n;
vector<vector<ll>> a;
vector<vector<int>> used;
unordered_map<ll, ll> mp;
seg2dc(int n) : n(n), a(2 * n), used(2 * n) {}
void fmod(int x, int y) {
seg2d_comp(int n) : n(n), a(2 * n), used(2 * n) {}
void mark_set(int x, int y) {
for (x += n; x >= 1; x >>= 1) used[x].push_back(y);
}
void fqry(int x1, int x2, int y1, int y2) {
void mark_qry(int x1, int x2, int y1, int y2) {
for (x1 += n, x2 += n + 1; x1 < x2; x1 >>= 1, x2 >>= 1) {
if (x1 & 1) {
used[x1].push_back(y1);
Expand Down
4 changes: 2 additions & 2 deletions src/2-graph/bcc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
// what: biconnected components + articulation points/edges (undirected).
// time: O(n+m); memory: O(n+m)
// constraint: 1-indexed; no self-loops; recursion depth O(n).
// usage: bcc g; g.init(n); g.add(u,v); g.run(); // g.bccs, g.ap, g.ae
struct bcc {
// usage: bcc_graph g; g.init(n); g.add(u,v); g.run(); // g.bccs, g.ap, g.ae
struct bcc_graph {
int n, tim;
vector<vector<pii>> adj;
vector<int> dfn, low, ap, st;
Expand Down
4 changes: 2 additions & 2 deletions src/2-graph/euler_circuit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
// what: Euler circuit via Hierholzer (undirected multigraph, matrix).
// time: O(n^2+m); memory: O(n^2)
// constraint: 1-indexed; all nonzero-degree nodes connected.
// usage: ecir g; g.init(n); g.add(u,v); if (g.can()) auto path=g.run(1);
struct ecir {
// usage: euler_cir g; g.init(n); g.add(u,v); if (g.can()) auto path=g.run(1);
struct euler_cir {
int n;
vector<vector<int>> adj;
vector<int> nxt, path;
Expand Down
4 changes: 2 additions & 2 deletions src/2-graph/kth_shortest_path.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
// what: k-th shortest walk (Eppstein-style, non-negative weights).
// time: O((n+m)log m + klog k); memory: O(n+m+heap)
// constraint: 1-indexed; w >= 0; n <= MAXN-1; recursion depth O(log m).
// usage: ksp g; g.init(n); g.add(u,v,w); auto v=g.run(s,e,k);
struct ksp {
// usage: kth_walk g; g.init(n); g.add(u,v,w); auto v=g.run(s,e,k);
struct kth_walk {
static const int MAXN = 303030;
static const ll INF = (ll)1e18;

Expand Down
4 changes: 2 additions & 2 deletions src/2-graph/offline_dynamic_connectivity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
// what: offline dynamic connectivity with segment tree + rollback dsu.
// time: O((n+q)log q); memory: O(n+q)
// constraint: 1-indexed time; ops consistent; no parallel active edge.
// usage: odc g; g.init(n,q); g.add_op(i,op,u,v); g.build(); g.run();
struct odc {
// usage: dyn_conn g; g.init(n,q); g.add_op(i,op,u,v); g.build(); g.run();
struct dyn_conn {
struct seg {
int flg;
vector<vector<pii>> t;
Expand Down
8 changes: 4 additions & 4 deletions src/2-graph/scc_2_sat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
// what: SCC via Kosaraju.
// time: O(n+m); memory: O(n+m)
// constraint: directed; 1-indexed; recursion depth O(n).
// usage: scc_ko s; s.init(n); s.add(u,v); int c=s.run();
struct scc_ko {
// usage: scc_kosa s; s.init(n); s.add(u,v); int c=s.run();
struct scc_kosa {
int n;
vector<vector<int>> g, rg, sccs;
vector<int> vis, comp, ord;
Expand Down Expand Up @@ -50,8 +50,8 @@ struct scc_ko {
// what: SCC via Tarjan.
// time: O(n+m); memory: O(n+m)
// constraint: directed; 1-indexed; recursion depth O(n).
// usage: scc_ta s; s.init(n); s.add(u,v); int c=s.run();
struct scc_ta {
// usage: scc_tarjan s; s.init(n); s.add(u,v); int c=s.run();
struct scc_tarjan {
int n, tim;
vector<vector<int>> g, sccs;
vector<int> dfn, low, comp, st, ins;
Expand Down
8 changes: 4 additions & 4 deletions src/2-graph/shortest_path.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
// what: Dijkstra shortest path (non-negative weights).
// time: O((n+m)log n); memory: O(n+m)
// constraint: directed; 1-indexed; w >= 0.
// usage: dijk g; g.init(n); g.add(u,v,w); auto dist=g.run(s);
struct dijk {
// usage: dijkstra g; g.init(n); g.add(u,v,w); auto dist=g.run(s);
struct dijkstra {
static const ll INF = (1LL << 62);
int n;
vector<vector<pll>> adj;
Expand Down Expand Up @@ -37,8 +37,8 @@ struct dijk {
// what: Bellman-Ford shortest path.
// time: O(nm); memory: O(n+m)
// constraint: directed; 1-indexed; detects negative cycle reachable from s.
// usage: bell g; g.init(n); g.add(u,v,w); bool ok=g.run(s, dist);
struct bell {
// usage: bell_ford g; g.init(n); g.add(u,v,w); bool ok=g.run(s, dist);
struct bell_ford {
static const ll INF = (1LL << 62);
int n;
vector<tuple<int, int, ll>> ed;
Expand Down
6 changes: 3 additions & 3 deletions tests/1-ds/test_erasable_pq.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "../../src/1-ds/erasable_pq.cpp"

// what: tests for epq (erasable pq).
// what: tests for erase_pq (erasable pq).
// time: random + edge cases; memory: O(n)
// constraint: uses assert, fixed seed.
// usage: g++ -std=c++17 test_erasable_pq.cpp && ./a.out
Expand All @@ -19,7 +19,7 @@ ll pick_multiset(multiset<ll> &ms) {
}

void test_edge_cases() {
epq<ll> pq;
erase_pq<ll> pq;
multiset<ll> ms;

pq.push(5), ms.insert(5);
Expand All @@ -43,7 +43,7 @@ void test_edge_cases() {
}

void test_randomized() {
epq<ll> pq;
erase_pq<ll> pq;
multiset<ll> ms;

for (int it = 0; it < 3000; it++) {
Expand Down
14 changes: 7 additions & 7 deletions tests/1-ds/test_fenwick_tree.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "../../src/1-ds/fenwick_tree.cpp"

// what: tests for fenw, fenw_rp, fenw2d.
// what: tests for fenwick, fenw_range, fenw_2d.
// time: random + edge cases; memory: O(n^2)
// constraint: uses assert, fixed seed.
// usage: g++ -std=c++17 test_fenwick_tree.cpp && ./a.out
Expand Down Expand Up @@ -34,7 +34,7 @@ ll sum_2d(const vector<vector<ll>> &a, int x1, int y1, int x2, int y2) {
}

void test_fenwick_basic() {
fenw fw;
fenwick fw;
vector<ll> a = {5};
fw.build(a);
assert(fw.sum(0, 0) == 5);
Expand All @@ -50,7 +50,7 @@ void test_fenwick_random() {
vector<ll> a(n);
for (int i = 0; i < n; i++) a[i] = rnd(0, 5);

fenw fw;
fenwick fw;
fw.build(a);

for (int it = 0; it < 5000; it++) {
Expand Down Expand Up @@ -80,7 +80,7 @@ void test_fenwick_random() {
}

void test_fenwick_rp_basic() {
fenw_rp fw;
fenw_range fw;
fw.init(1);
fw.add(1, 1, 5);
assert(fw.get(1) == 5);
Expand All @@ -89,7 +89,7 @@ void test_fenwick_rp_basic() {
void test_fenwick_rp_random() {
int n = 40;
vector<ll> a(n + 1, 0);
fenw_rp fw;
fenw_range fw;
fw.init(n);

for (int it = 0; it < 4000; it++) {
Expand All @@ -108,7 +108,7 @@ void test_fenwick_rp_random() {
}

void test_fenwick_2d_basic() {
fenw2d fw;
fenw_2d fw;
vector<vector<ll>> a = {{3}};
fw.build(a);
assert(fw.sum(0, 0, 0, 0) == 3);
Expand All @@ -122,7 +122,7 @@ void test_fenwick_2d_random() {
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++) a[i][j] = rnd(-3, 3);

fenw2d fw;
fenw_2d fw;
fw.build(a);

for (int it = 0; it < 4000; it++) {
Expand Down
Loading