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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
My implementations of various data structures and algorithms for competitive programming.

## Contents (GitHub links, `main`)
- [0-common](https://github.com/manoflearning/cp-reference-codes/tree/main/src/0-common)
- [`common.hpp`](https://github.com/manoflearning/cp-reference-codes/blob/main/src/0-common/common.hpp)
- [1-ds](https://github.com/manoflearning/cp-reference-codes/tree/main/src/1-ds)
- [`erasable_pq.cpp`](https://github.com/manoflearning/cp-reference-codes/blob/main/src/1-ds/erasable_pq.cpp)
- [`fenwick_tree.cpp`](https://github.com/manoflearning/cp-reference-codes/blob/main/src/1-ds/fenwick_tree.cpp)
Expand Down Expand Up @@ -69,5 +71,3 @@ My implementations of various data structures and algorithms for competitive pro
- [`stress_test.py`](https://github.com/manoflearning/cp-reference-codes/blob/main/src/8-misc/stress_test.py)
- [`system_of_difference_constraints.cpp`](https://github.com/manoflearning/cp-reference-codes/blob/main/src/8-misc/system_of_difference_constraints.cpp)
- [`ternary_search.cpp`](https://github.com/manoflearning/cp-reference-codes/blob/main/src/8-misc/ternary_search.cpp)
- [common](https://github.com/manoflearning/cp-reference-codes/tree/main/src/common)
- [`common.hpp`](https://github.com/manoflearning/cp-reference-codes/blob/main/src/common/common.hpp)
8 changes: 5 additions & 3 deletions src/common/common.hpp → src/0-common/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@

#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

using vi = vector<int>;
using vl = vector<ll>;
using vvi = vector<vector<int>>;
using vvl = vector<vector<ll>>;
#define fr first
#define sc second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
4 changes: 2 additions & 2 deletions src/1-ds/erasable_pq.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "../common/common.hpp"
#include "../0-common/common.hpp"

// what: priority queue that supports deleting arbitrary values via lazy deletion.
// time: push/pop/erase O(log n); memory: O(n)
Expand All @@ -7,7 +7,7 @@
template <class T, class cmp = less<T>>
struct erase_pq {
priority_queue<T, vector<T>, cmp> q, del;
int size() { return (int)q.size() - (int)del.size(); }
int size() { return sz(q) - sz(del); }
bool empty() { return size() == 0; }
const T &top() { return (fix(), q.top()); } // result: current extreme element.
void push(const T &x) { q.push(x); }
Expand Down
18 changes: 9 additions & 9 deletions src/1-ds/fenwick_tree.cpp
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
#include "../common/common.hpp"
#include "../0-common/common.hpp"

// what: maintain prefix sums with point updates and range sum queries.
// time: build O(n), update/query O(log n); memory: O(n)
// constraint: 0-indexed; kth needs all values >= 0.
// 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;
vl a, t;
void init(int n_) {
// goal: allocate arrays for size n.
n = n_;
a.assign(n, 0);
t.assign(n, 0);
}
void build(const vector<ll> &v) {
void build(const vl &v) {
// goal: build fenwick in O(n) from initial array.
n = sz(v);
a = v;
Expand Down Expand Up @@ -60,7 +60,7 @@ struct fenwick {
// 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;
vl t;
void init(int n_) {
// goal: allocate internal tree (1-indexed).
n = n_;
Expand All @@ -85,19 +85,19 @@ struct fenw_range { // 1-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;
vvl a, t;
void init(int n_, int m_) {
// goal: allocate arrays for n x m.
n = n_, m = m_;
a.assign(n, vector<ll>(m, 0));
t.assign(n, vector<ll>(m, 0));
a.assign(n, vl(m, 0));
t.assign(n, vl(m, 0));
}
void build(const vector<vector<ll>> &v) {
void build(const vvl &v) {
// goal: build 2D fenwick in O(n*m).
n = sz(v);
m = n ? sz(v[0]) : 0;
a = v;
t.assign(n, vector<ll>(m, 0));
t.assign(n, vl(m, 0));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
t[i][j] += a[i][j];
Expand Down
8 changes: 4 additions & 4 deletions src/1-ds/li_chao_tree.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "../common/common.hpp"
#include "../0-common/common.hpp"

// what: maintain max of lines on a fixed x-range with online add + point query.
// time: add/query O(log X); memory: O(n)
Expand All @@ -22,7 +22,7 @@ struct li_chao {
void init(ll xl, ll xr) {
// goal: set x-range and clear tree.
t.clear();
t.push_back({xl, xr, -1, -1, LINE_E});
t.pb({xl, xr, -1, -1, LINE_E});
}
void add(lc_line nw, int v = 0) {
// goal: insert a new line into the segment.
Expand All @@ -40,14 +40,14 @@ struct li_chao {
t[v].ln = hi;
if (t[v].r == -1) {
t[v].r = sz(t);
t.push_back({mid + 1, xr, -1, -1, LINE_E});
t.pb({mid + 1, xr, -1, -1, LINE_E});
}
add(lo, t[v].r);
} else {
t[v].ln = lo;
if (t[v].l == -1) {
t[v].l = sz(t);
t.push_back({xl, mid, -1, -1, LINE_E});
t.pb({xl, mid, -1, -1, LINE_E});
}
add(hi, t[v].l);
}
Expand Down
14 changes: 7 additions & 7 deletions src/1-ds/merge_sort_tree.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
#include "../common/common.hpp"
#include "../0-common/common.hpp"
constexpr int MAX_MST = 1 << 17;

// what: static range count queries by storing sorted lists on a segment tree.
// 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: 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) {
vi t[MAX_MST << 1];
void build(const vi &a) {
// goal: build sorted lists for each node.
for (int i = 0; i < sz(a); i++)
t[i + MAX_MST].push_back(a[i]);
t[i + MAX_MST].pb(a[i]);
for (int i = MAX_MST - 1; i >= 1; i--) {
t[i].resize(sz(t[i << 1]) + sz(t[i << 1 | 1]));
merge(all(t[i << 1]), all(t[i << 1 | 1]), t[i].begin());
Expand All @@ -31,11 +31,11 @@ struct merge_seg {
// constraint: MAX_MST >= n; values fit in int; 0-indexed [l, r]; build once.
// 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) {
vi t[MAX_MST << 1];
void build(const vi &a) {
// goal: build sorted lists for each node.
for (int i = 0; i < sz(a); i++)
t[i + MAX_MST].push_back(a[i]);
t[i + MAX_MST].pb(a[i]);
for (int i = MAX_MST - 1; i >= 1; i--) {
t[i].resize(sz(t[i << 1]) + sz(t[i << 1 | 1]));
merge(all(t[i << 1]), all(t[i << 1 | 1]), t[i].begin());
Expand Down
5 changes: 1 addition & 4 deletions src/1-ds/pbds.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "../common/common.hpp"
#include "../0-common/common.hpp"
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
Expand All @@ -20,18 +20,15 @@ void m_insert(omset &os, ll val) {
// goal: insert one occurrence of val.
os.insert({val, om_uid++});
}

void m_erase(omset &os, ll val) {
// goal: erase one occurrence of val.
auto it = os.lower_bound({val, LLONG_MIN});
os.erase(it);
}

int m_order(const omset &os, ll val) {
// result: number of elements strictly less than val.
return os.order_of_key({val, LLONG_MIN});
}

ll m_kth(const omset &os, int k) {
// result: k-th value (0-indexed) by order.
return os.find_by_order(k)->fr;
Expand Down
52 changes: 26 additions & 26 deletions src/1-ds/segment_tree.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#include "../common/common.hpp"
#include "../0-common/common.hpp"

// what: point update + range sum on a fixed-size array using a tree.
// time: build O(n), update/query O(log n); memory: O(n)
// constraint: 1-indexed [1, n]; a[0] unused.
// 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) {
vl t;
void build(const vl &a) {
// goal: build tree from 1-indexed array.
int n = sz(a) - 1;
flag = 1;
Expand Down Expand Up @@ -36,8 +36,8 @@ struct seg_tree {
// 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) {
vl t;
void build(const vl &a) {
// goal: build tree from 0-indexed array.
n = sz(a);
t.assign(2 * n, 0);
Expand Down Expand Up @@ -65,7 +65,7 @@ struct seg_tree_it { // 0-indexed
// usage: seg_tree_kth st; st.init(n); st.add(p, v); st.kth(k);
struct seg_tree_kth {
int flag;
vector<ll> t;
vl t;
void init(int n) {
// goal: allocate tree for size n.
flag = 1;
Expand All @@ -91,8 +91,8 @@ struct seg_tree_kth {
// 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) {
vl t, lz;
void build(const vl &a) {
// goal: build tree and clear lazy tags.
int n = sz(a) - 1;
flag = 1;
Expand Down Expand Up @@ -149,19 +149,19 @@ struct seg_pst {
};
int n;
vector<node> t;
vector<int> root;
vi root;

void newnd() { t.push_back({-1, -1, 0}); }
void build(int n_, const vector<ll> &a) {
void newnd() { t.pb({-1, -1, 0}); }
void build(int n_, const vl &a) {
// goal: build initial version.
n = n_;
t.clear();
root.clear();
newnd();
root.push_back(0);
root.pb(0);
build(1, n, root[0], a);
}
void build(int l, int r, int v, const vector<ll> &a) {
void build(int l, int r, int v, const vl &a) {
// goal: build node v for range [l, r].
if (l == r) {
t[v].val = a[l];
Expand All @@ -179,7 +179,7 @@ struct seg_pst {
void set(int p, ll val) {
// goal: create new version with a[p] = val.
newnd();
root.push_back(sz(t) - 1);
root.pb(sz(t) - 1);
set(p, val, 1, n, root[sz(root) - 2], root.back());
}
void set(int p, ll val, int l, int r, int v1, int v2) {
Expand Down Expand Up @@ -246,13 +246,13 @@ struct seg_sparse {
if (p <= mid) {
if (t[v].l == -1) {
t[v].l = sz(t);
t.push_back({0, -1, -1});
t.pb({0, -1, -1});
}
add(p, x, t[v].l, nl, mid);
} else {
if (t[v].r == -1) {
t[v].r = sz(t);
t.push_back({0, -1, -1});
t.pb({0, -1, -1});
}
add(p, x, t[v].r, mid + 1, nr);
}
Expand All @@ -275,11 +275,11 @@ struct seg_sparse {
// 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) {
vvl t;
void build(const vvl &a) {
// goal: build 2D tree from initial grid.
n = sz(a);
t.assign(2 * n, vector<ll>(2 * n, 0));
t.assign(2 * n, vl(2 * n, 0));
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
t[i + n][j + n] = a[i][j];
Expand Down Expand Up @@ -325,24 +325,24 @@ struct seg_2d { // 0-indexed
// 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;
vvl a;
vvi used;
unordered_map<ll, ll> mp;
seg2d_comp(int n) : n(n), a(2 * n), used(2 * n) {}
void mark_set(int x, int y) {
// goal: record y-coordinates that will be updated.
for (x += n; x >= 1; x >>= 1) used[x].push_back(y);
for (x += n; x >= 1; x >>= 1) used[x].pb(y);
}
void mark_qry(int x1, int x2, int y1, int y2) {
// goal: record y-coordinates needed for queries.
for (x1 += n, x2 += n + 1; x1 < x2; x1 >>= 1, x2 >>= 1) {
if (x1 & 1) {
used[x1].push_back(y1);
used[x1++].push_back(y2);
used[x1].pb(y1);
used[x1++].pb(y2);
}
if (x2 & 1) {
used[--x2].push_back(y1);
used[x2].push_back(y2);
used[--x2].pb(y1);
used[x2].pb(y2);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/1-ds/union_find.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#include "../common/common.hpp"
#include "../0-common/common.hpp"

// what: maintain dynamic connectivity with union-find and size queries.
// time: init O(n), join/find amortized a(n); memory: O(n)
// constraint: 1-indexed [1, n].
// usage: dsu d; d.init(n); d.join(a, b); int r = d.find(x); int s = d.size(x);
struct dsu {
vector<int> p;
vi p;
void init(int n) { p.assign(n + 1, -1); } // goal: reset to n singletons.
int find(int x) { return p[x] < 0 ? x : p[x] = find(p[x]); } // result: root of x.
int size(int x) { return -p[find(x)]; }
Expand Down
Loading