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
41 changes: 28 additions & 13 deletions content-wf.typ
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
#import "lib/render.typ": *

#let university = "UTFSM"
#let team-name = "Team Name"
#let team-name = "La CASneta"

#let wf-config = (
code-text-size: 6.5pt,
code-small-text-size: 5pt,
code-small-text-size: 6.5pt,
code-small-threshold: 90,
category-size: 10pt,
subcategory-size: 8pt,
section-size: 9pt,
description-size: 7pt,
category-spacing: 0.8em,
category-spacing: 0.5em,
subcategory-spacing: 0.5em,
category-line-stroke: 1pt,
pagebreak-between-topics: false,
Expand All @@ -21,19 +21,34 @@
#set page(
paper: "a4",
flipped: true,
columns: 3,
margin: (x: 0.5cm, top: 1.2cm, bottom: 0.5cm),
columns: 4,
margin: (x: 0.3cm, top: 1.2cm, bottom: 0.3cm),
numbering: "1",
number-align: right + top,
header: [
#set text(size: 8pt)
#university — #team-name
#h(1fr)
#context counter(page).display("1")
],
header: context {
pad(top: 0.3cm)[
#set text(size: 8pt)
#[#university — #team-name]
#let current-page = counter(page).at(here()).first()
#let all-titles = query(<section-title>)
#let page-titles = all-titles.filter(m =>
counter(page).at(m.location()).first() == current-page
).map(m => m.value)
#place(center + top)[
#block(width: 70%, align(center)[
#text(weight: "bold", size: 7pt)[
#page-titles.dedup().join(", ")
]
])
]
#place(right + top)[
#counter(page).display("1")
]
]
},
)

#set columns(gutter: 0.3cm)
#set text(font: "New Computer Modern", size: 8pt)
#set columns(gutter: 0.2cm)
#set text(font: "New Computer Modern", size: 6.5pt)

#render-from-tracker("tracker-wf.yaml", wf-config)
28 changes: 28 additions & 0 deletions content/data-structures/sequences/interval-container.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
*Description:* Add/remove intervals from a set of disjoint intervals $[L, R)$. Merges overlapping intervals on add. $O(log N)$.
*Status:* KACTL based, not self tested
*/
using pii = pair<int,int>;
set<pii>::iterator addInterval(set<pii>& is,
int L, int R) {
if (L == R) return is.end();
auto it = is.lower_bound({L, R}), before = it;
while (it != is.end() && it->first <= R) {
R = max(R, it->second);
before = it = is.erase(it);
}
if (it != is.begin() && (--it)->second >= L) {
L = min(L, it->first);
R = max(R, it->second);
is.erase(it);
}
return is.insert(before, {L, R});
}
void removeInterval(set<pii>& is, int L, int R) {
if (L == R) return;
auto it = addInterval(is, L, R);
auto r2 = it->second;
if (it->first == L) is.erase(it);
else (int&)it->second = L;
if (R != r2) is.emplace(R, r2);
}
22 changes: 22 additions & 0 deletions content/dynamic-programming/misc/fast-knapsack.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
*Description:* Given $N$ non-negative weights $w$ and target $t$, computes max $S lt.eq t$ that is a subset sum. $O(N max(w_i))$.
*Status:* KACTL based, not self tested
*/
int knapsack(vector<int> w, int t) {
int a = 0, b = 0, n = w.size(), x;
while (b < n && a + w[b] <= t) a += w[b++];
if (b == n) return a;
int m = *max_element(w.begin(), w.end());
vector<int> u, v(2*m, -1);
v[a+m-t] = b;
for (int i = b; i < n; i++) {
u = v;
for (x = 0; x < m; x++)
v[x+w[i]] = max(v[x+w[i]], u[x]);
for (x = 2*m; --x > m;)
for (int j = max(0, u[x]); j < v[x]; j++)
v[x-w[j]] = max(v[x-w[j]], j);
}
for (a = t; v[a+m-t] < 0; a--) ;
return a;
}
39 changes: 0 additions & 39 deletions content/dynamic-programming/optimization/line-container.cpp

This file was deleted.

3 changes: 3 additions & 0 deletions content/general/tricks/debugging-tricks.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- `signal(SIGSEGV, [](int) { _Exit(0); });` converts segfaults into Wrong Answers. Similarly catch `SIGABRT` (assertion failures) and `SIGFPE` (zero divisions).

- `feenableexcept(29);` kills the program on NaNs (1), 0-divs (4), infinities (8) and denormals (16).
16 changes: 16 additions & 0 deletions content/general/tricks/optimization-tricks.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
`__builtin_ia32_ldmxcsr(40896);` disables denormals (which make floats 20x slower near their minimum value).

*Bit hacks:*
- `x & -x` is the least significant bit of `x`.
- `for (int x = m; x; ) { --x &= m; ... }` loops over all subset masks of `m` (except `m` itself).
- `c = x&-x, r = x+c; (((r^x) >> 2)/c) | r` is the next number after `x` with the same popcount.
- Subset sum over all bitmasks in $O(2^K)$:
```cpp
rep(b,0,K) rep(i,0,(1 << K))
if (i & 1 << b) D[i] += D[i^(1 << b)];
```

*Pragmas:*
- `#pragma GCC optimize ("Ofast")` — auto-vectorize loops, optimize floats.
- `#pragma GCC target ("avx2")` — can double vectorized performance (crashes on old machines).
- `#pragma GCC optimize ("trapv")` — kills program on integer overflows (slow).
19 changes: 19 additions & 0 deletions content/geometry/algorithms/circle-intersection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
*Description:* Computes the pair of points where two circles intersect. Returns false if no intersection. Uses Point2D.
*Status:* KACTL based, not self tested
*/
using P = Point2D<ld>;
bool circleInter(P a, P b, ld r1, ld r2,
pair<P,P>* out) {
if (a.sqdist(b) < 1e-18) return false;
P vec = b - a;
ld d2 = vec.norm(), sum = r1+r2, dif = r1-r2,
p = (d2 + r1*r1 - r2*r2) / (d2*2),
h2 = r1*r1 - p*p*d2;
if (sum*sum < d2 || dif*dif > d2) return false;
P per = {-vec.y, vec.x};
P mid = a + vec*p;
per = per * sqrt(fmax(0, h2) / d2);
*out = {mid + per, mid - per};
return true;
}
27 changes: 27 additions & 0 deletions content/geometry/algorithms/circle-polygon-intersection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
*Description:* Area of intersection of a circle (center $c$, radius $r$) with a CCW polygon. $O(n)$. Uses Point2D.
*Status:* KACTL based, not self tested
*/
using P = Point2D<ld>;
ld circlePoly(P c, ld r, vector<P>& ps) {
auto arg = [](P p, P q) {
return atan2(p^q, p|q);
};
auto tri = [&](P p, P q) {
auto r2 = r*r/2;
P d = q - p;
auto a = (d|p)/d.norm(), b = (p.norm()-r*r)/d.norm();
auto det = a*a - b;
if (det <= 0) return arg(p,q) * r2;
auto s = max(0.0, -a-sqrt(det));
auto t = min(1.0, -a+sqrt(det));
if (t < 0 || 1 <= s) return arg(p,q) * r2;
P u = p + d*s, v = q + d*(t-1);
return arg(p,u)*r2 + (u^v)/2 + arg(v,q)*r2;
};
ld sum = 0;
int n = ps.size();
for (int i = 0; i < n; i++)
sum += tri(ps[i]-c, ps[(i+1)%n]-c);
return sum;
}
19 changes: 19 additions & 0 deletions content/geometry/algorithms/circle-tangents.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
*Description:* External tangents of two circles (negate $r_2$ for internal). Returns 0, 1 or 2 tangents. `.first`/`.second` = tangency points on circle 1/2. Set $r_2 = 0$ for point tangents. Uses Point2D.
*Status:* KACTL based, not self tested
*/
using P = Point2D<ld>;
vector<pair<P,P>> tangents(P c1, ld r1,
P c2, ld r2) {
P d = c2 - c1;
ld dr = r1 - r2, d2 = d.norm(), h2 = d2 - dr*dr;
if (d2 < 1e-18 || h2 < 0) return {};
vector<pair<P,P>> out;
P perp = {-d.y, d.x};
for (ld sign : {-1.0, 1.0}) {
P v = (d*dr + perp*sqrt(h2)*sign) / d2;
out.push_back({c1 + v*r1, c2 + v*r2});
}
if (h2 < 1e-18) out.pop_back();
return out;
}
16 changes: 16 additions & 0 deletions content/geometry/algorithms/hull-diameter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
*Description:* Returns the two points with max distance on a convex hull (CCW, no collinear points). $O(n)$. Uses Point2D.
*Status:* KACTL based, not self tested
*/
template<class T>
array<Point2D<T>,2> hullDiameter(vector<Point2D<T>>& S) {
int n = S.size(), j = n < 2 ? 0 : 1;
pair<T, array<Point2D<T>,2>> res = {0, {S[0], S[0]}};
for (int i = 0; i < j;)
for (;; j = (j+1)%n) {
res = max(res, {S[i].sqdist(S[j]), {S[i], S[j]}});
if (((S[(j+1)%n]-S[j])^(S[i+1]-S[i])) >= 0)
{ i++; break; }
}
return res.second;
}
14 changes: 14 additions & 0 deletions content/geometry/algorithms/polygon-center.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
*Description:* Returns the centroid (center of mass) of a polygon. $O(n)$. Uses Point2D.
*Status:* KACTL based, not self tested
*/
using P = Point2D<ld>;
P polygonCenter(vector<P>& v) {
P res(0, 0); ld A = 0;
int n = v.size();
for (int i = 0, j = n-1; i < n; j = i++) {
res = res + (v[i]+v[j]) * (v[j]^v[i]);
A += v[j]^v[i];
}
return res / A / 3;
}
17 changes: 17 additions & 0 deletions content/geometry/algorithms/polygon-cut.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
*Description:* Returns polygon with everything to the left of line $s -> e$ cut away. Uses Point2D.
*Status:* KACTL based, not self tested
*/
using P = Point2D<ld>;
vector<P> polygonCut(vector<P>& poly, P s, P e) {
vector<P> res;
int n = poly.size();
for (int i = 0; i < n; i++) {
P cur = poly[i], prev = i ? poly[i-1] : poly.back();
auto a = s.cross(e, cur), b = s.cross(e, prev);
if ((a < 0) != (b < 0))
res.push_back(cur + (prev-cur) * (a / (a-b)));
if (a < 0) res.push_back(cur);
}
return res;
}
8 changes: 8 additions & 0 deletions content/geometry/primitives/line-distance.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
*Description:* Signed distance from point $p$ to line through $a$, $b$. Positive on left side seen from $a$ to $b$. Uses Point2D.
*Status:* KACTL based, not self tested
*/
template<class T>
ld lineDist(Point2D<T> a, Point2D<T> b, Point2D<T> p) {
return (ld)((b-a)^(p-a)) / (b-a).abs();
}
11 changes: 11 additions & 0 deletions content/geometry/primitives/segment-distance.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
*Description:* Shortest distance from point $p$ to segment $s$-$e$. Uses Point2D.
*Status:* KACTL based, not self tested
*/
using P = Point2D<ld>;
ld segDist(P s, P e, P p) {
if (s.sqdist(e) < 1e-18) return (p-s).abs();
auto d = (e-s).norm();
auto t = min(d, max(0.0, (p-s)|(e-s)));
return ((p-s)*d - (e-s)*t).abs() / d;
}
55 changes: 55 additions & 0 deletions content/graphs/connectivity/2sat.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
*Description:* 2-SAT solver. Negated variables use \~x. $O(N + E)$.
*Usage:* `TwoSat ts(n); ts.either(0, ~3); ts.setValue(2); ts.solve();`
*Status:* KACTL based, not self tested
*/
struct TwoSat {
int N;
vector<vector<int>> gr;
vector<int> values;
TwoSat(int n = 0) : N(n), gr(2*n) {}
int addVar() {
gr.emplace_back(); gr.emplace_back();
return N++;
}
void either(int f, int j) {
f = max(2*f, -1-2*f);
j = max(2*j, -1-2*j);
gr[f].push_back(j^1);
gr[j].push_back(f^1);
}
void setValue(int x) { either(x, x); }
void atMostOne(const vector<int>& li) {
if ((int)li.size() <= 1) return;
int cur = ~li[0];
for (int i = 2; i < (int)li.size(); i++) {
int next = addVar();
either(cur, ~li[i]);
either(cur, next);
either(~li[i], next);
cur = ~next;
}
either(cur, ~li[1]);
}
vector<int> val, comp, z; int Time = 0;
int dfs(int i) {
int low = val[i] = ++Time, x; z.push_back(i);
for (int e : gr[i]) if (!comp[e])
low = min(low, val[e] ? val[e] : dfs(e));
if (low == val[i]) do {
x = z.back(); z.pop_back();
comp[x] = low;
if (values[x>>1] == -1)
values[x>>1] = x&1;
} while (x != i);
return val[i] = low;
}
bool solve() {
values.assign(N, -1);
val.assign(2*N, 0); comp = val;
for (int i = 0; i < 2*N; i++) if (!comp[i]) dfs(i);
for (int i = 0; i < N; i++)
if (comp[2*i] == comp[2*i+1]) return false;
return true;
}
};
Loading