diff --git a/caderno.pdf b/caderno.pdf index 7714cc621aef8714e5683bd461e4a4018e148806..04e48e5e28662cb1bee84cd621640096a5c8cdbd 100644 Binary files a/caderno.pdf and b/caderno.pdf differ diff --git a/caderno/caderno.tex b/caderno/caderno.tex index 029cdd13df74d4e65a814e608e5cc6135de7c3b4..bf2079f951cb228284661f231fda39e8412c91a4 100644 --- a/caderno/caderno.tex +++ b/caderno/caderno.tex @@ -229,7 +229,7 @@ uma das partes do corte mínimo. \subsection{Fatorial e desarranjos} \begin{align*} n! &\approxeq \sqrt{2\pi n} \left(\frac{n}{e}\right)^n \\ - !n &= n!\sum_{i=0}^{n} \frac{(-1)^i)}{i!} \text{ para } n \ge 0 \\ + !n &= n!\sum_{i=0}^{n} \frac{(-1)^i}{i!} \text{ para } n \ge 0 \\ !n &= \left\lfloor \frac{n! + 1}{e} \right\rfloor \text{ para } n \ge 1 \\ !n &= n(!(n-1)) + (-1)^n \text{ para } n > 0 \end{align*} @@ -270,7 +270,7 @@ Então: \begin{itemize} \item $\mathcal{L}(\mathbb{Z}^2)$ escala $\mathbb{Z}^2$ em $\sqrt{2}$ e rotaciona em $\frac{\pi}{4}$ em sentido horário. \item Para algum $p \in \mathbb{Z}^2$, $\mathcal{L}(\{ q : M(q, p) \le d \})$ (círculo) forma um quadrado alinhado - nos eixos em $\mathcal{L}(\mathbb{Z})^2$, com canto inferior-esquerda em $\mathcal{L}(p) - (d, d)$ e canto superior-direito em $\mathcal{L}(p) + (d, d)$. + nos eixos em $\mathcal{L}(\mathbb{Z})^2$, com canto inferior-esquerdo em $\mathcal{L}(p) - (d, d)$ e canto superior-direito em $\mathcal{L}(p) + (d, d)$. \item $M(p, q) = C(\mathcal{L}(p), \mathcal{L}(q))$, e $C(p, q) = M(\mathcal{L}^{-1}(p), \mathcal{L}^{-1}(q))$. \end{itemize} diff --git a/fontes/circle-line-intersection.h b/fontes/circle-line-intersection.h new file mode 100644 index 0000000000000000000000000000000000000000..ea107f85a84155cdee7bc8527b432c6c65f2d257 --- /dev/null +++ b/fontes/circle-line-intersection.h @@ -0,0 +1,22 @@ +using line = tuple<ll, ll, ll>; + +vector<pt> circle_line_intersection(double r, line abc) { + auto [a, b, c] = abc; vector<pt> ans; + double a2b2 = (a*a+b*b), x0 = -a*c/a2b2, y0 = -b*c/a2b2; + if (c*c > r*r*a2b2+EPS) { + /* zero points */ + } + else if (abs(c*c - r*r*a2b2) < EPS) + ans.emplace_back(x0, y0); + else { + double d = r*r - c*c/a2b2, m = sqrt(d/a2b2); + ans.emplace_back(x0 + b*m, y0 - a*m); + ans.emplace_back(x0 - b*m, y0 + a*m); + } + return ans; +} + +line get_line(pt p, pt q) { + double a = q.py - p.py, b = p.px - q.px; + return make_tuple(a, b, a*p.px + b*p.py); +} diff --git a/fontes/dinic.h b/fontes/dinic.h index 5b01160537bcf01dd9c7febd69e0a1c9d74d0a94..85c99c6eea3fb0aadfb251d007ef34393064ad95 100644 --- a/fontes/dinic.h +++ b/fontes/dinic.h @@ -1,13 +1,13 @@ vector<vector<int>> res (N); vector<int> level (N), ptr (N); -struct edge { int u, v; ll cap, flow = 0; }; +struct edge { int u, v; ll cap; }; vector<edge> edges; queue<int> q; bool minimum_path(int s, int t) { while (!q.empty()) { int u = q.front(); q.pop(); for (int i : res[u]) { - if (edges[i].cap - edges[i].flow < 1) { continue; } + if (edges[i].cap < 1) { continue; } if (level[edges[i].v] != -1) { continue; } level[edges[i].v] = level[u] + 1; q.push(edges[i].v); @@ -22,11 +22,10 @@ ll dfs(int u, int t, ll pushed) { for (int& cid = ptr[u]; cid < res[u].size(); cid++) { int i = res[u][cid], v = edges[i].v; if (level[u] + 1 != level[v]) { continue; } - if (edges[i].cap - edges[i].flow < 1) { continue; } - ll tr = dfs(v, t, - min(pushed, edges[i].cap - edges[i].flow)); + if (edges[i].cap < 1) { continue; } + ll tr = dfs(v, t, min(pushed, edges[i].cap)); if (tr == 0) { continue; } - edges[i].flow += tr; edges[i^1].flow -= tr; + edges[i].cap -= tr; edges[i^1].cap += tr; return tr; } return 0; diff --git a/fontes/interval-set.h b/fontes/interval-set.h index 8db08b75ade7a399065bbbb4b1c2e833a7b42b88..b6824a38822c01b71e3a995fc132dc7cbfc11d38 100644 --- a/fontes/interval-set.h +++ b/fontes/interval-set.h @@ -1,34 +1,34 @@ struct itvl { + itvl(int _a = 0) : a(_a) {} + itvl(int _a, int _b, int _c) : a(_a), b(_b), c(_c) { } int a, b, c; - itvl(int _a, int _b, int _c) - : a(_a), b(_b), c(_c) {} - bool operator<(const itvl& o) const { - return ii(b, a) < ii(o.b, o.a); } - bool operator<(const int& o) const { return b < o; } + bool operator<(const itvl &b) const { return a < b.a; } }; -set<itvl, less<>> si; +set<itvl> si; -void ins_in(itvl in) { //<@\compl{\lg n}@> - auto it = si.lower_bound(in); - int a = in.a, b = in.b, c = in.c; - if (si.size() > 0 && it != begin(si) - && prev(it)->b+1 == a && prev(it)->c == c) { - auto prv = prev(it); int prva = prv->a; - si.erase(prv); a = prva; - } - if (it != end(si) && c == it->c && b+1 == it->a) { - int nxtb = it->b; si.erase(it); b = nxtb; - } - si.insert(itvl(a, b, c)); +void erase_sub(int m) { + auto it = si.lower_bound(m); + if (it == begin(si)) { return; } it--; + if (it->b <= m) { return; } + auto cur = *it; si.erase(it); + si.insert(itvl(cur.a, m, cur.c)); + si.insert(itvl(m, cur.b, cur.c)); } -void upd_color(int a, int b, int c) { //<@\compl{\lg n}@> - auto it = si.lower_bound(b); - if (it != end(si)) { - itvl ori = *it; si.erase(it); - if (ori.a < a) { ins_in(itvl(ori.a, a-1, v)); } - if (ori.b > b) { ins_in(itvl(b+1, ori.b, v)); } - } - ins_in(itvl(a, b, c)); +void erase(int a, int b) { + if (a >= b) return; + erase_sub(a); erase_sub(b); + si.erase(si.lower_bound(a), si.lower_bound(b)); +} + +void upd_color_inclusive(int a, int b, int c) { + erase(a, b+1); si.insert(itvl(a, b+1, c)); +} + +const itvl* get(int i) { + auto it = si.upper_bound(i); + if (it == begin(si)) { return NULL; } it--; + if (!(it->a <= i && i < it->b)) { return NULL; } + return &*it; } diff --git a/fontes/kadane.h b/fontes/kadane.h index eb07582aa05a84f2ff0c04c8e100048a1ad34608..5fe0af5e8630ce4a1254c0b297beacd13f0eda35 100644 --- a/fontes/kadane.h +++ b/fontes/kadane.h @@ -10,4 +10,4 @@ struct kadane { a.ans = max({ l.ans, r.ans, l.suf + r.pre }); return a; } -} +}; diff --git a/fontes/kruskal.h b/fontes/kruskal.h index c0f2bddfaae02977e5b28ef341ea7f8eb41e5965..471b54adc17a1396f974c0a155c60f1340e40ffa 100644 --- a/fontes/kruskal.h +++ b/fontes/kruskal.h @@ -9,7 +9,7 @@ int kruskal(int n) { //<@\compl{m\alpha(n)}@> for (auto [u, v, w] : edges) { if (components == 1) { break; } if (ds_find(u) != ds_find(v)) { - ds_union(u, v); + ds_unite(u, v); components--; sum += w; } diff --git a/fontes/lazy-segment-tree.h b/fontes/lazy-segment-tree.h index 64115a750843cfb923a6f37e4093c8d7a66c0ca0..503fd2b46cbb07f061d68f1803cbe4643f802f91 100644 --- a/fontes/lazy-segment-tree.h +++ b/fontes/lazy-segment-tree.h @@ -7,6 +7,7 @@ void build(vector<int>& src, int n) { //<@\compl{n}@> t[n+i] = src[i]; for (int ti = n-1; ti > 0; ti--) t[ti] = OP(t[2*ti], t[2*ti+1]); + fill(begin(delta), begin(delta)+2*n, dlta()); } ll apply(int ti, dlta d, int sz) { diff --git a/fontes/mo-algorithm.h b/fontes/mo-algorithm.h index 89e3ea60e69f6e189f349cf410ae9beb4fb5c70a..6fc4c21af5418480bddae544c144bf9d88faa9f2 100644 --- a/fontes/mo-algorithm.h +++ b/fontes/mo-algorithm.h @@ -1,4 +1,4 @@ -vector<int> mo(vector<qry> qs) { +vector<int> mo(vector<qry> qs) { //<@\compl{(N+Q)F\sqrt{N}}@> vector<int> ans (qs.size()); sort(all(qs), [](qry a, qry b) { if (a.l/B != b.l/B) { return a.l < b.l; } diff --git a/fontes/sos.h b/fontes/sos.h index 01b394645ec51731532aca2c6214caf5b0b24de7..d672db51d29df399bd31705f8a57670f8c6d3a79 100644 --- a/fontes/sos.h +++ b/fontes/sos.h @@ -3,6 +3,6 @@ vector<ll> sos_dp(vector<ll> f) { assert((1<<n) == f.size()); for (int i = 0; i < n; i++) for (int mask = 0; mask < (1<<n); mask++) - if (mask>>i&1) f[mask] += f[mask^(1<<i)]; + if (mask&(i<<1)) f[mask] += f[mask^(1<<i)]; return f; }