杂项
Fast IO
void read (int &x) {
x = 0; char c = getchar(); bool f = c == '-';
while (!('0' <= c && c <= '9')) c = getchar(), f |= c == '-';
while ('0' <= c && c <= '9') x = (x<<1)+(x<<3)+(c-'0'), c = getchar();
x = f ? -x : x;
}
void write (int x) {
if (x >= 10) write(x / 10);
putchar(x%10+'0');
}
mint
struct mint {
int val;
mint (int x=0) : val(x) {}
inline mint operator + (const mint& x) { return val+x.val >= mod ? val+x.val-mod : val+x.val; }
inline mint operator * (const mint& x) { return 1ll*val*x.val%mod; }
inline mint operator += (const mint& x) { return *this = *this + x; }
friend ostream& operator << (ostream& out, const mint& x) { return out << x.val; }
};
数学
CRT
inline int exgcd (const int &a, const int &b, int &x, int &y) {
if (!b) return x = 1, y = 0, a;
int d = exgcd(b, a % b, y, x);
return y -= a / b * x, d;
}
inline int inv (const int &a, const int &m) {
int x, y, d = exgcd(a, m, x, y);
return (x % m + m) % m;
}
inline int CRT (const int *a, const int *m) {
int M = 1, res = 0;
for (int i = 1; i <= n; i++) M *= m[i];
for (int i = 1; i <= n; i++) {
int Mi = M / m[i];
(res += a[i] * Mi * inv(Mi, m[i])) %= M;
}
return res < 0 ? res + M : res;
}
矩阵
Link
#include <bits/stdc++.h>
using namespace std;
const int SIZE = 105, mod = 1e9 + 7;
struct mint {
int val;
mint (int x = 0) { val = x % mod; }
mint operator + (mint x) { return (1ll*val + x.val) % mod; }
mint operator * (mint x) { return (1ll*val * x.val) % mod; }
mint operator += (mint x) { return *this = *this + x; }
};
struct Array { mint val[SIZE*SIZE]; };
struct Matrix {
int n, m; mint a[SIZE][SIZE];
Matrix (int nn, int mm) {
n = nn, m = mm;
for (int i = 1; i <= n; i++) a[i][i] = 1;
}
Matrix (int nn, int mm, Array aa) {
n = nn, m = mm; int _ = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
a[i][j] = aa.val[_++];
}
Matrix () {
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
a[i][j] = 0;
}
Matrix operator * (Matrix x) {
Matrix res; res.n = n, res.m = x.m;
for (int i = 1; i <= res.n; i++)
for (int j = 1; j <= res.m; j++)
for (int k = 1; k <= m; k++)
res.a[i][j] += a[i][k] * x.a[k][j];
return res;
}
};
Matrix qpow (Matrix a, int b) {
Matrix res(a.n, a.m);
for (; b; b >>= 1, a = a * a)
if (b & 1) res = res * a;
return res;
}
signed main () {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T; cin >> T;
while (T--) {
Matrix a(1, 3, {
1, 1, 1,
});
Matrix b(3, 3, {
0, 0, 1,
1, 0, 0,
0, 1, 1,
});
int n; cin >> n;
if (n <= 3) { cout << "1\n"; continue; }
cout << (a * qpow(b, n-3)).a[1][3].val << '\n';
}
return 0;
}
图论
树
lca
点的距离
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
int n, fa[MAXN][31], dep[MAXN], maxstep;
vector<int> G[MAXN];
void init (int u) {
dep[u] = dep[fa[u][0]] + 1;
for (int i = 1; i <= maxstep; i++)
fa[u][i] = fa[fa[u][i-1]][i-1];
for (int v : G[u]) if (v != fa[u][0])
fa[v][0] = u, init(v);
}
int lca (int x, int y) {
if (dep[x] > dep[y]) swap(x, y);
for (int diff = dep[y] - dep[x], i = 0; diff; diff>>=1, i++)
if (diff & 1) y = fa[y][i];
if (x == y) return x;
for (int i = maxstep; i >= 0 && fa[x][0] != fa[y][0]; i--)
if (fa[x][i] != fa[y][i])
x = fa[x][i], y = fa[y][i];
return fa[x][0];
}
int main () {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n, maxstep = log2(n);
for (int i = 1, u, v; i < n; i++)
cin >> u >> v,
G[u].push_back(v),
G[v].push_back(u);
init(1);
int q; cin >> q;
while (q--) {
int u, v; cin >> u >> v;
int x = lca(u, v);
cout << dep[u] + dep[v] - dep[x] * 2 << '\n';
}
return 0;
}
数据结构
平衡树
非旋 Treap
#include <bits/stdc++.h>
using namespace std;
#define pii pair<int, int>
#define mk(x, y) make_pair(x, y)
const int MAXN = 1e5 + 5;
int _id, rt;
struct node {
int rd, key, siz, ls, rs;
} d[MAXN]; // 空间最多为插入的 n 次
int NewNode (int x) {
return d[++_id] = {rand(), x, 1, 0, 0}, _id;
}
void push_up (int x) { d[x].siz = d[d[x].ls].siz + d[d[x].rs].siz + 1; }
int Merge (int x, int y) { // 必须保证 x 内所有的 key < y 内所有的 key
if (!x || !y) return x | y;
if (d[x].rd < d[y].rd) {
d[x].rs = Merge(d[x].rs, y);
return push_up(x), x;
} else {
d[y].ls = Merge(x, d[y].ls);
return push_up(y), y;
}
}
pii Split_key (int x, int y) { // 按 key 拆
if (!x) return mk(0, 0);
pii res;
if (d[x].key <= y) {
res = Split_key(d[x].rs, y);
d[x].rs = res.first;
res.first = x;
} else {
res = Split_key(d[x].ls, y);
d[x].ls = res.second;
res.second = x;
}
push_up(x);
return res;
}
pii Split_siz (int x, int y) { // 按 siz 拆
if (!x) return mk(0, 0);
if (!y) return mk(0, x);
pii res;
if (d[d[x].ls].siz >= y) {
res = Split_siz(d[x].ls, y);
d[x].ls = res.second;
res.second = x;
} else {
res = Split_siz(d[x].rs, y - d[d[x].ls].siz - 1);
d[x].rs = res.first;
res.first = x;
}
push_up(x);
return res;
}
int Insert (int x, int y) {
pii t = Split_key(x, y);
return Merge(Merge(t.first, NewNode(y)), t.second);
}
int Erase (int x, int y) {
pii t1 = Split_key(x, y), t2 = Split_key(t1.first, y-1);
return Merge(Merge(t2.first, Merge(d[t2.second].ls, d[t2.second].rs)), t1.second);
}
int Query_id (int y) {
pii t = Split_key(rt, y-1);
int res = d[t.first].siz + 1;
rt = Merge(t.first, t.second);
return res;
}
int Query_kth (int x, int y) {
pii t1 = Split_siz(x, y), t2 = Split_siz(t1.first, y-1);
int res = d[t2.second].key;
x = Merge(Merge(t2.first, t2.second), t1.second);
return res;
}
int Query_pre (int y) {
pii t = Split_key(rt, y-1);
int res = Query_kth(t.first, d[t.first].siz);
rt = Merge(t.first, t.second);
return res;
}
int Query_suf (int y) {
pii t = Split_key(rt, y);
int res = Query_kth(t.second, 1);
rt = Merge(t.first, t.second);
return res;
}
void Insert (int x) { rt = Insert(rt, x); }
void Erase (int x) { rt = Erase(rt, x); }
int Query_kth (int x) { return Query_kth(rt, x); }
int main () {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T; cin >> T;
while (T--) {
int opt, x; cin >> opt >> x;
if (opt == 1) Insert(x);
if (opt == 2) Erase(x);
if (opt == 3) cout << Query_id(x) << '\n';
if (opt == 4) cout << Query_kth(x) << '\n';
if (opt == 5) cout << Query_pre(x) << '\n';
if (opt == 6) cout << Query_suf(x) << '\n';
}
return 0;
}