Team Notebook: Algorithms & Data Structures
Team Notebook: Algorithms & Data Structures
1
Sample Team Name (Sample University Name) 2
t[v] = ts++;
struct Dsu { c[k].push_back(v); node (int x) : l(NULL), r(NULL), val(x) {}
vector<int> p; r[v] = k; node () : l(NULL), r(NULL), val(-1) {}
};
Dsu(int n) { int x = 0, y = -1;
[Link](n); for (int i = 0; i < g[v].size(); ++i) { typedef node* pnode;
for (int i = 0; i < n; i++) { int w = g[v][i];
p[i] = i; if (w != f) { pnode update(pnode cur, int l, int r, int at, int what) {
} if (s[w] > x) { pnode ans = new node();
} x = s[w];
y = w; if (cur != NULL) {
int Find(int x) { return x == p[x] ? x : p[x] = Find(p[x]) } *ans = *cur;
; } } }
} if (l == r) {
int Join(int x, int y) { if (y != -1) { ans-> val = what;
int px = Find(x), py = Find(y); hld(y, v, k); return ans;
if (px == py) return 0; } }
p[px] = py; int m = (l + r) >> 1;
return 1; for (int i = 0; i < g[v].size(); ++i) { if (at <= m) ans-> l = update(ans-> l, l, m, at, what);
} int w = g[v][i]; else ans-> r = update(ans-> r, m + 1, r, at, what);
}; if (w != f && w != y) { return ans;
hld(w, v, w); }
}
} int get(pnode cur, int l, int r, int at) {
3.6 heavy light decomposition } if (cur == NULL) return 0;
if (l == r) return cur-> val;
struct TreeDecomposition { void init(int n) { int m = (l + r) >> 1;
vector<int> g[MAXN], c[MAXN]; for (int i = 0; i < n; ++i) { if (at <= m) return get(cur-> l, l, m, at);
int s[MAXN]; // subtree size g[i].clear(); else return get(cur-> r, m + 1, r, at);
int p[MAXN]; // parent id } }
int r[MAXN]; // chain root id }
int t[MAXN]; // index used in segtree/bit/...
int d[MAXN]; // depht void add(int a, int b) {
int ts; g[a].push_back(b); 3.8 persistent seg tree
g[b].push_back(a);
void dfs(int v, int f) { } /**
p[v] = f; * Problems:
s[v] = 1; void build() { * [Link]
if (f != -1) d[v] = d[f] + 1; ts = 0; *
else d[v] = 0; dfs(0, -1); * Important:
hld(0, 0, 0); * When using lazy propagation remembert to create new
for (int i = 0; i < g[v].size(); ++i) { } * versions for each push_down operation!!!
int w = g[v][i]; }; * */
if (w != f) {
dfs(w, v); struct node {
s[v] += s[w]; node *l, *r;
} 3.7 persistent array long long acc;
} int flip;
} struct node {
node *l, *r; node (int x) : l(NULL), r(NULL), acc(x), flip(0) {}
void hld(int v, int f, int k) { int val; node () : l(NULL), r(NULL), acc(0), flip(0) {}
Sample Team Name (Sample University Name) 7
ans = sum_smaller(cur->child[0], key, id - 1); * If at some point after modifications we need to inspect
} const int MN = 1e5; // limit for array size all the
return ans; * elements in the array, we can push all the modifications
} struct seg_tree { to the
int n; // array size * leaves using the following code. After that we can just
int t[2 * MN]; traverse
// Persistent trie for strings. * elements starting with index n. This way we reduce the
const int MAX_CHILD = 26; seg_tree(int _n) : n(_n) {} complexity
struct node { * from O(n log(n)) to O(n) similarly to using build instead
node *child[MAX_CHILD]; void clear() { of n modifications.
int val; memset(t, 0, sizeof t); * */
node() : val(-1) { }
for (int i = 0; i < MAX_CHILD; i++) { void push() {
child[i] = NULL; void build() { // build the tree for (int i = 1; i < n; ++i) {
} for (int i = n - 1; i > 0; --i) t[i] = t[i<<1] + t[i t[i<<1] += t[i];
} <<1|1]; t[i<<1|1] += t[i];
}; } t[i] = 0;
}
typedef node* pnode; // Single modification, range query. }
void modify(int p, int value) { // set value at position p
pnode copy_node(pnode cur) { for (t[p += n] = value; p > 1; p >>= 1) t[p>>1] = t[p] + // Non commutative combiner functions.
pnode ans = new node(); t[p^1];
if (cur) *ans = *cur; } void modify(int p, const S& value) {
return ans; for (t[p += n] = value; p >>= 1; ) t[p] = combine(t[p<<1],
} int query(int l, int r) { // sum on interval [l, r) t[p<<1|1]);
int res = 0; }
pnode set_val(pnode cur, string &key, int val, int id = 0) { for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
pnode ans = copy_node(cur); if (l&1) res += t[l++]; S query(int l, int r) {
if (id >= int([Link]())) { if (r&1) res += t[--r]; S resl, resr;
ans->val = val; } for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
} else { return res; if (l&1) resl = combine(resl, t[l++]);
int t = key[id] - ’a’; } if (r&1) resr = combine(t[--r], resr);
ans->child[t] = set_val(ans->child[t], key, val, id + 1); }; }
} return combine(resl, resr);
return ans; // Range modification, single query. }
}
void modify(int l, int r, int value) {
pnode get(pnode cur, string &key, int id = 0) { for (l += n, r += n; l < r; l >>= 1, r >>= 1) { /**
if (id >= int([Link]()) || !cur) if (l&1) t[l++] += value; * segment tree for intervals
return cur; if (r&1) t[--r] += value; *
int t = key[id] - ’a’; } * */
return get(cur->child[t], key, id + 1); }
} const int MN = 100000 + 100;
int query(int p) { struct seg_tree {
int res = 0; int val[MN * 4 + 4];
for (p += n; p > 0; p >>= 1) res += t[p]; int pending[MN * 4 + 4];
3.10 segment tree return res;
} seg_tree() {
/** memset(val, -1, sizeof val);
* Taken from: [Link] /** memset(pending, -1, sizeof pending);
* */
Sample Team Name (Sample University Name) 9
left_rot(x), left_rot(x); void clear(){ wavelet *node = new wavelet(lo, hi, mid);
} tree[nodes].c = 0;
} memset(tree[nodes].a, -1, sizeof tree[nodes].a); vector<int> data_l, data_r, ind_l, ind_r;
if (fa == 0) root = x; nodes++; int ls = 0, rs = 0;
} } for (int i = 0; i < int([Link]()); i++) {
int value = data[i];
void insert(T key) { void init(){ if (value <= mid) {
node *cur = root; nodes = 0; data_l.emplace_back(value);
node *pcur = 0; clear(); ind_l.emplace_back(ind[i]);
while (cur) { } ls++;
pcur = cur; } else {
if (key > cur->key) cur = cur->right; int add(const string &s, bool query = 0){ data_r.emplace_back(value);
else cur = cur->left; int cur_node = 0; ind_r.emplace_back(ind[i]);
} for(int i = 0; i < [Link](); ++i){ rs++;
cur = new node(key); int id = gid(s[i]); }
cur->parent = pcur; if(tree[cur_node].a[id] == -1){ node->map_left.emplace_back(ls);
if (!pcur) root = cur; if(query) return 0; node->map_right.emplace_back(rs);
else if (key > pcur->key ) pcur->right = cur; tree[cur_node].a[id] = nodes; node->values.emplace_back(value);
else pcur->left = cur; clear(); node->ori.emplace_back(ind[i]);
splay(cur); } }
} cur_node = tree[cur_node].a[id];
} if (lo < hi) {
node *find(T key) { if(!query) tree[cur_node].c++; node->left = init(data_l, ind_l, lo, mid);
node *cur = root; return tree[cur_node].c; node->right = init(data_r, ind_r, mid + 1, hi);
while (cur) { } }
if (key > cur->key) cur = cur->right; return node;
else if(key < cur->key) cur = cur->left; }; }
else return cur;
} int kth(wavelet *node, int to, int k) {
return 0; // returns the kth element in the sorted version of (a[0],
} 3.14 wavelet tree ..., a[to])
if (node->l == node->r) return node->m;
splay_tree(){ root = 0;}; // this can be tested in the problem: [Link] int c = node->map_left[to];
}; problems/ILKQUERY/ if (k < c)
return kth(node->left, c - 1, k);
struct wavelet { return kth(node->right, node->map_right[to] - 1, k - c);
vector<int> values, ori; }
3.13 trie vector<int> map_left, map_right;
int l, r, m; int pos_kth_ocurrence(wavelet *node, int val, int k) {
const int MN = 26; // size of alphabet wavelet *left, *right; // returns the position on the original array of the kth
const int MS = 100010; // Number of states. wavelet() : left(NULL), right(NULL) {} ocurrence of the value "val"
wavelet(int a, int b, int c) : l(a), r(b), m(c), left(NULL if (!node) return -1;
struct trie{ ), right(NULL) {}
struct node{ }; if (node->l == node->r) {
int c; if (int(node->[Link]()) <= k)
int a[MN]; wavelet *init(vector<int> &data, vector<int> &ind, int lo, return -1;
}; int hi) { return node->ori[k];
if (lo > hi || ([Link]() == 0)) return NULL; }
node tree[MS]; int mid = ((long long)(lo) + hi) / 2;
int nodes; if (lo + 1 == hi) mid = lo; // handle negative values if (val <= node->m)
Sample Team Name (Sample University Name) 11
return pos_kth_ocurrence(node->left, val, k); best = min(best, dist(p[i], p[j])); sort([Link](), [Link](), [](const point &a, const point &b
return pos_kth_ocurrence(node->right, val, k); return best; ) {
} } return a.x < b.x;
});
int ls = ([Link]() + 1) >> 1; vector<point> y([Link](), [Link]());
double l = (p[ls - 1].x + p[ls].x) * 0.5; sort([Link](), [Link](), [](const point &a, const point &b
4 Geometry vector<point> xl(ls), xr([Link]() - ls);
unordered_set<int> left;
) {
return a.y < b.y;
for (int i = 0; i < ls; ++i) { });
4.1 center 2 points + radious xl[i] = x[i]; return cp(p, x, y);
[Link](x[i].id); }
vector<point> find_center(point a, point b, long double r) { }
point d = (a - b) * 0.5; for (int i = ls; i < [Link](); ++i) {
if ([Link](d) > r * r) { xr[i - ls] = x[i];
return vector<point> (); } 4.3 triangles
}
point e = b + d; vector<point> yl, yr; Let a, b, c be length of the three sides of a triangle.
long double fac = sqrt(r * r - [Link](d)); vector<point> pl, pr;
vector<point> ans; [Link](ls); [Link]([Link]() - ls); p = (a + b + c) ∗ 0.5
point x = point(-d.y, d.x); [Link](ls); [Link]([Link]() - ls);
long double l = sqrt([Link](x)); for (int i = 0; i < [Link](); ++i) { The inradius is defined by:
x = x * (fac / l); if ([Link](y[i].id))
ans.push_back(e + x); yl.push_back(y[i]); s
x = point(d.y, -d.x); else (p − a)(p − b)(p − c)
x = x * (fac / l); yr.push_back(y[i]);
iR =
p
ans.push_back(e + x);
return ans; if ([Link](p[i].id)) The radius of its circumcircle is given by the formula:
} pl.push_back(p[i]);
else
pr.push_back(p[i]);
abc
} cR = p
4.2 closest pair problem (a + b + c)(a + b − c)(a + c − b)(b + c − a)
double dl = cp(pl, xl, yl);
struct point { double dr = cp(pr, xr, yr);
double x, y;
int id;
double d = min(dl, dr); 5 Graphs
vector<point> yp; [Link]([Link]());
point() {} for (int i = 0; i < [Link](); ++i) {
point (double a, double b) : x(a), y(b) {} if (fabs(y[i].x - l) < d) 5.1 SCC kosaraju
}; yp.push_back(y[i]);
} struct SCC {
double dist(const point &o, const point &p) { for (int i = 0; i < [Link](); ++i) { vector<vector<int> > g, gr;
double a = p.x - o.x, b = p.y - o.y; for (int j = i + 1; j < [Link]() && j < i + 7; ++j) { vector<bool> used;
return sqrt(a * a + b * b); d = min(d, dist(yp[i], yp[j])); vector<int> order, component;
} } int total_components;
}
double cp(vector<point> &p, vector<point> &x, vector<point> return d; SCC(vector<vector<int> > &adj) {
&y) { } g = adj;
if ([Link]() < 4) { int n = [Link]();
double best = 1e100; double closest_pair(vector<point> &p) { [Link](n);
for (int i = 0; i < [Link](); ++i) vector<point> x([Link](), [Link]()); for (int i = 0; i < n; i++)
for (int j = i + 1; j < [Link](); ++j) for (auto to : g[i])
Sample Team Name (Sample University Name) 12
d[g[u][i].v][k] = min(d[g[u][i].v][k], d[u][k - 1] + g[ void dfs(vector<vector<edge> > &g, int root, int pi = -1)
u][i].w); {
} if (pi == -1) {
L[root] = W[root] = 0;
bool flag = true; V out = {v ∈ V : v has positive out − degree} T[root] = -1;
}
for (int i = 0; i < n && flag; ++i) V in = {v ∈ V : v has positive in − degree} for (int i = 0; i < (int)g[root].size(); ++i) {
if (d[i][n] != INT_MAX) int to = g[root][i].v;
flag = false; E 0 = {(u, v) ∈ V out × V in : (u, v) ∈ E} if (to != pi) {
T[to] = root;
if (flag) { Then it can be shown, via König’s theorem, that G’ W[to] = g[root][i].w;
return true; // return true if there is no a cycle. L[to] = L[root] + 1;
has a matching of size m if and only if there exists n − m
} dfs(g, to, root);
vertex-disjoint paths that cover each vertex in G, where }
double ans = 1e15; n is the number of vertices in G and m is the maximum }
cardinality bipartite mathching in G’. }
for (int u = 0; u + 1 < n; ++u) {
if (d[u][n] == INT_MAX) continue; void init(vector<vector<edge> > &g, int root) {
double W = -1e15; Therefore, the problem can be solved by finding the max- // g is undirected
imum cardinality matching in G’ instead. dfs(g, root);
for (int k = 0; k < n; ++k) NOTE: If the paths are note necesarily disjoints, find int N = [Link](), i, j;
if (d[u][k] != INT_MAX)
W = max(W, (double)(d[u][n] - d[u][k]) / (n - k)); the transitive closure and solve the problem for disjoint for (i = 0; i < N; i++) {
paths. for (j = 0; 1 << j < N; j++) {
ans = min(ans, W); P[i][j] = -1;
} MI[i][j] = inf;
5.9 planar graph (euler) }
// printf("%.2lf\n", ans); }
cout << fixed << setprecision(2) << ans << endl; Euler’s formula states that if a finite, connected, planar
graph is drawn in the plane without any edge intersections, for (i = 0; i < N; i++) {
return false; P[i][0] = T[i];
}
and v is the number of vertices, e is the number of edges MI[i][0] = W[i];
and f is the number of faces (regions bounded by edges, }
including the outer, infinitely large region), then:
for (j = 1; 1 << j < N; j++)
5.7 konig’s theorem for (i = 0; i < N; i++)
f +v =e+2 if (P[i][j - 1] != -1) {
In any bipartite graph, the number of edges in a maximum P[i][j] = P[P[i][j - 1]][j - 1];
matching equals the number of vertices in a minimum vertex It can be extended to non connected planar graphs with MI[i][j] = min(MI[i][j-1], MI[ P[i][j - 1] ][j -
cover c connected components: 1]);
}
}
f +v =e+c+1
5.8 minimum path cover in DAG int query(int p, int q) {
int tmp, log, i;
Given a directed acyclic graph G = (V, E), we are to find 5.10 query with lca
the minimum number of vertex-disjoint paths to cover each int mmin = inf;
vertex in V. struct lowest_ca { if (L[p] < L[q])
0 int T[MN], L[MN], W[MN]; tmp = p, p = q, q = tmp;
We can construct a bipartite graph G = (V out ∪ int P[MN][ML], MI[MN][ML], MA[MN][ML];
V in, E 0 ) from G, where :
Sample Team Name (Sample University Name) 15
while (t--) {
cin >> m >> n; 6.3 cumulative sum of divisors
Sample Team Name (Sample University Name) 17
struct cpx { }
/** double real, image; if (DFT == -1) for (int i = 0; i < len; i++) A[i].real /=
The function SOD(n) (sum of divisors) is defined cpx(double _real, double _image) { len, A[i].image /= len;
as the summation of all the actual divisors of real = _real; for (int i = 0; i < len; i++) a[i] = A[i];
an integer number n. For example, image = _image; return;
} }
SOD(24) = 2+3+4+6+8+12 = 35. cpx(){}
}; cpx in[1 << 20];
The function CSOD(n) (cumulative SOD) of an integer n, is
defined as below: cpx operator + (const cpx &c1, const cpx &c2) { void solve(int n) {
return cpx([Link] + [Link], [Link] + [Link]); memset(d, 0, sizeof d);
csod(n) = \sum_{i = 1}^{n} sod(i) } int t;
for (int i = 0; i < n; ++i) {
It can be computed in O(sqrt(n)): cpx operator - (const cpx &c1, const cpx &c2) { cin >> t;
*/ return cpx([Link] - [Link], [Link] - [Link]); d[t] = true;
} }
long long csod(long long n) { int m;
long long ans = 0; cpx operator * (const cpx &c1, const cpx &c2) { cin >> m;
for (long long i = 2; i * i <= n; ++i) { return cpx([Link]*[Link] - [Link]*[Link], [Link]*c2 vector<int> q(m);
long long j = n / i; .image + [Link]*[Link]); for (int i = 0; i < m; ++i)
ans += (i + j) * (j - i + 1) / 2; } cin >> q[i];
ans += i * (j - i);
} int rev(int id, int len) { for (int i = 0; i < MN; ++i) {
return ans; int ret = 0; if (d[i])
} for (int i = 0; (1 << i) < len; i++) { in[i] = cpx(1, 0);
ret <<= 1; else
if (id & (1 << i)) ret |= 1; in[i] = cpx(0, 0);
} }
6.4 fft return ret;
} FFT(in, MN, 1);
/** for (int i = 0; i < MN; ++i) {
* Fast Fourier Transform. cpx A[1 << 20]; in[i] = in[i] * in[i];
* Useful to compute convolutions. }
* computes: void FFT(cpx *a, int len, int DFT) { FFT(in, MN, -1);
* C(f star g)[n] = sum_m(f[m] * g[n - m]) for (int i = 0; i < len; i++)
* for all n. A[rev(i, len)] = a[i]; int ans = 0;
* test: icpc live archive, 6886 - Golf Bot for (int s = 1; (1 << s) <= len; s++) { for (int i = 0; i < [Link](); ++i) {
* */ int m = (1 << s); if (in[q[i]].real > 0.5 || d[q[i]]) {
cpx wm = cpx(cos( DFT * 2 * PI / m), sin(DFT * 2 * PI / m ans++;
)); }
using namespace std; for(int k = 0; k < len; k += m) { }
#include<bits/stdc++.h> cpx w = cpx(1, 0); cout << ans << endl;
#define D(x) cout << #x " = " << (x) << endl for(int j = 0; j < (m >> 1); j++) { }
#define endl ’\n’ cpx t = w * A[k + j + (m >> 1)];
cpx u = A[k + j]; int main() {
const int MN = 262144 << 1; A[k + j] = u + t; ios_base::sync_with_stdio(false);[Link](NULL);
int d[MN + 10], d2[MN + 10]; A[k + j + (m >> 1)] = u - t; int n;
w = w * wm; while (cin >> n)
} solve(n);
const double PI = acos(-1.0); } return 0;
Sample Team Name (Sample University Name) 18
class Scanner{ public void print(char []c) throws IOException { if (d > p100*3) top100 = true, d -= 3*p100, y += 300;
public BufferedReader reader; [Link](c); else y += ((d-1) / p100) * 100, d = (d-1) % p100 + 1;
public StringTokenizer st; }
public void close() throws IOException { if (d > p4*24) top4 = true, d -= 24*p4, y += 24*4;
public Scanner(InputStream stream){ [Link](); else y += ((d-1) / p4) * 4, d = (d-1) % p4 + 1;
reader = new BufferedReader(new InputStreamReader( }
stream)); if (d > p1*3) top1 = true, d -= p1*3, y += 3;
st = null; } else y += (d-1) / p1, d = (d-1) % p1 + 1;
}
const int *ac = top1 && (!top4 || top100) ? B : A;
public String next(){ for (m = 1; m < 12; ++m) if (d <= ac[m + 1]) break;
while(st == null || ![Link]()){ 8.2 dates d -= ac[m];
try{ }
String line = [Link](); //
if(line == null) return null; // Time - Leap years
st = new StringTokenizer(line); //
}catch (Exception e){
8.3 fraction
throw (new RuntimeException()); // A[i] has the accumulated number of days from months
} previous to i struct frac{
} const int A[13] = { 0, 0, 31, 59, 90, 120, 151, 181, 212, long long x, y;
return [Link](); 243, 273, 304, 334 }; frac(long long a, long long b) {
} // same as A, but for a leap year long long g = __gcd(a, b);
const int B[13] = { 0, 0, 31, 60, 91, 121, 152, 182, 213, x = a / g;
public int nextInt(){ 244, 274, 305, 335 }; y = b / g;
return [Link](next()); // returns number of leap years up to, and including, y }
} int leap_years(int y) { return y / 4 - y / 100 + y / 400; } bool operator < (const frac &o) const {
public long nextLong(){ bool is_leap(int y) { return y % 400 == 0 || (y % 4 == 0 && return (x * o.y < y * o.x);
return [Link](next()); y % 100 != 0); } }
} // number of days in blocks of years };
public double nextDouble(){ const int p400 = 400*365 + leap_years(400);
return [Link](next()); const int p100 = 100*365 + leap_years(100);
} const int p4 = 4*365 + 1; 8.4 io
const int p1 = 365;
Sample Team Name (Sample University Name) 20
/* Returns the convolution of the two given vectors in time long long x1, y1;
// taken from : [Link] proportional to n*log(n). long long d = gcd(b % a, a, x1, y1);
solved/c-e/diablo/[Link] * The number of roots of unity to use nroots_unity must be x = y1 - (b / a) * x1;
// this is very fast as well : [Link] set so that the product of the first y = x1;
code/blob/master/code/[Link] * nroots_unity primes of the vector nth_roots_unity is return d;
greater than the maximum value of the }
typedef unsigned int u32; * convolution. Never use sizes of vectors bigger than 2^24,
#define BUF 524288 if you need to change the values of bool find_any_solution(long long a, long long b, long long c
struct Reader { * the nth roots of unity to appropriate primes for those , long long &x0,
char buf[BUF]; char b; int bi, bz; sizes. long long &y0, long long &g) {
Reader() { bi=bz=0; read(); } */ g = gcd(abs(a), abs(b), x0, y0);
void read() { vector<LL> convolve(const vector<LL> &a, const vector<LL> &b if (c % g) {
if (bi==bz) { bi=0; bz = fread(buf, 1, BUF, stdin); } , int nroots_unity = 2) { return false;
b = bz ? buf[bi++] : 0; } int N = 1 << ceil_log2([Link]() + [Link]()); }
void skip() { while (b > 0 && b <= 32) read(); } vector<LL> ans(N,0), fA(N), fB(N), fC(N);
u32 next_u32() { LL modulo = 1; x0 *= c / g;
u32 v = 0; for (skip(); b > 32; read()) v = v*10 + b-48; for (int times = 0; times < nroots_unity; times++) { y0 *= c / g;
return v; } fill([Link](), [Link](), 0); if (a < 0) x0 = -x0;
int next_int() { fill([Link](), [Link](), 0); if (b < 0) y0 = -y0;
int v = 0; bool s = false; for (int i = 0; i < [Link](); i++) fA[i] = a[i]; return true;
skip(); if (b == ’-’) { s = true; read(); } for (int i = 0; i < [Link](); i++) fB[i] = b[i]; }
for (; 48<=b&&b<=57; read()) v = v*10 + b-48; return s ? LL prime = nth_roots_unity[times].first;
-v : v; } LL inv_modulo = mod_inv(modulo % prime, prime); void shift_solution(long long &x, long long &y, long long a,
char next_char() { skip(); char c = b; read(); return c; } LL normalize = mod_inv(N, prime); long long b,
}; ntfft(fA, 1, nth_roots_unity[times]); long long cnt) {
ntfft(fB, 1, nth_roots_unity[times]); x += cnt * b;
for (int i = 0; i < N; i++) fC[i] = (fA[i] * fB[i]) % y -= cnt * a;
prime; }
ntfft(fC, -1, nth_roots_unity[times]);
9 Number theory for (int i = 0; i < N; i++) { long long find_all_solutions(long long a, long long b, long
LL curr = (fC[i] * normalize) % prime; long c,
LL k = (curr - (ans[i] % prime) + prime) % prime; long long minx, long long maxx, long long miny,
9.1 convolution k = (k * inv_modulo) % prime; long long maxy) {
ans[i] += modulo * k; long long x, y, g;
typedef long long int LL; } if (!find_any_solution(a, b, c, x, y, g)) return 0;
typedef pair<LL, LL> PLL; modulo *= prime; a /= g;
} b /= g;
inline bool is_pow2(LL x) { return ans;
return (x & (x-1)) == 0; } long long sign_a = a > 0 ? +1 : -1;
} long long sign_b = b > 0 ? +1 : -1;
namespace primes {
PLL ext_euclid(LL a, LL b) { const int MP = 100001;
9.9 mod mul if (b == 0) bool sieve[MP];
return make_pair(1,0); long long primes[MP];
// Computes (a * b) % mod pair<LL,LL> rc = ext_euclid(b, a % b); int num_p;
long long mod_mul(long long a, long long b, long long mod) { return make_pair([Link], [Link] - (a / b) * [Link] void fill_sieve() {
long long x = 0, y = a % mod; ); num_p = 0;
while (b > 0) { } sieve[0] = sieve[1] = true;
if (b & 1) for (long long i = 2; i < MP; ++i) {
x = (x + y) % mod; //returns -1 if there is no unique modular inverse if (!sieve[i]) {
y = (y * 2) % mod; LL mod_inv(LL x, LL modulo) { primes[num_p++] = i;
b /= 2; PLL p = ext_euclid(x, modulo); for (long long j = i * i; j < MP; j += i)
} if ( ([Link] * x + [Link] * modulo) != 1 ) sieve[j] = true;
return x % mod; return -1; }
} return ([Link]+modulo) % modulo; }
} }
static int matchPMA(const Node *t, const string &str) { int lmsr() {
int res = 0; string s; SuffixArray(const string &s) : N([Link]()) , s(s), P(1,
for(char c : str) { cin >> s; vector<int> (N, 0)), M(N) {
int a = c - AlphabetBase; int n = [Link](); for (int i = 0; i < N; ++i)
while(t->next[a] == nullptr) s += s; P[0][i] = (int) s[i];
t = t->fail; vector<int> f([Link](), -1);
t = t->next[a]; int k = 0; for (int skip = 1, level = 1; skip < N; skip *= 2, level
res += t->sum; for (int j = 1; j < 2 * n; ++j) { ++) {
} int i = f[j - k - 1]; P.push_back(vector<int>(N, 0));
return res; while (i != -1 && s[j] != s[k + i + 1]) { for (int i = 0 ; i < N; ++i) {
} if (s[j] < s[k + i + 1]) int next = ((i + skip) < N) ? P[level - 1][i + skip]
k = j - i - 1; : -10000;
i = f[i]; M[i] = entry(P[level - 1][i], next, i);
vector<Node> nodes; } }
int nNodes; if (i == -1 && s[j] != s[k + i + 1]) { sort([Link](), [Link]());
vector<String> strings; if (s[j] < s[k + i + 1]) { for (int i = 0; i < N; ++i)
vector<Node*> roots; k = j; P[level][M[i].p] = (i > 0 and M[i].a == M[i - 1].a
vector<int> sizes; } and M[i].b == M[i - 1].b) ? P[level][M[i - 1].p]
vector<Node*> que; f[j - k] = -1; : i;
}; } else { }
f[j - k] = i + 1; }
int main() { }
int m; } vector<int> getSuffixArray(){
while(~scanf("%d", &m)) { return k; vector<int> &rank = [Link]();
IncrementalAhoCorasic iac; } vector<pair<int, int> > inv([Link]());
[Link](600000); for (int i = 0; i < [Link](); ++i)
rep(i, m) { inv[i] = make_pair(rank[i], i);
int ty; sort([Link](), [Link]());
char s[300001]; 10.3 suffix array vector<int> sa([Link]());
scanf("%d%s", &ty, s); for (int i = 0; i < [Link](); ++i)
if(ty == 1) { /** sa[i] = inv[i].second;
[Link](s, +1); * O (n log^2 (n)) return sa;
} else if(ty == 2) { * See [Link] }
[Link](s, -1); for reference
} else if(ty == 3) { * */ // returns the length of the longest common prefix of s[i
int ans = [Link](s); ...L-1] and s[j...L-1]
printf("%d\n", ans); struct entry{ int lcp(int i, int j) {
fflush(stdout); int a, b, p; int len = 0;
} else { entry(){} if (i == j) return N - i;
abort(); entry(int x, int y, int z): a(x), b(y), p(z){} for (int k = [Link]() - 1; k >= 0 && i < N && j < N; --k)
} bool operator < (const entry &o) const { {
} return (a == o.a) ? (b == o.b) ? ( p < o.p) : (b < o.b) : if (P[k][i] == P[k][j]) {
} (a < o.a); i += 1 << k;
return 0; } j += 1 << k;
} }; len += 1 << k;
}
struct SuffixArray{ }
const int N; return len;
10.2 minimal string rotation string s; }
vector<vector<int> > P; };
// Lexicographically minimal string rotation vector<entry> M;
Sample Team Name (Sample University Name) 25