Notebook
Notebook
1
6.7 BIT 2D (Template by Tran Khoi Nguyen) . . . . . . . . . . . . . . . . . . . . . 24
if (flowin != Inf)
University of Engineering and Technology
flowin -= q; if (d[e.v] == d[e.u] + 1)
s[i].c -= q; {
s[i ^ 1].c += q; ll amt = e.cap - e.flow;
if (flowin == 0) if (flow != -1 && amt > flow)
break; amt = flow;
} if (ll pushed = DFS(e.v, T, amt))
return flowout; {
} e.flow += pushed;
void BlockFlow(ll &flow) oe.flow -= pushed;
{ return pushed;
for (int i = 1; i <= n; ++i) }
cur[i] = adj[i].begin(); }
flow += DFS(sink, Inf); }
} return 0;
ll MaxFlow(int s, int t) }
{
this->sink = s; ll MaxFlow(int S, int T)
this->t = t; {
ll flow = 0; ll total = 0;
while (BFS()) while (BFS(S, T))
BlockFlow(flow); {
return flow; fill(pt.begin(), pt.end(), 0);
} while (ll flow = DFS(S, T))
}; total += flow;
}
return total;
}
};
1.2 Dinic (Template by Tran Khoi Nguyen)
struct Edge
{
1.3 Min Cut (Template by Tran Khoi Nguyen)
int u, v;
ll cap, flow;
Edge() {} typedef long long LL;
Edge(int u, int v, ll cap) : u(u), v(v), cap(cap), flow(0) {}
}; struct Edge
{
struct Dinic int u, v;
{ LL cap, flow;
int N; Edge() {}
vector<Edge> E; Edge(int u, int v, LL cap) : u(u), v(v), cap(cap), flow(0) {}
vector<vector<int>> g; };
vector<int> d, pt;
map<ll, map<ll, ll>> mp; bool chk[maxn];
Dinic(int N) : N(N), E(0), g(N), d(N), pt(N) {} vector<pll> mincut;
struct Dinic
void AddEdge(int u, int v, ll cap) {
{ int N;
if (u != v) vector<Edge> E;
{ vector<vector<int>> g;
E.emplace_back(u, v, cap); vector<int> d, pt;
g[u].emplace_back(E.size() - 1);
E.emplace_back(v, u, 0); Dinic(int N) : N(N), E(0), g(N), d(N), pt(N) {}
g[v].emplace_back(E.size() - 1);
} void AddEdge(int u, int v, LL cap)
} {
// cout <<u<<" "<<v<<" "<<cap<<endl;
bool BFS(int S, int T) if (u != v)
{ {
queue<int> q({S}); E.emplace_back(u, v, cap);
fill(d.begin(), d.end(), N + 1); g[u].emplace_back(E.size() - 1);
d[S] = 0; E.emplace_back(v, u, 0);
while (!q.empty()) g[v].emplace_back(E.size() - 1);
{ }
int u = q.front(); }
q.pop();
if (u == T) bool BFS(int S, int T)
break; {
for (int k : g[u]) queue<int> q({S});
{ fill(d.begin(), d.end(), N + 1);
Edge &e = E[k]; d[S] = 0;
if (e.flow < e.cap && d[e.v] > d[e.u] + 1) while (!q.empty())
{ {
d[e.v] = d[e.u] + 1; int u = q.front();
q.emplace(e.v); q.pop();
} if (u == T)
} break;
} for (int k : g[u])
return d[T] != N + 1; {
} Edge &e = E[k];
if (e.flow < e.cap && d[e.v] > d[e.u] + 1)
ll DFS(int u, int T, ll flow = -1) {
{ d[e.v] = d[e.u] + 1;
if (u == T || flow == 0) q.emplace(e.v);
return flow; }
for (int &i = pt[u]; i < g[u].size(); ++i) }
{ }
Edge &e = E[g[u][i]]; return d[T] != N + 1;
2
Edge &oe = E[g[u][i] ^ 1]; }
University of Engineering and Technology
S.reserve(nx);
LL DFS(int u, int T, LL flow = -1) h.resize(ny + 5);
{ adj.resize(nx + 5);
if (u == T || flow == 0) match.resize(ny + 5, NoMatch);
return flow; }
for (int &i = pt[u]; i < g[u].size(); ++i) void Clear()
{ {
Edge &e = E[g[u][i]]; for (int i = 1; i <= nx; ++i)
Edge &oe = E[g[u][i] ^ 1]; adj[i].clear();
if (d[e.v] == d[e.u] + 1) S.clear();
{ fill(match.begin(), match.end(), NoMatch);
LL amt = e.cap - e.flow; }
if (flow != -1 && amt > flow) void AddEdge(int x, int y)
amt = flow; {
if (LL pushed = DFS(e.v, T, amt)) adj[x].emplace_back(y);
{ }
e.flow += pushed; bool BFS()
oe.flow -= pushed; {
return pushed; fill(h.begin(), h.end(), 0);
} queue<int> q;
} for (auto x : S)
} for (auto i : adj[x])
return 0; if (h[i] == 0)
} {
void dfs1(ll u) q.emplace(i);
{ h[i] = 1;
// cout <<u<<endl; }
chk[u] = 1; while (q.size())
for (int k : g[u]) {
{ int x, ypop = q.front();
Edge e = E[k]; q.pop();
if (e.cap - e.flow > 0) if ((x = match[ypop]) == NoMatch)
{ return true;
ll nxt = e.v; for (auto i : adj[x])
if (!chk[nxt]) if (h[i] == 0)
dfs1(nxt); {
} h[i] = h[ypop] + 1;
} q.emplace(i);
} }
void find_mincut(ll S) }
{ return false;
dfs1(S); }
for (int i = 0; i < E.size(); i += 2) void dfs(int v, int lv)
{ {
auto p = E[i]; for (auto i : adj[v])
if (chk[p.u] && !chk[p.v]) if (h[i] == lv + 1)
{ {
mincut.pb(make_pair(p.u, p.v)); if (match[i] == NoMatch)
} found = 1;
} else
} dfs(match[i], lv + 1);
if (found)
LL MaxFlow(int S, int T) {
{ match[i] = v;
LL total = 0; return;
while (BFS(S, T)) }
{ }
fill(pt.begin(), pt.end(), 0); }
while (LL flow = DFS(S, T)) int MaxMatch()
total += flow; {
} int ans(0);
return total; for (int i = 1; i <= nx; ++i)
} S.emplace_back(i);
}; while (BFS())
{
for (int i = S.size() - 1; ~i; --i)
{
found = 0;
1.4 Maximum Matching (HopCroft - Karp) dfs(S[i], 0);
if (found)
{
++ans;
// Trace to find vertex cover and independence set S[i] = S.back();
/* S.pop_back();
Y* = Set of vertices y such that exist an argument path from y to a vertex x which isn’t }
matched }
X* = Set of matched vertices x that x isn’t matched with a vertex in Y* }
return ans;
(X* v Y*) is vertex cover }
*/
};
struct HopCroft_Karp
{
const int NoMatch = -1;
vector<int> h, S, match;
vector<vector<int>> adj;
int nx, ny;
1.5 Maximum Matching (Template by Tran Khoi Nguyen)
bool found;
HopCroft_Karp(int nx = 0, int ny = 0)
{ struct bipartite_graph
this->nx = nx; {
3
this->ny = ny; int nx, ny;
University of Engineering and Technology
vector<vector<int>> gr;
vector<int> match, x_not_matched;
vector<int> level;
1.6 Maximum Matching (O(n2 ))
bool found;
// start from 1
void init(int _nx, int _ny) // O(n^2)
{ struct Maximum_matching
nx = _nx; {
ny = _ny; int nx, ny, t;
gr.assign(nx, vector<int>()); vector<int> Visited, match;
x_not_matched.resize(nx); vector<vector<int>> a;
for (int i = 0; i < nx; ++i)
x_not_matched[i] = i; Maximum_matching(int nx = 0, int ny = 0)
match.assign(ny, -1); {
level.resize(ny); Assign(nx, ny);
} }
int max_matching()
{
1.7 Min Cost Flow
int res = 0;
while (bfs()) struct Edge
{ {
for (int i = sz(x_not_matched) - 1; i >= 0; --i) int u, v;
{ ll c, w;
found = false; Edge(const int &u, const int &v, const ll &c, const ll &w) : u(u), v(v), c(c), w(w) {}
dfs(x_not_matched[i], 0); };
if (found) struct MaxFlowMinCost
{ {
++res; const ll Inf = 1e17;
x_not_matched[i] = x_not_matched.back(); int n, source, sink;
x_not_matched.pop_back(); vector<ll> d;
} vector<int> par;
} vector<bool> inqueue;
} vector<Edge> s;
return res; vector<vector<int>> adj;
} MaxFlowMinCost(int n)
} man; {
this->n = n;
4
s.reserve(n * 2);
University of Engineering and Technology
d.resize(n + 5); inline void amax(T &x, const T &y)
inqueue.resize(n + 5); {
par.resize(n + 5); if (x < y)
adj.resize(n + 5); x = y;
} }
void AddEdge(int u, int v, ll c, ll w) typedef vector<int> VI;
{ typedef ll Flow;
s.emplace_back(u, v, c, w); typedef ll Cost;
adj[u].emplace_back(s.size() - 1); const Flow FLOW_INF = 1LL << 60;
s.emplace_back(v, u, 0, -w); const Cost COST_INF = 1LL << 60;
adj[v].emplace_back(s.size() - 1);
} const int SIZE = 65;
bool SPFA() vector<pair<Cost, int>> B[SIZE];
{ Cost last;
fill(d.begin(), d.end(), Inf); int sz;
fill(par.begin(), par.end(), s.size());
fill(inqueue.begin(), inqueue.end(), 0); int bsr(Cost c)
d[sink] = 0; {
queue<int> q; if (c == 0)
q.emplace(sink); return 0;
inqueue[sink] = 1; return __lg(c) + 1;
while (q.size()) }
{
int c = q.front(); void init()
inqueue[c] = 0; {
q.pop(); last = sz = 0;
for (auto i : adj[c]) REP(i, SIZE)
if (s[i ^ 1].c > 0 && d[s[i].v] > d[c] + s[i ^ 1].w) B[i].clear();
{ }
par[s[i].v] = i ^ 1;
d[s[i].v] = d[c] + s[i ^ 1].w; void push(Cost cst, int v)
if (!inqueue[s[i].v]) {
{ assert(cst >= last);
q.emplace(s[i].v); sz++;
inqueue[s[i].v] = 1; B[bsr(cst ^ last)].emplace_back(cst, v);
} }
}
} pair<Cost, int> pop_min()
return (d[source] < Inf); {
} assert(sz);
pair<ll, ll> MaxFlow(int so, int t, ll k) if (B[0].empty())
{ {
source = so; int k = 1;
sink = t; while (k < SIZE && B[k].empty())
ll Flow(0), cost(0); k++;
while (k && SPFA()) assert(k < SIZE);
{ last = B[k][0].first;
ll q(Inf); EACH(e, B[k])
int v = source; amin(last, e->first);
while (v != sink) EACH(e, B[k])
{ B[bsr(e->first ^ last)].push_back(*e);
q = min(q, s[par[v]].c); B[k].clear();
v = s[par[v]].v; }
} assert(B[0].size());
pair<Cost, int> ret = B[0].back();
q = min(q, k); B[0].pop_back();
sz--;
cost += d[source] * q; return ret;
Flow += q; }
k -= q;
struct MinCostMaxFlow
v = source; {
while (v != sink) struct Edge
{ {
s[par[v]].c -= q; int dst;
s[par[v] ^ 1].c += q; Cost cst;
v = s[par[v]].v; Flow cap;
} int rev;
} };
return {Flow, cost}; typedef vector<vector<Edge>> Graph;
} Graph G;
}; bool negative_edge;
MinCostMaxFlow(int N) : G(N)
{
negative_edge = false;
}
1.8 Min Cost Flow (Template by Tran Khoi Nguyen) void add_edge(int u, int v, Cost x, Flow f)
{
if (u == v)
namespace MIN_COST_MAX_FLOW return;
{ if (x < 0)
negative_edge = true;
#define REP(i, n) for (int i = 0, i##_len = (n); i < i##_len; ++i) G[u].push_back((Edge){
#define EACH(i, c) for (__typeof((c).begin()) i = (c).begin(), i##_end = (c).end(); i != i##_end; ++i) v, x, f, (int)G[v].size()});
template <class T> G[v].push_back((Edge){
inline void amin(T &x, const T &y) u, -x, 0, (int)G[u].size() - 1});
{ }
if (y < x)
x = y; void bellman_ford(int s, vector<Cost> &h)
} {
5
template <class T> fill(h.begin(), h.end(), COST_INF);
University of Engineering and Technology
vector<bool> in(G.size()); }
h[s] = 0; };
in[s] = true; };
VI front, back; using MinCostMaxFlow = MIN_COST_MAX_FLOW::MinCostMaxFlow;
front.push_back(s);
while (1)
{
if (front.empty())
{
if (back.empty())
return;
2 Geometry
swap(front, back);
reverse(front.begin(), front.end());
}
int v = front.back();
2.1 Pick’s Theorem
front.pop_back();
in[v] = false; Given a certain lattice polygon (all its vertices have integer coordinates in some 2D grid) with non-
EACH(e, G[v]) zero area.
if (e->cap)
{ We denote its area by $S$, the number of points with integer coordinates lying strictly inside the
int w = e->dst; polygon by $I$ and the number of points lying on polygon sides by $B$.
if (h[w] > h[v] + e->cst)
{ Then, the Pick’s formula states:
h[w] = h[v] + e->cst;
if (!in[w]) \begin{center}
{ $S=I+ \frac{B}{2} - 1$
back.push_back(w); \end{center}
in[w] = true;
}
}
}
}
}
2.2 Smallest Circle - Emo Welzl (Contain all points)
Flow flow;
Cost cost; #include <bits/stdc++.h>
Flow solve(int s, int t, Flow limit = FLOW_INF) using namespace std;
{ using ld = double;
flow = 0;
cost = 0; typedef pair<ld, ld> point;
vector<Cost> len(G.size()), h(G.size()); typedef pair<point, ld> circle;
if (negative_edge) #define X first
bellman_ford(s, h); #define Y second
6
return flow; T.push_back(a[i]);
University of Engineering and Technology
Result = f(i - 1, T); void DAC(int l, int r)
T.pop_back(); {
} if (r - l <= 3)
return Result; {
} Bruteforce(l, r);
}; return;
}
int main() int mid = (l + r) / 2;
{
cin >> emowelzl::n; DAC(l, mid);
DAC(mid + 1, r);
for (int i = 1; i <= emowelzl::n; ++i)
cin >> emowelzl::a[i].X >> emowelzl::a[i].Y; vector<int> s;
for (int i = l; i <= r; ++i)
cout << emowelzl::f(emowelzl::n, {}).Y * 2; if (sq(a[i].x - a[mid].x) <= ans)
} s.push_back(i);
Brute(s);
}
7
memset(par, -1, sizeof par);
University of Engineering and Technology
} sort(s.begin(), s.end());
s.resize(unique(s.begin(), s.end()) - s.begin());
int findpar(int v) sort(v.begin(), v.end());
{
return par[v] < 0 ? v : par[v] = findpar(par[v]); FenwickTreeMin f(n);
}
for (auto [num1, num2, cost, idx] : v)
bool Merge(int u, int v) {
{ num2 = Find(s, num2);
u = findpar(u);
v = findpar(v); int res = f.Get(num2).second;
if (u == v) if (res != -1)
return false; edges.emplace_back(res, idx, dist(res, idx));
FenwickTreeMin(int n = 0) dsu f;
{
Assign(n); sort(edges.begin(), edges.end());
} vector<pair<int, int>> res;
ll ans(0);
void Assign(int n)
{ for (auto i : edges)
this->n = n; if (f.Merge(i.u, i.v))
fill(a, a + n + 1, make_pair(Inf, -1)); {
} ans += i.w;
res.emplace_back(i.u, i.v);
void Update(int p, pair<ll, int> v) }
{
for (; p <= n; p += p & -p) cout << ans << "\n";
a[p] = min(a[p], v);
} for (auto i : res)
cout << i.first << " " << i.second << "\n";
pair<ll, int> Get(int p) }
{ };
pair<ll, int> ans({Inf, -1});
int32_t main()
for (; p; p -= p & -p) {
ans = min(ans, a[p]); ios_base::sync_with_stdio(0);
return ans; cin.tie(0);
} cout.tie(0);
};
cin >> manhattanMST::n;
struct Edge
{ for (int i = 1; i <= manhattanMST::n; ++i)
int u, v; cin >> manhattanMST::x[i] >> manhattanMST::y[i];
ll w;
Edge(const int &u = 0, const int &v = 0, const ll &w = 0) : u(u), v(v), w(w) {} manhattanMST::calc();
bool operator<(const Edge &a) const }
{
return w < a.w;
}
};
int n;
ll x[N], y[N];
3 Numerical algorithms
vector<Edge> edges;
8
} }
University of Engineering and Technology
ll Pow(ll a, ll b, const ll &mod)
3.2 Rabin Miller - Prime Checker {
ll ans(1);
for (; b; b >>= 1)
{
// There is another version of Rabin Miller using random in the implementation of Pollard Rho
if (b & 1)
ans = Mul(ans, a, mod);
ll mul(ll a, ll b, ll mod)
a = Mul(a, a, mod);
{
}
a %= mod;
b %= mod;
return ans;
ll q = (ld)a * b / mod;
}
ll r = a * b - q * mod;
return (r % mod + mod) % mod;
ll calPhi(ll n)
}
{
ll pow(ll a, ll n, ll m)
ll ans = 1;
{
ll result = 1;
for (ll i = 2; i * i <= n; ++i)
a %= m;
if (n % i == 0)
while (n > 0)
{
{
while (n % i == 0)
if (n & 1)
{
result = mul(result, a, m);
n /= i;
n >>= 1;
ans *= i;
a = mul(a, a, m);
}
}
return result;
ans = ans / i * (i - 1);
}
}
pair<ll, ll> factor(ll n)
{
if (n != 1)
ll s = 0;
ans *= n - 1;
while ((n & 1) == 0)
{
return ans;
s++;
}
n >>= 1;
}
pair<ll, ll> solve(const vector<ll> &a, const vector<ll> &b, vector<ll> phi = {})
return {s, n};
{
}
assert(a.size() == b.size()); // Assume a and b have the same size
bool test(ll s, ll d, ll n, ll witness)
ll m = 1;
{
if (n == witness)
{
return true;
m = 1;
ll p = pow(witness, d, n);
for (auto i : b)
if (p == 1)
m *= i;
return true;
}
for (; s > 0; s--)
{
if (phi.empty())
if (p == n - 1)
{
return true;
for (auto i : b)
p = mul(p, p, n);
phi.emplace_back(calPhi(i));
}
}
return false;
}
ll r = 0;
bool miller(ll n)
{
for (int i = 0; i < (int)b.size(); ++i)
if (n < 2)
r = (r + Mul(Mul(a[i], m / b[i], m), Pow(m / b[i], phi[i] - 1, m), m)) % m;
return false;
if ((n & 1) == 0)
return make_pair(r, m);
return n == 2;
}
ll s, d;
};
tie(s, d) = factor(n - 1);
return test(s, d, n, 2) && test(s, d, n, 3) && test(s, d, n, 5) &&
test(s, d, n, 7) && test(s, d, n, 11) && test(s, d, n, 13) &&
test(s, d, n, 17) && test(s, d, n, 19) && test(s, d, n, 23);
}
3.4 Pollard Rho - Factorialize
// You can change code Rabin-Miller (preposition)
struct PollardRho
3.3 Chinese Remain Theorem {
ll n;
map<ll, int> ans;
using ll = long long; PollardRho(ll n) : n(n) {}
using ld = long double; ll random(ll u)
namespace CRT {
{ return abs(rand()) % u;
// b must contain distinct element }
// x % b_i = a_i ll mul(ll a, ll b, ll mod)
// x % m == (a1 * m2 * m3 * ... * m_k) * [(m2 * m3 * ... * mk) ^ -1 mod m_1] + (a2 * m1 * m3 * ... {
* m_k) / [(m1 * m3 * ... * mk) ^ -1 mod m2] + ... a %= mod;
// Call CRT(a, b, phi) [Default phi is empty] b %= mod;
// return {r, m} that x % m == r ll q = (ld)a * b / mod;
ll r = a * b - q * mod;
// In case of overflow, use this function return (r % mod + mod) % mod;
ll Mul(ll a, ll b, const ll &mod) }
{
ll q = (ld)a * b / mod; ll pow(ll a, ll b, ll m)
ll r = a * b - q * mod; {
ll ans = 1;
return (r % mod + mod) % mod; a %= m;
9
} for (; b; b >>= 1)
University of Engineering and Technology
{ }
if (b & 1) ll p = 0;
ans = mul(ans, a, m);
a = mul(a, a, m); while (p == 0 || p == n)
} p = findfactor(n);
return ans;
} pollard_rho(n / p);
pollard_rho(p);
pair<ll, ll> factor(ll n) }
{ };
ll s = 0;
while ((n & 1) == 0)
{
s++;
}
n >>= 1; 3.5 FFT
return {s, n};
} using cd = complex<double>;
// Rabin - Miller const double PI = acos(-1);
bool miller(ll n) // invert == true means Interpolation
{ // invert == false means dft
if (n < 2) void fft(vector<cd> &a, bool invert)
return 0; {
if (n == 2) int n = a.size();
return 1; for (int i = 1, j = 0; i < n; i++)
ll s = 0, m = n - 1; {
while (m % 2 == 0) int bit = n >> 1;
{ for (; j & bit; bit >>= 1)
s++; j ^= bit;
m >>= 1; j ^= bit;
} if (i < j)
// 1 - 0.9 ^ 40 swap(a[i], a[j]);
for (int it = 1; it <= 40; it++) }
{
ll u = random(n - 2) + 2; for (int len = 2; len <= n; len <<= 1)
ll f = pow(u, m, n); {
if (f == 1 || f == n - 1) double ang = 2 * PI / len * (invert ? -1 : 1);
continue; cd wlen(cos(ang), sin(ang));
for (int i = 1; i < s; i++) for (int i = 0; i < n; i += len)
{ {
f = mul(f, f, n); cd w(1);
if (f == 1) for (int j = 0; j < len / 2; j++)
return 0; {
if (f == n - 1) cd u = a[i + j],
break; v = a[i + j + len / 2] * w;
} a[i + j] = u + v;
if (f != n - 1) a[i + j + len / 2] = u - v;
return 0; w *= wlen;
} }
return 1; }
} }
ll f(ll x, ll n) if (invert)
{ {
return (mul(x, x, n) + 1) % n; for (cd &x : a)
} x /= n;
// Find a factor }
ll findfactor(ll n) }
{
ll x = random(n - 1) + 2;
ll y = x;
ll p = 1;
while (p == 1)
{ 3.6 FFT (Mod 998244353)
x = f(x, n);
y = f(f(y, n), n);
p = __gcd(abs(x - y), n); constexpr int N = 1e5 + 5; // keep N double of n+m
}
return p; // Call init() before call mul()
}
// prime factorization constexpr ll mod = 998244353;
void pollard_rho(ll n)
{ ll Pow(ll a, ll b, ll mod)
if (n <= 1000000) {
{ ll ans(1);
for (int i = 2; i * i <= n; i++) for (; b; b >>= 1)
{ {
while (n % i == 0) if (b & 1)
{ ans = ans * a % mod;
ans[i]++; a = a * a % mod;
n /= i; }
} return ans;
} }
if (n > 1)
ans[n]++; namespace ntt
return; {
} const int N = ::N;
const long long mod = ::mod, rt = 3;
if (miller(n)) ll G[55], iG[55], itwo[55];
{ void add(int &a, int b)
10
ans[n]++; {
return; a += b;
University of Engineering and Technology
if (a >= mod) for (static int k = 2; k < n; k *= 2)
a -= mod; {
} R.resize(n);
void init() rt.resize(n);
{ auto x = polar(1.0L, acos(-1.0L) / k);
int now = (mod - 1) / 2, len = 1, irt = Pow(rt, mod - 2, mod); for (int i = k; i < 2 * k; i++)
while (now % 2 == 0) rt[i] = R[i] = i & 1 ? R[i / 2] * x : R[i / 2];
{ }
G[len] = Pow(rt, now, mod); vector<int> rev(n);
iG[len] = Pow(irt, now, mod); for (int i = 0; i < n; i++)
itwo[len] = Pow(1 << len, mod - 2, mod); rev[i] = (rev[i / 2] | (i & 1) << L) / 2;
now >>= 1;
len++; for (int i = 0; i < n; i++)
} if (i < rev[i])
} swap(a[i], a[rev[i]]);
void dft(ll *x, int n, int fg = 1) // fg=1 for dft, fg=-1 for inverse dft for (int k = 1; k < n; k *= 2)
{ for (int i = 0; i < n; i += 2 * k)
for (int i = (n >> 1), j = 1, k; j < n; ++j) for (int j = 0; j < k; j++)
{ {
if (i < j) // C z = rt[j+k] * a[i+j+k]; // (25% faster if hand-rolled) /// include-line
swap(x[i], x[j]); auto x = (double *)&rt[j + k], y = (double *)&a[i + j + k]; /// exclude-line
for (k = (n >> 1); k & i; i ^= k, k >>= 1) C z(x[0] * y[0] - x[1] * y[1], x[0] * y[1] + x[1] * y[0]); /// exclude-line
; a[i + j + k] = a[i + j] - z;
i ^= k; a[i + j] += z;
} }
for (int m = 2, now = 1; m <= n; m <<= 1, now++) }
{
ll r = fg > 0 ? G[now] : iG[now]; typedef vector<ll> vl;
for (int i = 0, j; i < n; i += m) vl convMod(const vl &a, const vl &b)
{ {
ll tr = 1, u, v;
for (j = i; j < i + (m >> 1); ++j) vl res((int)a.size() + b.size() - 1);
{ int B = 32 - __builtin_clz(res.size()), n = 1 << B, cut = int(sqrt(M));
u = x[j];
v = x[j + (m >> 1)] * tr % mod; vector<C> L(n), R(n), outs(n), outl(n);
x[j] = (u + v) % mod;
x[j + (m >> 1)] = (u + mod - v) % for (int i = 0; i < (int)a.size(); i++)
mod; L[i] = C((int)a[i] / cut, (int)a[i] % cut);
tr = tr * r % mod;
} for (int i = 0; i < (int)b.size(); i++)
} R[i] = C((int)b[i] / cut, (int)b[i] % cut);
}
} fft(L), fft(R);
ll rec(ll n, int k)
{
struct FFTmod if (n <= 1 || k < 0)
{ return 0;
typedef complex<double> C; if (n <= P[k])
const ll M = mod; return n - 1;
void fft(vector<C> &a)
{ if (n < N && ll(P[k]) * P[k] > n)
int n = a.size(), L = 31 - __builtin_clz(n); return n - 1 - prec[n] + prec[P[k]];
11
static vector<complex<long double>> R(2, 1);
static vector<C> rt(2, 1); // (^ 10% faster if double) const int LIM = 250;
University of Engineering and Technology
static int memo[LIM * LIM][LIM]; prf[0] = suf[k + 1] = 1;
bool ok = n < LIM * LIM;
if (ok && memo[n][k]) for (int i = 1; i <= k; i++)
return memo[n][k]; prf[i] = prf[i - 1] * (x - i + mod) % mod;
ll ret = n / P[k] - rec(n / P[k], k - 1) + rec(n, k - 1); for (int i = k; i >= 1; i--)
suf[i] = suf[i + 1] * (x - i + mod) % mod;
if (ok)
memo[n][k] = ret; ll res = 0;
return ret;
} for (int i = 1; i <= k; i++)
void init_count_primes() {
{ if (!((k - i) & 1))
prime[2] = true; res = (res + prf[i - 1] * suf[i + 1] % mod * ifac[i - 1] % mod * ifac[k - i] % mod * a
for (int i = 3; i < N; i += 2) [i]) % mod;
prime[i] = true; else
for (int i = 3, j; i * i < N; i += 2) res = (res - prf[i - 1] * suf[i + 1] % mod * ifac[i - 1] % mod * ifac[k - i] % mod * a
if (prime[i]) [i] % mod + mod) % mod;
for (j = i * i; j < N; j += i + i) }
prime[j] = false;
return res;
for (int i = 1; i < N; ++i) }
if (prime[i]) };
P.push_back(i);
12
ll calc(int x) }
{ }
University of Engineering and Technology
while (n > 1 && a[n - 1] == 0) return 3;
--n; }
} bool operator<(const Bignum &s) const
Bignum &operator+=(const Bignum &x) {
{ return com(s) == 1;
n = max(n, x.n); }
for (int i = 0; i < n; ++i) bool operator>(const Bignum &s) const
a[i] += x.a[i]; {
fix(); return com(s) == 2;
return *this; }
} bool operator==(const Bignum &s) const
Bignum &operator-=(const Bignum &x) {
{ return com(s) == 3;
for (int i = 0; i < x.n; ++i) }
a[i] -= x.a[i]; bool operator<=(const Bignum &s) const
fix(); {
return *this; return com(s) != 2;
} }
Bignum &operator*=(const Bignum &x) bool operator>=(const Bignum &s) const
{ {
vector<ll> c(x.n + n, 0); return com(s) != 1;
for (int i = 0; i < n; ++i) }
for (int j = 0; j < x.n; ++j) void read()
c[i + j] += a[i] * x.a[j]; {
n += x.n; string s;
for (int i = 0; i < n; ++i) cin >> s;
a[i] = c[i]; Convert(s);
fix(); }
return *this; void print()
} {
Bignum &operator/=(const ll &x) int i = n;
{ while (i > 0 && a[i] == 0)
ll r = 0ll; --i;
for (int i = n - 1; i > -1; --i) cout << a[i];
{ for (--i; ~i; --i)
r = r * BASE + a[i]; cout << setw(gd) << setfill(’0’)
a[i] = r / x; << a[i];
r %= x; }
} };
fix();
return *this;
}
Bignum operator+(const Bignum &s)
{
Bignum c; 3.11 Bignum with FFT multiplication
copy(a, a + n, c.a);
c.n = n;
c += s; // Replace function *= in Bignum implementation with below code:
return c; void fft(vector<cd> &a, bool invert)
} {
Bignum operator-(const Bignum &s) int n = a.size();
{ for (int i = 1, j = 0; i < n; i++)
Bignum c; {
copy(a, a + n, c.a); int bit = n >> 1;
c.n = n; for (; j & bit; bit >>= 1)
c -= s; j ^= bit;
return c; j ^= bit;
} if (i < j)
Bignum operator*(const Bignum &s) swap(a[i], a[j]);
{ }
Bignum c; for (int len = 2; len <= n; len <<= 1)
copy(a, a + n, c.a); {
c.n = n; double ang = 2 * PI / len * (invert ? -1 : 1);
c *= s; cd wlen(cos(ang), sin(ang));
return c; for (int i = 0; i < n; i += len)
} {
Bignum operator/(const ll &x) cd w(1);
{ for (int j = 0; j < len / 2; j++)
Bignum c; {
copy(a, a + n, c.a); cd u = a[i + j], v = a[i + j + len / 2] * w;
c.n = n; a[i + j] = u + v;
c /= x; a[i + j + len / 2] = u - v;
return c; w *= wlen;
} }
ll operator%(const ll &x) }
{ }
ll ans(0); if (invert)
for (int i = n - 1; ~i; --i) {
ans = (ans * BASE + a[i]) % x; for (cd &x : a)
return ans; x /= n;
} }
int com(const Bignum &s) const }
{ Bignum &operator*=(const Bignum &x)
if (n < s.n) {
return 1; int m = 1;
if (n > s.n) while (m < n + x.n)
return 2; m <<= 1;
for (int i = n - 1; i > -1; --i) vector<cd> fa(m), fb(m);
if (a[i] > s.a[i]) for (int i = 0; i < m; ++i)
return 2; {
13
else if (a[i] < s.a[i]) fa[i] = a[i];
return 1; fb[i] = x.a[i];
University of Engineering and Technology
} 3.13 Discrete Logarithm (Find x that ax ≡ b (mod m))
fft(fa, false); /// dft
fft(fb, false); /// dft
for (int i = 0; i < m; i++)
fa[i] *= fb[i]; // Returns minimum x for which a ^ x % m = b % m.
fft(fa, true); /// Interpolation // Returns -1 if x isn’t exist
n = m;
for (int i = 0; i < n; ++i) using ll = int;
a[i] = round(fa[i].real());
fix(); ll DiscreteLogarithm(ll a, ll b, ll m)
return *this; {
} a %= m, b %= m;
ll k = 1, add = 0, g;
while ((g = __gcd(a, m)) > 1)
{
if (b == k)
return add;
3.12 Tonelli Shanks (Find square root modulo prime) if (b % g)
return -1;
b /= g, m /= g, ++add;
k = (k * 1ll * a / g) % m;
/* }
Takes as input an odd prime p and n < p and returns r such that r * r = n [mod p].
There’s exist r if and only if n ^ [(p-1) / 2] = 1 (mod p) ll n = sqrt((ld)m) + 1;
*/ ll an = 1;
for (ll i = 0; i < n; ++i)
using ll = int; // Change type of data here an = (an * 1ll * a) % m;
14
while (n % i == 0)
{
University of Engineering and Technology
n /= i; // Sieve up to 10^9 by RR
ans *= i; namespace Sieve
} {
const int MAX = 1000000000LL;
ans = ans / i * (i - 1); const int WHEEL = 3 * 5 * 7 * 11 * 13;
} const int N_SMALL_PRIMES = 6536; // cnt primes less than 2^16
const int SIEVE_SPAN = WHEEL * 64; // one iteration of segmented sieve
if (n != 1) const int SIEVE_SIZE = SIEVE_SPAN / 128 + 1;
ans *= n - 1;
uint64_t ONES[64]; // ONES[i] = 1<<i
return ans; int small_primes[N_SMALL_PRIMES]; // primes less than 2^16
}
// each element of sieve is a 64-bit bitmask.
ll PrimitiveRoot(ll p) // Each bit (0/1) stores whether the corresponding element is a prime number.
{ // We only need to store odd numbers
vector<ll> fact; // -> 1st bitmask stores 3, 5, 7, 9, ...
ll phi = GetPhi(p); uint64_t si[SIEVE_SIZE];
ll n = phi; // for each ’wheel’, we store the sieve pattern (i.e. what numbers cannot be primes)
uint64_t pattern[WHEEL];
for (int i = 2; i * i <= n; ++i)
if (n % i == 0) inline void mark(uint64_t *s, int o) { s[o >> 6] |= ONES[o & 63]; }
{ inline int test(uint64_t *s, int o) { return (s[o >> 6] & ONES[o & 63]) == 0; }
fact.push_back(i);
while (n % i == 0) // update_sieve {{{
n /= i; void update_sieve(int offset)
} {
// copy each wheel pattern to sieve
if (n > 1) for (int i = 0, k; i < SIEVE_SIZE; i += k)
fact.push_back(n); {
k = std::min(WHEEL, SIEVE_SIZE - i);
for (ll res = 2; res <= p; ++res) memcpy(si + i, pattern, sizeof(*pattern) * k);
{ }
bool ok = true;
// Correctly mark 1, 3, 5, 7, 11, 13 as not prime / primes
for (int i = 0; i < fact.size() && ok; ++i) if (offset == 0)
ok &= Pow(res, phi / fact[i], p) != 1; {
si[0] |= ONES[0];
if (ok) si[0] &= ~(ONES[1] | ONES[2] | ONES[3] | ONES[5] | ONES[6]);
return res; }
}
// sieve for primes >= 17 (stored in ‘small_primes‘)
return -1; // can’t find for (int i = 0; i < N_SMALL_PRIMES; ++i)
} {
int j = small_primes[i] * small_primes[i];
if (j > offset + SIEVE_SPAN - 1)
break;
if (j > offset)
3.15 Discrete Root (Find x that xk ≡ a (mod n), n is a prime) else
j = (j - offset) >> 1;
{
j = small_primes[i] - offset % small_primes[i];
/* if ((j & 1) == 0)
Given a prime n and two integers a and k, find all x for which:\ j += small_primes[i];
- x ^ k = a (mod n) j >>= 1;
}
Notice: while (j < SIEVE_SPAN / 2)
- In case k = 2, let’s use Tonelli - Shanks {
- You must insert my implementation of Discrete Logarithm and Primitive Root to run algorithm mark(si, j);
*/ j += small_primes[i];
}
ll Pow(ll a, ll b, ll mod) }
{ }
ll ans(1); // }}}
15
// For primes 3, 5, 7, 11, 13: we initialize wheel pattern..
University of Engineering and Technology
for (int i = 1; i < WHEEL * 64; i += 3) }
mark(pattern, i); if (low[u] == num[u])
for (int i = 2; i < WHEEL * 64; i += 5) {
mark(pattern, i); while (1)
for (int i = 3; i < WHEEL * 64; i += 7) {
mark(pattern, i); int v = stTarjan.back();
for (int i = 5; i < WHEEL * 64; i += 11) stTarjan.pop_back();
mark(pattern, i); root[v] = numComp;
for (int i = 6; i < WHEEL * 64; i += 13) if (u == v)
mark(pattern, i); break;
}
// Segmented sieve numComp++;
long long sum_primes = 2; }
}
for (int offset = 0; offset < MAX; offset += SIEVE_SPAN) bool solve()
{ {
update_sieve(offset); for (int i = 0; i < n; i++)
if (root[i] == -1)
for (uint32_t j = 0; j < SIEVE_SIZE; j++) tarjan(i);
{ for (int i = 0; i < n; i += 2)
uint64_t x = ~si[j]; {
while (x) if (root[i] == root[i ^ 1])
{ return 0;
uint32_t p = offset + (j << 7) + (__builtin_ctzll(x) << 1) + 1; color[i] = (root[i] < root[i ^ 1]);
if (p > offset + SIEVE_SPAN - 1) }
break; return 1;
if (p <= MAX) }
{ };
// p is a prime
}
x ^= (-x & x);
}
}
} 4.2 Eulerian Path
}
}; // Path that goes all edges
// Start from 1
struct EulerianGraph
{
vector<vector<pair<int, int>>> a;
int num_edges;
4 Graph algorithms EulerianGraph(int n)
{
a.resize(n + 1);
4.1 Twosat (2-SAT) }
num_edges = 0;
16
tarjan(v); return path;
low[u] = min(low[u], low[v]); }
University of Engineering and Technology
}; return base;
if (left == right)
return st[id];
dosth(id, left, right);
ll mid = (left + right) / 2;
4.3 Biconnected Component Tree }
return min(get(id * 2, left, mid, x), get(id * 2 + 1, mid + 1, right, x));
ll cntnw = 0;
ll nchain = 1;
ll chainhead[maxn];
// Biconnected Component Tree ll chainid[maxn];
// 1 is the root of Tree ll id[maxn];
// n + i is the node that represent i-th bcc, its depth is even vector<pll> adj[maxn];
ll par1[maxn];
const int N = 3e5 + 5; // Change size to n + number of bcc (For safety, set N >= 2 * n) ll siz[maxn];
int n, nBicon, nTime; void hld(ll u, ll par)
int low[N], num[N]; {
vector<int> adj[N], nadj[N]; if (!chainhead[nchain])
vector<int> s; chainhead[nchain] = u;
cntnw++;
void dfs(int v, int p = -1) chainid[u] = nchain;
{ id[u] = cntnw;
low[v] = num[v] = ++nTime; ll nxt = -1;
s.emplace_back(v); for (auto p : adj[u])
{
for (auto i : adj[v]) ll to = p.ff;
if (i != p) if (to == par)
{ continue;
if (!num[i]) if (nxt == -1 || siz[nxt] < siz[to])
{ {
dfs(i, v); nxt = to;
low[v] = min(low[v], low[i]); }
}
if (low[i] >= num[v]) if (nxt != -1)
{ {
++nBicon; hld(nxt, u);
nadj[v].emplace_back(n + nBicon); }
for (auto p : adj[u])
int vertex; {
do ll to = p.ff;
{ if (to == par || to == nxt)
vertex = s.back(); continue;
s.pop_back(); nchain++;
hld(to, u);
nadj[n + nBicon].emplace_back(vertex); }
} while (vertex != i); }
} void update1(ll u, ll a, ll w)
} {
else ll p = chainid[u];
low[v] = min(low[v], num[i]); ll chk = chainid[a];
} while (1)
} {
if (p == chk)
{
update(1, 1, cntnw, id[a], id[u], w);
break;
4.4 Heavy Light Decomposition (Template by Tran Khoi }
update(1, 1, cntnw, id[chainhead[p]], id[u], w);
Nguyen) u = par1[chainhead[p]];
p = chainid[u];
}
}
ll st[4 * maxn];
ll la[4 * maxn];
void dosth(ll id, ll left, ll right)
{
if (left == right)
return;
4.5 Check Odd Circle With DSU (Template by Tran Khoi
st[id * 2] = min(st[id * 2], la[id]);
st[id * 2 + 1] = min(st[id * 2 + 1], la[id]); Nguyen)
la[id * 2] = min(la[id * 2], la[id]);
la[id * 2 + 1] = min(la[id * 2 + 1], la[id]);
la[id] = base; namespace ufs
} {
void update(ll id, ll left, ll right, ll x, ll y, ll w) struct node
{ {
if (x > right || y < left) int fa, val, size;
return; } t[30];
if (x <= left && y >= right) struct info
{ {
st[id] = min(st[id], w); int x, y;
la[id] = min(la[id], w); node a, b;
return; } st[30];
} inline void pre()
dosth(id, left, right); {
ll mid = (left + right) / 2; for (int i = 1; i <= n; i++)
update(id * 2, left, mid, x, y, w); t[i] = (node){i, 0, 1};
update(id * 2 + 1, mid + 1, right, x, y, w); }
} inline int find(int x)
ll get(ll id, ll left, ll right, ll x) {
17
{ while (t[x].fa != x)
if (x > right || x < left) x = t[x].fa;
University of Engineering and Technology
return x; 5.2 Suffix Array
}
inline int dis(int x)
{ // string and array pos start from 0
int ans = 0; // but array sa and lcp start from 1
while (t[x].fa != x)
ans ^= t[x].val, x = t[x].fa; constexpr int N = 3e5 + 5; // change size to size of string;
return ans;
} struct SuffixArray
inline void link(int x, int y) {
{ string s;
int val = dis(x) ^ dis(y) ^ 1; int n, c[N], p[N], rp[N], lcp[N];
x = find(x);
y = find(y); //p[] : suffix array
if (t[x].size > t[y].size) // lcp[]: lcp array
swap(x, y);
t[x].fa = y; void Assign(const string &x)
t[x].val = val; {
t[y].size += t[x].size; s = x;
} s.push_back(’$’); // Change character here due to range of charater in string
n = s.size();
} Build();
using namespace ufs; s.pop_back();
n = s.size();
}
void Build()
{
5 String vector<int> pn(N), cn(N), cnt(N);
18
University of Engineering and Technology
5.3 Suffix Array (Template by Tran Khoi Nguyen) {
int v = sa[i];
if (v >= 1 && !ls[v - 1])
sa[buf[s[v - 1]]++] = v - 1;
struct suffix_array }
{ copy(sum_l.begin(), sum_l.end(), buf.begin());
vector<int> sa_naive(const vector<int> &s) for (auto i = n - 1; i >= 0; --i)
{ {
int n = (int)s.size(); int v = sa[i];
vector<int> sa(n); if (v >= 1 && ls[v - 1])
iota(sa.begin(), sa.end(), 0); sa[--buf[s[v - 1] + 1]] = v - 1;
sort(sa.begin(), sa.end(), [&](int l, int r) }
{ };
if(l == r) return false; vector<int> lms_map(n + 1, -1);
for(; l < n && r < n; ++ l, ++ r) if(s[l] != s[r]) return s[l] < s[r]; int m = 0;
return l == n; }); for (auto i = 1; i < n; ++i)
return sa; if (!ls[i - 1] && ls[i])
} lms_map[i] = m++;
vector<int> sa_doubling(const vector<int> &s) vector<int> lms;
{ lms.reserve(m);
int n = (int)s.size(); for (auto i = 1; i < n; ++i)
vector<int> sa(n), rank = s, tmp(n); if (!ls[i - 1] && ls[i])
iota(sa.begin(), sa.end(), 0); lms.push_back(i);
for (auto k = 1; k < n; k <<= 1) induce(lms);
{ if (m)
auto cmp = [&](int x, int y) {
{ vector<int> sorted_lms;
if (rank[x] != rank[y]) sorted_lms.reserve(m);
return rank[x] < rank[y]; for (auto v : sa)
int rx = x + k < n ? rank[x + k] : -1; if (lms_map[v] != -1)
int ry = y + k < n ? rank[y + k] : -1; sorted_lms.push_back(v);
return rx < ry; vector<int> rec_s(m);
}; int rec_sigma = 0;
sort(sa.begin(), sa.end(), cmp); rec_s[lms_map[sorted_lms[0]]] = 0;
tmp[sa[0]] = 0; for (auto i = 1; i < m; ++i)
for (auto i = 1; i < n; ++i) {
tmp[sa[i]] = tmp[sa[i - 1]] + (cmp(sa[i - 1], sa[i]) ? 1 : 0); int l = sorted_lms[i - 1], r = sorted_lms[i];
swap(tmp, rank); int end_l = (lms_map[l] + 1 < m) ? lms[lms_map[l] + 1] : n;
} int end_r = (lms_map[r] + 1 < m) ? lms[lms_map[r] + 1] : n;
return sa; bool same = true;
} if (end_l - l != end_r - r)
template <int THRESHOLD_NAIVE = 10, int THRESHOLD_DOUBLING = 40> same = false;
vector<int> sa_is(const vector<int> &s, int sigma) else
{ {
int n = (int)s.size(); for (; l < end_l; ++l, ++r)
if (n == 0) if (s[l] != s[r])
return {}; break;
if (n == 1) if (l == n || s[l] != s[r])
return {0}; same = false;
if (n == 2) }
{ if (!same)
if (s[0] < s[1]) ++rec_sigma;
return {0, 1}; rec_s[lms_map[sorted_lms[i]]] = rec_sigma;
else }
return {1, 0}; auto rec_sa = sa_is<THRESHOLD_NAIVE, THRESHOLD_DOUBLING>(rec_s, rec_sigma + 1);
} for (auto i = 0; i < m; ++i)
if (n < THRESHOLD_NAIVE) sorted_lms[i] = lms[rec_sa[i]];
return sa_naive(s); induce(sorted_lms);
if (n < THRESHOLD_DOUBLING) }
return sa_doubling(s); return sa;
vector<int> sa(n); }
vector<bool> ls(n); int n;
for (auto i = n - 2; i >= 0; --i) // data: sorted sequence of suffices including the empty suffix
ls[i] = (s[i] == s[i + 1]) ? ls[i + 1] : (s[i] < s[i + 1]); // rank[i]: position of the suffix i in the suffix array
vector<int> sum_l(sigma), sum_s(sigma); // lcp[i]: longest common prefix of data[i] and data[i + 1]
for (auto i = 0; i < n; ++i) // index start from 1
{ vector<int> data, rank, lcp;
if (!ls[i]) // O(n + sigma)
++sum_s[s[i]]; suffix_array(const vector<int> &s, int sigma) : n((int)s.size()), rank(n + 1), lcp(n)
else {
++sum_l[s[i] + 1]; assert(0 <= sigma);
} for (auto d : s)
for (auto i = 0; i < sigma; ++i) assert(0 <= d && d < sigma);
{ data = sa_is(s, sigma);
sum_s[i] += sum_l[i]; data.insert(data.begin(), n);
if (i + 1 < sigma) for (auto i = 0; i <= n; ++i)
sum_l[i + 1] += sum_s[i]; rank[data[i]] = i;
} for (auto i = 0, h = 0; i <= n; ++i)
auto induce = [&](const vector<int> &lms) {
{ if (h > 0)
fill(sa.begin(), sa.end(), -1); --h;
vector<int> buf(sigma); if (rank[i] == 0)
copy(sum_s.begin(), sum_s.end(), buf.begin()); continue;
for (auto d : lms) int j = data[rank[i] - 1];
{ for (; j + h <= n && i + h <= n; ++h)
if (d == n) if ((j + h == n) != (i + h == n) || j + h < n && s[j + h] != s[i + h])
continue; break;
sa[buf[s[d]]++] = d; lcp[rank[i] - 1] = h;
} }
copy(sum_l.begin(), sum_l.end(), buf.begin()); }
19
sa[buf[s[n - 1]]++] = n - 1; // O(n log n) time, O(n) space
for (auto i = 0; i < n; ++i) template <class T>
University of Engineering and Technology
suffix_array(const vector<T> &s, bool prepare_lcp) : n((int)s.size()), rank(n + 1), lcp(n) // for convinient a->to[v] = the node x->to[v] that a match x and x->to[v] != NULL
{ // root -> suflink = root
vector<int> idx(n);
iota(idx.begin(), idx.end(), 0); void build()
sort(idx.begin(), idx.end(), [&](int l, int r) {
{ return s[l] < s[r]; }); queue<Node *> Q;
vector<int> s2(n); root->suflink = root;
int now = 0; Q.push(root);
for (auto i = 0; i < n; ++i)
{ while (!Q.empty())
if (i && s[idx[i - 1]] != s[idx[i]]) {
++now; Node *par = Q.front();
s2[idx[i]] = now; Q.pop();
} for (int c = 0; c < ALPHABET_SIZE; ++c)
data = sa_is(s2, now + 1); {
data.insert(data.begin(), n); if (par->to[c])
for (auto i = 0; i <= n; ++i) {
rank[data[i]] = i; par->to[c]->suflink = par == root ? root : par->suflink->to[c];
for (auto i = 0, h = 0; i <= n; ++i) Q.push(par->to[c]);
{ }
if (h > 0) else
--h; {
if (rank[i] == 0) par->to[c] = par == root ? root : par->suflink->to[c];
continue; }
int j = data[rank[i] - 1]; }
for (; j + h <= n && i + h <= n; ++h) }
if ((j + h == n) != (i + h == n) || j + h < n && s[j + h] != s[i + h]) }
break; };
lcp[rank[i] - 1] = h;
}
}
// RMQ must be built over lcp
// O(1)
template <class RMQ>
5.5 Aho Corasick (Template by Tran Khoi Nguyen)
int longest_common_prefix(int i, int j, const RMQ &rmq) const
{
assert(0 <= i && i <= n && 0 <= j && j <= n); struct aho_corasick
return i == j ? n - i : rmq.query(min(rank[i], rank[j]), max(rank[i], rank[j])); {
} struct tk
}; {
ll link;
ll nxt[27];
ll par;
char ch;
5.4 Aho Corasick - Extended KMP ll go[27];
ll val;
ll leaf;
constexpr int ALPHABET_SIZE = 26; tk(ll par = -1, char ch = ’a’) : par(par), ch(ch)
constexpr int firstCharacter = ’a’; {
memset(nxt, -1, sizeof(nxt));
struct Node memset(go, -1, sizeof(go));
{ val = -1;
Node *to[ALPHABET_SIZE]; link = -1;
Node *suflink; leaf = 0;
int ending_length; // 0 if is not ending }
};
Node() vector<tk> vt;
{ void init()
for (int i = 0; i < ALPHABET_SIZE; ++i) {
to[i] = NULL; vt.clear();
suflink = NULL; vt.pb({-1, ’a’});
ending_length = false; }
} ll add(string s, ll val)
}; {
ll nw = 0;
struct AhoCorasick for (auto to : s)
{ {
Node *root; if (vt[nw].nxt[to - ’a’ + 1] == -1)
{
AhoCorasick() vt[nw].nxt[to - ’a’ + 1] = vt.size();
{ vt.pb({nw, to});
root = new Node(); }
} nw = vt[nw].nxt[to - ’a’ + 1];
}
void add(const string &s) vt[nw].leaf = val;
{ return nw;
Node *cur_node = root; }
ll get_val(ll u)
for (char c : s) {
{ if (u == 0)
int v = c - firstCharacter; return 0;
if (vt[u].val == -1)
if (!cur_node->to[v]) {
cur_node->to[v] = new Node(); vt[u].val = vt[u].leaf + get_val(get_link(u));
}
cur_node = cur_node->to[v]; return vt[u].val;
} }
ll go(ll v, ll t)
cur_node->ending_length = s.size(); {
} if (vt[v].go[t] == -1)
20
{
// if a->to[v] == NULL if (vt[v].nxt[t] != -1)
University of Engineering and Technology
{ ll &v = st[node].nxt[edge];
vt[v].go[t] = vt[v].nxt[t]; ll t = s[st[v].f + dis - 1];
} if (v == 0)
else {
{ v = st.size();
if (v == 0) st.emplace_back(node, n - dis, base);
vt[v].go[t] = 0; st[last].link = node;
else last = 0;
vt[v].go[t] = go(get_link(v), t); }
} else if (c == t)
} {
return vt[v].go[t]; st[last].link = node;
} return;
ll get_link(ll v) }
{ else
if (vt[v].link == -1) {
{ ll u = st.size();
if (vt[v].par == 0 || v == 0) st.emplace_back(node, st[v].f, dis - 1);
vt[v].link = 0; st[u].nxt[c] = st.size();
else st.emplace_back(u, n - 1, base);
vt[v].link = go(get_link(vt[v].par), vt[v].ch - ’a’ + 1); st[u].nxt[t] = v;
} st[v].f += (dis - 1);
return vt[v].link; st[v].len -= (dis - 1);
} v = u;
ll get(string s) st[last].link = u;
{ last = u;
ll nw = 0; }
ll ans = 0; if (node == 0)
for (auto to : s) dis--;
{ else
nw = go(nw, to - ’a’ + 1); node = st[node].link;
ans += get_val(nw); }
} }
return ans; };
}
};
5.7 Z Function
5.6 Suffix Tree (Template by Tran Khoi Nguyen)
// string start from 1
// f[i] = longest prefix match with s[i...i + f[i] - 1]
struct tk
{ constexpr int N = 2e5 + 5;
map<ll, ll> nxt;
ll par, f, len; void Build(string &s, int n, int f[N]) // n = size of string, f = z array
ll link; {
tk(ll par = -1, ll f = 0, ll len = 0) : par(par), f(f), len(len) int l(1), r(1);
{
nxt.clear(); f[1] = n;
link = -1;
} for (int i = 2; i <= n; ++i)
}; if (r < i)
{
struct Suffix_Tree l = r = i;
{ while (r <= n && s[r - i + 1] == s[r])
vector<tk> st; ++r;
ll node; f[i] = r - i;
ll dis; --r;
s }
ll n; else if (f[i - l + 1] < r - i + 1)
vector<ll> s; f[i] = f[i - l + 1];
void init() else
{ {
st.clear(); l = i;
node = 0; while (r <= n && s[r - i + 1] == s[r])
dis = 0; ++r;
st.emplace_back(-1, 0, base); f[i] = r - i;
n = 0; --r;
} }
}
void go_edge()
{
while (dis > st[st[node].nxt[s[n - dis]]].len)
{
node = st[node].nxt[s[n - dis]];
dis -= st[node].len; 6 Data structures
}
}
21
go_edge();
ll edge = s[n - dis]; /*
University of Engineering and Technology
order_of_key (k) : Number of items strictly smaller than k. line.pop_back();
find_by_order(k) : K-th element in a set (counting from zero). if (!line.empty())
*/ point.pop_back();
}
else
break;
}
6.2 Fenwick Tree (With Walk on tree) else
{
if (ff(i, line.back()) <= ff(i, line[line.size() - 2]))
{
// This is equivalent to calculating lower_bound on prefix sums array line.pop_back();
// LOGN = log2(N) if (!line.empty())
point.pop_back();
struct FenwickTree }
{ else
int n, LOGN; break;
ll a[N]; // BIT array }
}
FenwickTree()
{ if (line.empty() || A[line.back()] != A[i])
memset(a, 0, sizeof a); {
} if (!line.empty())
point.emplace_back(ff(line.back(), i));
void Update(int p, ll v) line.emplace_back(i);
{ }
for (; p <= n; p += p & -p) }
a[p] += v; ll Get(int x)
} {
int j = lower_bound(point.begin(), point.end(), x) - point.begin();
ll Get(int p) return A[line[j - 1]] * x + B[line[j - 1]];
{ }
ll ans(0); };
return ans;
} 6.4 Dynamic Convex Hull Trick (Min)
int search(ll v)
{
ll sum = 0; struct Line
int pos = 0; {
for (int i = LOGN; i >= 0; i--) mutable ll k, m, p;
{ bool operator<(const Line& o) const
if (pos + (1 << i) <= n && sum + a[pos + (1 << i)] < v) {
{ if (k==o.k) return m>o.m;
sum += a[pos + (1 << i)]; return k > o.k;
pos += (1 << i); }
} bool operator<(ll x) const
} {
return pos + 1; return p < x;
//+1 because pos will be position of largest value less than v }
} };
}; struct LineContainer : multiset<Line, less<>>
{
static const ll inf = LLONG_MAX;
ll div(ll a, ll b)
{
return a / b - ((a ^ b) < 0 && a % b);
6.3 Convex Hull Trick (Min) }
bool isect(iterator x, iterator y)
{
// If you want to get maximum, sort coef (A) not decreasing and change B[line.back()] > B[i] into B[ if (y == end())
line.back()] < B[i] return x->p = inf, 0;
if (x->k == y->k)
struct ConvexHullTrick x->p = x->m < y->m ? inf : -inf;
{ else
vector<ll> A, B; x->p = div(y->m - x->m, x->k - y->k);
vector<int> line; return x->p >= y->p;
vector<ld> point; }
ConvexHullTrick(int n = 0) void add(ll k, ll m)
{ {
A.resize(n + 2, 0); auto z = insert({k, m, 0}), y = z++, x = y;
B.resize(n + 2, 0); while (isect(y, z))
point.emplace_back(-Inf); z = erase(z);
} if (x != begin() && isect(--x, y))
isect(x, y = erase(y));
ld ff(int x, int y) while ((y = x) != begin() && (--x)->p >= y->p)
{ isect(x, erase(y));
return (ld)1.0 * (B[y] - B[x]) / (A[x] - A[y]); }
} ll query(ll x)
{
void Add(int i) assert(!empty());
{ auto l = *lower_bound(x);
while ((int)line.size() > 1 || ((int)line.size() == 1 && A[line.back()] == A[i])) return l.k * x + l.m;
{ }
if (A[line.back()] == A[i]) };
{
22
if (B[line.back()] > B[i])
{
University of Engineering and Technology
6.5 SPlay Tree x = x->R;
}
}
struct KNode return nil;
{ }
int Value;
int Size; void Split(QNode x, int k, QNode &a, QNode &b)
KNode *P, *L, *R; {
}; if (k == 0)
using QNode = KNode *; {
KNode No_thing_here; a = nil;
QNode nil = &No_thing_here, root; b = x;
return;
void Link(QNode par, QNode child, bool Right) }
{ QNode cur = The_kth(x, k);
child->P = par; Up_to_Root(cur);
if (Right) a = cur;
par->R = child; b = a->R;
else a->R = nil;
par->L = child; b->P = nil;
} Update(a);
}
void Update(QNode &a)
{ QNode Join(QNode a, QNode b)
a->Size = a->L->Size + a->R->Size + 1; {
} if (a == nil)
return b;
void Init() while (a->R != nil)
{ a = a->R;
nil->Size = 0; Up_to_Root(a);
nil->P = nil->L = nil->R = nil; Link(a, b, true);
root = nil; Update(a);
for (int i = 1; i <= n; ++i) return a;
{ }
QNode cur = new KNode;
cur->P = cur->L = cur->R = nil; void Print(QNode &a)
cur->Value = i; {
Link(cur, root, false); if (a->L != nil)
root = cur; Print(a->L);
Update(root); cout << (a->Value) << " ";
} if (a->R != nil)
} Print(a->R);
}
void Rotate(QNode x)
{
QNode y = x->P;
QNode z = y->P;
if (x == y->L)
{
6.6 Hashing (Template by Tran Khoi Nguyen)
Link(y, x->R, false);
Link(x, y, true);
} struct Hashing
else {
{ vector<vector<vector<ll>>> f;
Link(y, x->L, true); vector<ll> mod;
Link(x, y, false); vector<vector<ll>> mu;
} vector<ll> chr;
Update(y); ll num;
Update(x); ll base;
x->P = nil; void init()
if (z != nil) {
Link(z, x, z->R == y); num = 2;
} f.clear();
mod.clear();
void Up_to_Root(QNode x) mu.clear();
{ chr.clear();
while (1){ vector<ll> vt = {999244369, 999254351, 999154309, 989154311, 989254411, 997254397, 991294387,
QNode y = x->P; 991814399, 994114351, 994914359, 994024333};
QNode z = y->P; random_shuffle(vt.begin(), vt.end());
if(y == nil) base = 317;
break; for (int i = 1; i <= 26; i++)
if(z != nil){ chr.pb(abs((ll)(rnd())));
if((x == y->L) == (y == z->L)) for (int i = 0; i < num; i++)
Rotate(y); {
else f.emplace_back();
Rotate(x); mod.pb(vt[i]);
} vector<ll> pt;
Rotate(x); pt.pb(1);
} for (int j = 1; j < maxn; j++)
} {
pt.pb((pt.back() * base) % mod[i]);
QNode The_kth(QNode x, int k) }
{ mu.pb(pt);
while (true) }
{ }
if (x->L->Size == k - 1) ll add(string s)
return x; {
if (x->L->Size >= k) ll n = s.length();
x = x->L; ll id = f[0].size();
else for (int j = 0; j < num; j++)
23
{ {
k -= x->L->Size + 1; vector<ll> vt1;
University of Engineering and Technology
vt1.pb(0); void fake_update(ll x, ll y)
for (int i = 1; i <= n; i++) {
{ for (int i = lower_bound(vt.begin(), vt.end(), x) - vt.begin() + 1; i <= vt.size(); i += i &
vt1.pb((vt1.back() * base + chr[s[i - 1] - ’a’]) % mod[j]); (-i))
} {
f[j].pb(vt1); node[i].pb(y);
} }
return id; }
} void fake_get(ll x, ll y)
pll get_hash(ll id, ll l, ll r) {
{ for (int i = lower_bound(vt.begin(), vt.end(), x) - vt.begin() + 1; i; i -= i & (-i))
return make_pair(((f[0][id][r] - f[0][id][l - 1] * mu[0][r - l + 1]) % mod[0] + mod[0]) % mod {
[0], ((f[1][id][r] - f[1][id][l - 1] * mu[1][r - l + 1]) % mod[1] + mod[1]) % mod[1]); node[i].pb(y);
} }
}; }
void update(ll x, ll y, ll val)
{
for (int i = lower_bound(vt.begin(), vt.end(), x) - vt.begin() + 1; i <= vt.size(); i += i &
(-i))
6.7 BIT 2D (Template by Tran Khoi Nguyen) {
for (int j = lower_bound(node[i].begin(), node[i].end(), y) - node[i].begin() + 1; j <=
node[i].size(); j += j & (-j))
{
struct BIT_2D f[i][j] = f[i][j] + val;
{ }
vector<ll> vt; }
vector<vector<ll>> f; }
vector<vector<ll>> node; ll get(ll x, ll y)
void init(vector<ll> vt1) {
{ ll ans = 0;
vt = vt1; for (int i = lower_bound(vt.begin(), vt.end(), x) - vt.begin() + 1; i; i -= i & (-i))
sort(vt.begin(), vt.end()); {
vt.resize(unique(vt.begin(), vt.end()) - vt.begin()); for (int j = lower_bound(node[i].begin(), node[i].end(), y) - node[i].begin() + 1; j; j -=
f = vector<vector<ll>>(vt.size() + 2, vector<ll>(0)); j & (-j))
node = vector<vector<ll>>(vt.size() + 2, vector<ll>(0)); {
} ans += f[i][j];
void rearrange() }
{ }
for (int i = 1; i <= vt.size(); i++) return ans;
{ }
sort(node[i].begin(), node[i].end()); };
node[i].resize(unique(node[i].begin(), node[i].end()) - node[i].begin());
f[i] = vector<ll>(node[i].size() + 2, 0);
}
}
24