Skip to content

Commit 0b65f27

Browse files
committed
add: 文艺平衡树, 左偏树, 主席树, 树上差分, 树上启发式合并, 重链剖分, 最近公共祖先, 线段树合并, Tarjan
1 parent 13e78aa commit 0b65f27

15 files changed

+825
-1
lines changed

README.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
11
# Templates-in-Competitive-Programming
22

33
自用算法竞赛模板,来源于我自己和网络。
4-
附有 LaTex 生成的 pdf 版本。
4+
5+
由于代码时间跨度较大,来源较多,代码风格存在差异。
6+
7+
附有 LaTex 生成的 pdf 版本,使用 [ply-template](https://github.com/palayutm/ply-template) 模板生成。
58

69
## 数据结构 data structure
710

811
+ 树状数组 (Fenwick Tree.cpp),支持单点修改、前缀和查询
912
+ 并查集 (Disjoint Set Union.cpp),支持查询集合、查询集合大小、合并
1013
+ FHQ Treap (FHQ Treap.cpp),支持插入、删除、按值查询排名、按排名查询值、查询前驱后继
14+
+ 文艺平衡树 (Interval Reverse.cpp),维护区间翻转
1115
+ ST 表 (ST.cpp)
16+
+ 左偏树 (Lefist Tree.cpp),可合并堆
17+
+ 主席树
18+
+ 静态区间第 k 小 (Persistent Segment Tree.cpp)
19+
+ 静态区间颜色数 (Static Interval Color.cpp)
20+
+ 静态区间 mex (Static Interval Mex.cpp)
1221

1322
## 数学 math
1423

@@ -28,6 +37,20 @@
2837
+ Trie (Trie.cpp)
2938
+ 字符串哈希 (String Hash.cpp)
3039

40+
## 图论 graph theory
41+
42+
+ 线段树合并 (Segment Tree Merge.cpp)
43+
+ 树上启发式合并 (Dsu On Tree.cpp)
44+
+ 重链剖分 (Heavy-light Decomposition.cpp)
45+
+ 最近公共祖先
46+
+ 倍增做法 (LCA1.cpp)
47+
+ 重链剖分做法 (LCA2.cpp)
48+
+ 树上差分 (Difference On Tree.cpp)
49+
+ 连通性相关
50+
+ 割点 (Tarjan1.cpp)
51+
+ 点双连通分量 (Tarjan2.cpp)
52+
+ 边双连通分量 (Tarjan3.cpp)
53+
3154
## 杂项 various
3255

3356
+ 取模类 (ModInt.cpp)
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
std::random_device seed;
2+
std::mt19937 rnd(seed());
3+
4+
int n, q;
5+
6+
struct node
7+
{
8+
int sz, key, val, ls, rs, lazy;
9+
}tree[MAXN];
10+
int rt, tot, t1, t2, t3;
11+
12+
int new_node(int v)
13+
{
14+
tree[++tot] = {1, int(rnd()), v, 0, 0, 0};
15+
return tot;
16+
}
17+
18+
void push_up(int u)
19+
{
20+
tree[u].sz = tree[tree[u].ls].sz + tree[tree[u].rs].sz + 1;
21+
}
22+
23+
void push_down(int u)
24+
{
25+
if(tree[u].lazy)
26+
{
27+
std::swap(tree[u].ls, tree[u].rs);
28+
if(tree[u].ls) tree[tree[u].ls].lazy ^= 1;
29+
if(tree[u].rs) tree[tree[u].rs].lazy ^= 1;
30+
tree[u].lazy = 0;
31+
}
32+
}
33+
34+
void split_by_rnk(int u, int k, int &x, int &y)
35+
{
36+
if(!u)
37+
{
38+
x = y = 0;
39+
return;
40+
}
41+
int t = tree[tree[u].ls].sz + 1;
42+
push_down(u);
43+
44+
if(tree[tree[u].ls].sz + 1 <= k)
45+
{
46+
x = u;
47+
split_by_rnk(tree[u].rs, k - tree[tree[u].ls].sz - 1, tree[u].rs, y);
48+
}
49+
else
50+
{
51+
y = u;
52+
split_by_rnk(tree[u].ls, k, x, tree[u].ls);
53+
}
54+
55+
push_up(u);
56+
}
57+
58+
int merge(int x, int y)
59+
{
60+
if(!x || !y) return x + y;
61+
62+
if(tree[x].key > tree[y].key)
63+
{
64+
push_down(x);
65+
tree[x].rs = merge(tree[x].rs, y);
66+
push_up(x);
67+
return x;
68+
}
69+
else
70+
{
71+
push_down(y);
72+
tree[y].ls = merge(x, tree[y].ls);
73+
push_up(y);
74+
return y;
75+
}
76+
}
77+
78+
void dfs(int u)
79+
{
80+
if(!u) return;
81+
push_down(u);
82+
dfs(tree[u].ls);
83+
std::cout << tree[u].val << " ";
84+
dfs(tree[u].rs);
85+
}
86+
87+
void solve()
88+
{
89+
std::cin >> n >> q;
90+
for(int i = 1; i <= n; ++i)
91+
{
92+
rt = merge(rt, new_node(i));
93+
}
94+
95+
while(q--)
96+
{
97+
int l, r;
98+
std::cin >> l >> r;
99+
split_by_rnk(rt, r, t1, t2);
100+
split_by_rnk(t1, l - 1, t1, t3);
101+
tree[t3].lazy ^= 1;
102+
rt = merge(merge(t1, t3), t2);
103+
}
104+
105+
dfs(rt);
106+
}

data structure/Lefist Tree.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
struct node
2+
{
3+
int fa, lt, rt, val, dist;
4+
}ltree[MAXN];
5+
6+
int n, m;
7+
int opt, x, y;
8+
9+
int find(int x)
10+
{
11+
return (fa(x) == x ? x : fa(x) = find(fa(x)));
12+
}
13+
14+
int merge(int x, int y)
15+
{
16+
if(!x | !y) return x | y; // 空结点
17+
18+
if(val(x) > val(y)) swap(x, y);
19+
20+
rs(x) = merge(rs(x), y);
21+
22+
// 维护左偏树性质
23+
if(dist(ls(x)) < dist(rs(x))) swap(ls(x), rs(x));
24+
25+
// 维护dist和并查集
26+
dist(x) = dist(rs(x)) + 1;
27+
fa(ls(x)) = fa(rs(x)) = fa(x) = x;
28+
29+
return x;
30+
}
31+
32+
void pop(int x)
33+
{
34+
val(x) = -1;
35+
fa(ls(x)) = ls(x);
36+
fa(rs(x)) = rs(x);
37+
fa(x) = merge(ls(x), rs(x));
38+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
int n, q, a[MAXN];
2+
int m, b[MAXN];
3+
4+
struct node
5+
{
6+
LL sum, ls, rs;
7+
}tree[MAXN << 5];
8+
LL tot = 0, rt[MAXN];
9+
10+
void build_tree(LL &u, LL l, LL r)
11+
{
12+
u = ++tot;
13+
if(l == r) return;
14+
LL mid = (l + r) >> 1;
15+
build_tree(tree[u].ls, l, mid);
16+
build_tree(tree[u].rs, mid + 1, r);
17+
}
18+
19+
LL clone(LL u)
20+
{
21+
tree[++tot] = tree[u];
22+
return tot;
23+
}
24+
25+
LL modify(LL u, LL l, LL r, LL qp)
26+
{
27+
u = clone(u);
28+
tree[u].sum += 1;
29+
if(l == r) return u;
30+
LL mid = (l + r) >> 1;
31+
if(qp <= mid) tree[u].ls = modify(tree[u].ls, l, mid, qp);
32+
else tree[u].rs = modify(tree[u].rs, mid + 1, r, qp);
33+
return u;
34+
}
35+
36+
LL query(LL u, LL v, LL l, LL r, LL k)
37+
{
38+
if(l == r) return l;
39+
LL x = tree[tree[v].ls].sum - tree[tree[u].ls].sum;
40+
LL res = 0, mid = (l + r) >> 1;
41+
if(x >= k) res = query(tree[u].ls, tree[v].ls, l, mid, k);
42+
else res = query(tree[u].rs, tree[v].rs, mid + 1, r, k - x);
43+
return res;
44+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
int n, a[MAXN], q;
2+
3+
int last[MAXN], nxt[MAXN];
4+
5+
struct node
6+
{
7+
int ls, rs, val;
8+
}tree[MAXN << 5];
9+
int rt[MAXN], tot = 0;
10+
11+
int modify(int u, int l, int r, int x)
12+
{
13+
tree[++tot] = tree[u];
14+
u = tot;
15+
tree[u].val += 1;
16+
17+
if(l == r) return u;
18+
int mid = (l + r) >> 1;
19+
if(x <= mid) tree[u].ls = modify(tree[u].ls, l, mid, x);
20+
else tree[u].rs = modify(tree[u].rs, mid + 1, r, x);
21+
return u;
22+
}
23+
24+
int query(int u, int v, int l, int r, int x)
25+
{
26+
if(l == r) return tree[v].val - tree[u].val;
27+
int mid = (l + r) >> 1;
28+
if(x <= mid) return query(tree[u].ls, tree[v].ls, l, mid, x) + tree[tree[v].rs].val - tree[tree[u].rs].val;
29+
else return query(tree[u].rs, tree[v].rs, mid + 1, r, x);
30+
}
31+
32+
void solve()
33+
{
34+
cin >> n;
35+
for(int i = 1; i <= n; ++i) cin >> a[i];
36+
37+
fill(nxt + 1, nxt + 1 + n, n + 1);
38+
for(int i = 1; i <= n; ++i)
39+
{
40+
if(last[a[i]]) nxt[last[a[i]]] = i;
41+
last[a[i]] = i;
42+
}
43+
44+
for(int i = 1; i <= n; ++i)
45+
{
46+
rt[i] = modify(rt[i - 1], 1, n + 1, nxt[i]);
47+
}
48+
49+
cin >> q;
50+
while(q--)
51+
{
52+
int l, r;
53+
cin >> l >> r;
54+
cout << query(rt[l - 1], rt[r], 1, n + 1, r + 1) << "\n";
55+
}
56+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
int n, m, a[MAXN];
2+
3+
struct node
4+
{
5+
int ls, rs, val;
6+
}tree[MAXN << 5];
7+
int rt[MAXN], tot = 0;
8+
9+
int build_tree(int u, int l, int r)
10+
{
11+
u = ++tot;
12+
if(l == r)
13+
{
14+
tree[u].val = INF;
15+
return u;
16+
}
17+
int mid = (l + r) >> 1;
18+
tree[u].ls = build_tree(tree[u].ls, l, mid);
19+
tree[u].rs = build_tree(tree[u].rs, mid + 1, r);
20+
return u;
21+
}
22+
23+
void push_up(int u)
24+
{
25+
tree[u].val = min(tree[tree[u].ls].val, tree[tree[u].rs].val);
26+
}
27+
28+
int modify(int u, int l, int r, int qp, int k)
29+
{
30+
tree[++tot] = tree[u];
31+
u = tot;
32+
if(l == r)
33+
{
34+
tree[u].val = k;
35+
return u;
36+
}
37+
int mid = (l + r) >> 1;
38+
if(qp <= mid) tree[u].ls = modify(tree[u].ls, l, mid, qp, k);
39+
else tree[u].rs = modify(tree[u].rs, mid + 1, r, qp, k);
40+
push_up(u);
41+
return u;
42+
}
43+
44+
int query(int u, int l, int r, int x)
45+
{
46+
if(l == r) return l;
47+
int mid = (l + r) >> 1;
48+
if(tree[tree[u].ls].val < x) return query(tree[u].ls, l, mid, x);
49+
else return query(tree[u].rs, mid + 1, r, x);
50+
}
51+
52+
void solve()
53+
{
54+
cin >> n >> m;
55+
// rt[0] = build_tree(rt[0], 0, N);
56+
for(int i = 1; i <= n; ++i)
57+
{
58+
cin >> a[i];
59+
rt[i] = modify(rt[i - 1], 0, N, a[i], i);
60+
}
61+
while(m--)
62+
{
63+
int l, r;
64+
cin >> l >> r;
65+
cout << query(rt[r], 0, N, l) << "\n";
66+
}
67+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// 边差分
2+
d[u] += 1, d[v] += 1;
3+
d[lca(u, v)] -= 2;
4+
5+
// 点差分
6+
d[u] += 1, d[v] += 1;
7+
d[lca(u, v)] -= 1;
8+
d[fa[lca(u, v)]] -= 1;

0 commit comments

Comments
 (0)