几个板子
FHQ Treap#
普通平衡树
struct treap {
int l, r, siz, dat, val;
} tr[N];
int idx, rt;
int get_new(int val) {
tr[++ idx].val = val;
tr[idx].dat = rand();
tr[idx].siz = 1;
return idx;
}
void pushup(int u) {
tr[u].siz = tr[tr[u].l].siz + tr[tr[u].r].siz + 1;
}
void split(int u, int v, int &x, int &y) {
if(!u) x = y = 0;
else {
if(tr[u].val <= v) x = u, split(tr[x].r, v, tr[x].r, y);
else y = u, split(tr[y].l, v, x, tr[y].l);
pushup(u);
}
}
int merge(int x, int y) {
if(!x || !y) return x + y;
if(tr[x].dat < tr[y].dat) {
tr[x].r = merge(tr[x].r, y);
pushup(x);
return x;
}
else {
tr[y].l = merge(x, tr[y].l);
pushup(y);
return y;
}
}
void insert(int val) {
int x, y, z;
split(rt, val, x, y);
z = get_new(val);
rt = merge(merge(x, z), y);
}
void remove(int val) {
int x, y, z;
split(rt, val, x, z);
split(x, val - 1, x, y);
y = merge(tr[y].l, tr[y].r);
rt = merge(merge(x, y), z);
}
int get_rk_by_val(int val) {
int x, y, res;
split(rt, val - 1, x, y);
res = tr[x].siz + 1;
rt = merge(x, y);
return res;
}
int get_val_by_rk(int u, int rk) {
if(rk <= tr[tr[u].l].siz) return get_val_by_rk(tr[u].l, rk);
else if(rk == tr[tr[u].l].siz + 1) return tr[u].val;
return get_val_by_rk(tr[u].r, rk - tr[tr[u].l].siz - 1);
}
int get_pre(int val) {
int x, y, res;
split(rt, val - 1, x, y);
res = get_val_by_rk(x, tr[x].siz);
rt = merge(x, y);
return res;
}
int get_nxt(int val) {
int x, y, res;
split(rt, val, x, y);
res = get_val_by_rk(y, 1);
rt = merge(x, y);
return res;
}
文艺平衡树#
struct Treap {
int l, r, val, dat, siz, tag;
} tr[N];
int idx, rt;
void pushup(int u) {
tr[u].siz = tr[tr[u].l].siz + tr[tr[u].r].siz + 1;
}
void pushdown(int u) {
if(!tr[u].tag) return;
swap(tr[u].l, tr[u].r);
tr[tr[u].l].tag ^= 1;
tr[tr[u].r].tag ^= 1;
tr[u].tag = 0;
}
int get_new(int val) {
tr[++ idx].val = val;
tr[idx].dat = rand();
tr[idx].siz = 1;
return idx;
}
void split(int u, int sz, int &x, int &y) {
if(!u) {
x = y = 0;
return;
}
pushdown(u);
if(tr[tr[u].l].siz < sz) {
x = u;
split(tr[u].r, sz - tr[tr[u].l].siz - 1, tr[x].r, y);
}
else {
y = u;
split(tr[u].l, sz, x, tr[y].l);
}
pushup(u);
}
int merge(int x, int y) {
if(!x || !y) return x + y;
if(tr[x].dat < tr[y].dat) {
pushdown(y);
tr[y].l = merge(x, tr[y].l);
pushup(y);
return y;
}
else {
pushdown(x);
tr[x].r = merge(tr[x].r, y);
pushup(x);
return x;
}
}
void reverse(int l, int r) {
int x, y, z;
split(rt, r, y, z);
split(y, l - 1, x, y);
tr[y].tag ^= 1;
rt = merge(x, merge(y, z));
}
void output(int u) {
if(!u) return;
pushdown(u);
output(tr[u].l);
cout << tr[u].val << ' ';
output(tr[u].r);
}
Treap#
struct treap {
int l, r;
int val, dat;
int cnt, siz;
} tr[N];
int idx, rt;
int get_new(int val) {
tr[++ idx].val = val;
tr[idx].dat = rand();
tr[idx].siz = tr[idx].cnt = 1;
return idx;
}
void pushup(int x) {
tr[x].siz = tr[tr[x].l].siz + tr[tr[x].r].siz + tr[x].cnt;
}
void zig(int &x) {
int y = tr[x].l;
tr[x].l = tr[y].r, tr[y].r = x, x = y;
pushup(tr[x].r), pushup(x);
}
void zag(int &x) {
int y = tr[x].r;
tr[x].r = tr[y].l, tr[y].l = x, x = y;
pushup(tr[x].l), pushup(x);
}
void insert(int &x, int val) {
if(x == 0) {
x = get_new(val);
return;
}
if(val == tr[x].val) {
tr[x].cnt ++, pushup(x);
return;
}
if(val < tr[x].val) {
insert(tr[x].l, val);
if(tr[tr[x].l].dat > tr[x].dat) zig(x);
}
else if(val > tr[x].val) {
insert(tr[x].r, val);
if(tr[tr[x].r].dat > tr[x].dat) zag(x);
}
pushup(x);
}
void remove(int &x, int val) {
if(x == 0) return;
if(tr[x].val == val) {
if(tr[x].cnt > 1) {
tr[x].cnt --;
pushup(x);
return;
}
if(tr[x].l || tr[x].r) {
if(tr[x].r == 0 || tr[tr[x].l].dat > tr[tr[x].r].dat)
zig(x), remove(tr[x].r, val);
else
zag(x), remove(tr[x].l, val);
pushup(x);
}
else x = 0;
return;
}
if(val < tr[x].val) remove(tr[x].l, val);
else remove(tr[x].r, val);
pushup(x);
}
int get_rk_by_val(int x, int val) {
if(x == 0) return 0;
if(val == tr[x].val) return tr[tr[x].l].siz + 1;
if(val < tr[x].val) return get_rk_by_val(tr[x].l, val);
return tr[tr[x].l].siz + tr[x].cnt + get_rk_by_val(tr[x].r, val);
}
int get_val_by_rk(int x, int rk) {
if(x == 0) return INF;
if(tr[tr[x].l].siz >= rk) return get_val_by_rk(tr[x].l, rk);
if(tr[tr[x].l].siz + tr[x].cnt >= rk) return tr[x].val;
return get_val_by_rk(tr[x].r, rk - tr[tr[x].l].siz - tr[x].cnt);
}
int get_pre(int x, int val) {
if(x == 0) return -INF;
if(val <= tr[x].val) return get_pre(tr[x].l, val);
return max(tr[x].val, get_pre(tr[x].r, val));
}
int get_nxt(int x, int val) {
if(x == 0) return INF;
if(val >= tr[x].val) return get_nxt(tr[x].r, val);
return min(tr[x].val, get_nxt(tr[x].l, val));
}
树状数组#
struct BIT {
int n;
vector<int> c;
void init(int N) {
n = N;
c.resize(n + 1);
}
#define lbt(x) x & -x
void modify(int x, int v) {
for(; x <= n; x += lbt(x)) c[x] += v;
}
int query(int x) {
int res = 0;
for(; x; x -= lbt(x)) res += c[x];
return res;
}
} bit;
线段树#
区间修区间查#
struct Tag {
bool empty () {
}
void clear() {
}
};
struct Info {
};
Info operator + (Info lhs, Info rhs) {
}
Info operator + (Info lhs, Tag rhs) {
}
Tag operator +(Tag lhs, Tag rhs) {
}
struct Segment_Tree {
struct Node {
int l, r;
Info val;
Tag tag;
void apply(Tag v) {
val = val + v;
tag = tag + v;
return;
}
#define l(x) tr[x].l
#define r(x) tr[x].r
#define val(x) tr[x].val
#define tag(x) tr[x].tag
} tr[N << 2];
void pushdown(int x) {
if (tag(x).empty()) {
return;
}
tr[x * 2].apply(tag(x)), tr[x * 2 + 1].apply(tag(x));
tag(x).clear();
}
void build(int l, int r, int x) {
tr[x] = {l, r};
tag(x).clear();
if (l == r) {
return;
}
int mid = (l + r) / 2;
build(l, mid, x * 2), build(mid + 1, r, x * 2 + 1);
val(x) = val(x * 2) + val(x * 2 + 1);
}
void update(int l, int r, int x, Tag v) {
if (l <= l(x) && r(x) <= r) {
tr[x].apply(v);
return;
}
pushdown(x);
int mid = (l(x) + r(x)) / 2;
if (l <= mid) {
update(l, r, x * 2, v);
}
if (r > mid) {
update(l, r, x * 2 + 1, v);
}
val(x) = val(x * 2) + val(x * 2 + 1);
}
Info query(int l, int r, int x) {
if (l <= l(x) && r(x) <= r) return val(x);
pushdown(x);
int mid = (l(x) + r(x)) / 2;
if (r <= mid) {
return query(l, r, x * 2);
} else if (l > mid) {
return query(l, r, x * 2 + 1);
} else {
return query(l, r, x * 2) + query(l, r, x * 2 + 1);
}
}
} SegT;
单调修区间查#
struct Tag {
bool empty () {
}
void clear() {
}
};
struct Info {
};
Info operator + (Info lhs, Info rhs) {
}
Info operator + (Info lhs, Tag rhs) {
}
Tag operator +(Tag lhs, Tag rhs) {
}
struct Segment_Tree {
struct Node {
int l, r;
Info val;
#define l(x) tr[x].l
#define r(x) tr[x].r
#define val(x) tr[x].val
#define tag(x) tr[x].tag
} tr[N << 2];
void build(int l, int r, int x) {
tr[x] = {l, r};
tag(x).clear();
if (l == r) {
return;
}
int mid = (l + r) / 2;
build(l, mid, x * 2), build(mid + 1, r, x * 2 + 1);
val(x) = val(x * 2) + val(x * 2 + 1);
}
void update(int p, int x, Info v) {
if (l(x) == r(x)) {
return;
}
pushdown(x);
int mid = (l(x) + r(x)) / 2;
if (l <= mid) {
update(l, r, x * 2, v);
}
if (r > mid) {
update(l, r, x * 2 + 1, v);
}
val(x) = val(x * 2) + val(x * 2 + 1);
}
Info query(int l, int r, int x) {
if (l <= l(x) && r(x) <= r) return val(x);
int mid = (l(x) + r(x)) / 2;
if (r <= mid) {
return query(l, r, x * 2);
} else if (l > mid) {
return query(l, r, x * 2 + 1);
} else {
return query(l, r, x * 2) + query(l, r, x * 2 + 1);
}
}
} SegT;
树链剖分#
void dfs1(int u, int fath) {
fa[u] = fath;
dep[u] = dep[fath] + 1;
siz[u] = 1;
for(auto v : e[u]) {
if(v == fath) continue;
dfs1(v, u);
siz[u] += siz[v];
if(siz[v] > siz[son[u]])
son[u] = v;
}
}
void dfs2(int u, int fst) {
id[u] = ++ idx;
a[idx] = w[u];
top[u] = fst;
if(!son[u]) return;
dfs2(son[u], fst);
for(auto v:e[u]) {
if(v == fa[u] || v == son[u]) continue;
dfs2(v, v);
}
}
快速幂#
int power(int a, int b) {
int res = 1;
for(; b; a = (LL)a * a % mod, b >>= 1) if(b & 1) res = res * a % mod;
return res;
}
ST表#
for(int j = 1; (1 << j) <= n; j ++)
for(int i = 1; i + (1 << j) - 1 <= n; i ++)
f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
dijkstra#
void duijkstra() {
for(int i = 1; i <= n; i ++) dist[i] = INF, st[i] = false;
priority_queue<PII, vector<PII>, greater<PII> > q;
dist[s] = 0;
q.push({0, s});
while(q.size()) {
int u = q.top().se;
q.pop();
if(st[u]) continue;
st[u] = true;
for(int i = h[u]; i; i = nxt[i]) {
int v = to[i], w = val[i];
if(dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
q.push({dist[v], v});
}
}
}
}
加边#
int h[N], nxt[M << 1], to[M << 1], val[M << 1], cnt;
void add(int u, int v, int w) {
to[++ cnt] = v, val[cnt] = w, nxt[cnt] = h[u], h[u] = cnt;
}
int h[N], nxt[M << 1], to[M << 1], cnt;
void add(int u, int v) {
to[++ cnt] = v, nxt[cnt] = h[u], h[u] = cnt;
}
LCA#
void dfs(int u, int fath) {
dep[u] = dep[fath] + 1, fa[u][0] = fath;
for(int i = 1;i <= __lg(dep[u]);i ++) fa[u][i] = fa[fa[u][i - 1]][i - 1];
for(int i = h[u]; i; i = nxt[i])
{
int v = to[i];
if(v == fath) continue;
dfs(v, u);
}
}
int lca(int u, int v)
{
if(dep[u] < dep[v]) swap(u, v);
while(dep[u] > dep[v]) u = fa[u][__lg(dep[u] - dep[v])];
if(u == v) return u;
for(int k = __lg(dep[u]); ~k; k --)
if(fa[u][k] != fa[v][k]) u = fa[u][k], v = fa[v][k];
return fa[u][0];
}
DSU#
int fa[N];
void dsu_clear() {
for(int i = 1;i <= n;i ++) fa[i] = i;
}
int find(int x) {
if(fa[x] == x) return x;
return fa[x] = find(fa[x]);
}
void merge(int x, int y) {
fa[find(x)] = find(y);
}
最小生成树#
sort(e + 1, e + 1 + m);
ll res = 0;
for(int i = 1; i <= m; i ++) {
int u = find(e[i].u), v = find(e[i].v);
if(u == v) continue;
res += e[i].w;
merge(u, v);
}
Floyd#
for(int i = 1; i <= n; i ++) f[i][i] = 0;
for(int k = 1; k <= n; k ++)
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
矩阵快速幂#
struct matrix {
LL c[105][105];
} A;
LL n, k;
matrix operator *(const matrix &a, const matrix &b) {
matrix c;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++) c.c[i][j] = 0;
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= n; j ++)
for(int k = 1; k <= n; k ++)
c.c[i][j] = (c.c[i][j] + a.c[i][k] * b.c[k][j]) % mod;
return c;
}
matrix qpow(matrix a, ll b)
{
matrix res;
for(int i = 1; i <= n; i ++) res.c[i][i] = 1;
for(; b; a = a * a, b >>= 1)if(b & 1) res = res * a;
return res;
}
最大流#
template <class Type>
struct Flow {
int h[N], nxt[M << 1], to[M << 1], cnt;
int S, T;
Type val[M << 1];
int cur[N], d[N];
void init(int _S, int _T) {
S = _S, T = _T, cnt = 1;
}
void add(int u, int v, Type w) {
to[++ cnt] = v, val[cnt] = w, nxt[cnt] = h[u], h[u] = cnt;
to[++ cnt] = u, val[cnt] = 0, nxt[cnt] = h[v], h[v] = cnt;
}
bool bfs() {
memset(d, -1, sizeof d);
d[S] = 0, cur[S] = h[S];
queue<int> q;
q.push(S);
while(q.size()) {
int u = q.front();
q.pop();
for(int i = h[u]; i; i = nxt[i]) {
int v = to[i];
if(d[v] == -1 && val[i]) {
d[v] = d[u] + 1;
cur[v] = h[v];
if(v == T) return true;
q.push(v);
}
}
}
return false;
}
Type dfs(int u, Type lim) {
if(u == T) return lim;
Type flow = 0;
for(int i = cur[u]; i && flow < lim; i = nxt[i]) {
cur[u] = i;
int v = to[i];
if(d[v] == d[u] + 1 && val[i]) {
int t = dfs(v, min(val[i], lim - flow));
if(!t) d[v] = -1;
flow += t, val[i] -= t, val[i ^ 1] += t;
}
}
return flow;
}
Type dinic() {
Type flow, res = 0;
while(bfs()) while(flow = dfs(S, INF)) res += flow;
return res;
}
};
Modint#
template <typename T> T power(T a, ll b) {
T c{1}; for (; b; b /= 2, a *= a) if (b & 1) c *= a;
return c;
}
template <int P> struct MInt {
int x;
MInt() : x{} {}
MInt(ll x_) : x{norm(x_ % getMod())} {}
static int Mod;
static int getMod() { return P > 0 ? P : Mod; }
static void setMod(int Mod_) { Mod = Mod_; }
int up(int x) const {
if (x < 0) x += getMod();
return x;
}
int down(int x) const {
if (x >= getMod()) x -= getMod();
return x;
}
int norm(int x) const {
return up(down(x));
}
int val() const { return x; }
explicit operator int() const { return x; }
MInt operator-() const {
MInt res; res.x = norm(getMod() - x); return res;
}
MInt inv() const {
assert(x != 0);
return power(*this, getMod() - 2);
}
MInt &operator+=(MInt rhs) & { return x = down(x + rhs.x), *this; }
MInt &operator-=(MInt rhs) & { return x = up(x - rhs.x), *this; }
MInt &operator*=(MInt rhs) & { return x = 1ll * x * rhs.x % getMod(), *this; }
MInt &operator/=(MInt rhs) & { return *this *= rhs.inv(); }
friend MInt operator+(MInt lhs, MInt rhs) { return lhs += rhs; }
friend MInt operator-(MInt lhs, MInt rhs) { return lhs -= rhs; }
friend MInt operator*(MInt lhs, MInt rhs) { return lhs *= rhs; }
friend MInt operator/(MInt lhs, MInt rhs) { return lhs /= rhs; }
friend bool operator==(MInt lhs, MInt rhs) { return lhs.val() == rhs.val(); }
friend bool operator!=(MInt lhs, MInt rhs) { return lhs.val() != rhs.val(); }
friend std::istream &operator>>(std::istream &is, MInt &a) {
ll x = 0; is >> x, a = MInt(x); return is;
}
friend std::ostream &operator<<(std::ostream &os, const MInt &a) {
return os << a.val();
}
};
const int P = 1e9 + 7;
using Z = MInt<P>;
Comb#
Z fac[N], infac[N];
void init(int n) {
fac[0] = infac[0] = 1;
for (int i = 1; i <= n; i ++) {
fac[i] = fac[i - 1] * i;
}
infac[n] = (Z)1 / fac[n];
for (int i = n - 1; i >= 1; i --) {
infac[i] = infac[i + 1] * (i + 1);
}
}
Z comb(int a, int b) {
if (a < 0 || b < 0 || a < b) return 0;
return fac[a] * infac[a - b] * infac[b];
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!