算法模板

线段树

普通加带懒标记

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
//左闭右开区间
struct Seg_Tree {
#define lc(p) ((tree[p].ls == -1) ? (tree[p].ls = ++idx) : (tree[p].ls))
#define rc(p) ((tree[p].rs == -1) ? (tree[p].rs = ++idx) : (tree[p].rs))
struct point {
int l, r, ls, rs;
long long sum, lazy;
point() :l(0), r(0), ls(-1), rs(-1), sum(0), lazy(0) {}
point(int ll, int rr, long long ssum, long long lzy) :l(ll), r(rr), ls(-1), rs(-1), sum(ssum), lazy(lzy) {}
}tree[4 * 100000 + 10];
int idx = 1;
void pushdown(int p) {
if (tree[p].lazy) {
tree[lc(p)].sum += (tree[lc(p)].r - tree[lc(p)].l) * tree[p].lazy;
tree[rc(p)].sum += (tree[rc(p)].r - tree[rc(p)].l) * tree[p].lazy;
tree[lc(p)].lazy += tree[p].lazy;
tree[rc(p)].lazy += tree[p].lazy;
tree[p].lazy = 0;
}
}
void pushup(int p) {
tree[p].sum = tree[lc(p)].sum + tree[rc(p)].sum;
}
void add(int p, int l, int r, int k) {
if (tree[p].l >= r || tree[p].r <= l) return;
if (tree[p].l == tree[p].r - 1) {
if (tree[p].lazy) tree[p].lazy = 0;
tree[p].sum += k;
return;
}
if (l <= tree[p].l && tree[p].r <= r) {
tree[p].lazy += k;
pushdown(p);
pushup(p);
return;
}
pushdown(p);
add(lc(p), l, r, k);
add(rc(p), l, r, k);
pushup(p);
}
long long query(int p, int l, int r) {
if (tree[p].l >= r || tree[p].r <= l) return 0;
if (tree[p].l == tree[p].r - 1) {
if (tree[p].lazy) tree[p].lazy = 0;
return tree[p].sum;
}
if (l <= tree[p].l && tree[p].r <= r) return tree[p].sum;
pushdown(p);
long long ans = 1ll * query(lc(p), l, r) + query(rc(p), l, r);
pushup(p);
return ans;
}
void build(int p, int l, int r, const vector<int>& v) {
tree[p].l = l, tree[p].r = r, tree[p].lazy = 0;
if (l == r - 1) {
tree[p] = { l,r,v[l],0 };
return;
}
build(lc(p), l, l + r >> 1, v);
build(rc(p), l + r >> 1, r, v);
pushup(p);
}
void sett(int p, int x, int k) {
if (tree[p].l > x || tree[p].r <= x) return;
if (tree[p].l == tree[p].r - 1 && tree[p].l == x) {
if (tree[p].lazy) tree[p].lazy = 0;
tree[p].sum = k;
return;
}
pushdown(p);
sett(lc(p), x, k);
sett(rc(p), x, k);
pushup(p);
}
void clear(int p, int l, int r) {
tree[p].l = l, tree[p].r = r, tree[p].lazy = 0, tree[p].sum = 0;
if (l == r - 1) return;
clear(lc(p), l, l + r >> 1);
clear(rc(p), l + r >> 1, r);
}
void debug() {
bug(1);
get_a(1);
}
void bug(int x) {
cout << "in node " << x << ' ' << " it's in [" << tree[x].l << ',' << tree[x].r << ") and it's lazy tag is" << tree[x].lazy << " with sum " << tree[x].sum << endl;
if (tree[x].l == tree[x].r - 1) {
cout << "it's the leaf node!" << endl;
return;
}
cout << "begin the node " << x << "'s left child" << endl;
bug(lc(x));
cout << "begin the node " << x << "'s right child" << endl;
bug(rc(x));
cout << "end the node " << x << endl;
}
void get_a(int x) {
if (tree[x].l == tree[x].r - 1) {
cout << tree[x].sum << ' ';
return;
}
bug(lc(x));
bug(rc(x));
}
}t;

template 版无懒标记

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
template<typename Ty = int, typename mode = plus<Ty>, size_t Siz = 1000000>
class Seg_Tree {
#define lc(p) ((tree[p].ls == -1) ? (tree[p].ls = ++idx) : (tree[p].ls))
#define rc(p) ((tree[p].rs == -1) ? (tree[p].rs = ++idx) : (tree[p].rs))
public:
void add(int p, int x, Ty k) {
if (tree[p].l > x || tree[p].r < x) return;
if (tree[p].l == tree[p].r) {
tree[p].sum = merge(tree[p].sum, k);
return;
}
add(lc(p), x, k);
add(rc(p), x, k);
pushup(p);
}
Ty query(int p, int l, int r) {
if (tree[p].l > r || tree[p].r < l) return Ty();
if (l <= tree[p].l && tree[p].r <= r) return tree[p].sum;
return merge(query(lc(p), l, r), query(rc(p), l, r));
}
void build(int p, int l, int r, const vector<Ty>& v) {
tree[p].l = l, tree[p].r = r;
if (l == r) {
tree[p].sum = v[l];
return;
}
build(lc(p), l, l + r >> 1, v);
build(rc(p), (l + r >> 1) + 1, r, v);
pushup(p);
}
void sett(int p, int x, Ty k) {
if (tree[p].l > x || tree[p].r < x) return;
if (tree[p].l == tree[p].r) {
tree[p].sum = k;
return;
}
sett(lc(p), x, k);
sett(rc(p), x, k);
pushup(p);
}
void clear(int p, int l, int r) {
tree[p].l = l, tree[p].r = r, tree[p].sum = Ty();
if (l == r) return;
clear(lc(p), l, l + r >> 1);
clear(rc(p), (l + r >> 1) + 1, r);
pushup(p);
}
protected:
struct point {
int l, r, ls, rs;
Ty sum;
point() :l(0), r(0), ls(-1), rs(-1), sum(Ty()) {}
point(int ll, int rr, Ty ssum) :l(ll), r(rr), ls(-1), rs(-1), sum(ssum) {}
}tree[Siz];
mode merge;
void pushup(int p) {
tree[p].sum = merge(tree[lc(p)].sum, tree[rc(p)].sum);
}
int idx = 1;
};

可合并线段树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
class Seg_Tree {
protected:
struct Node {
int sum;
Node* ls, * rs;
Node() : sum(0), ls(nullptr), rs(nullptr) {}
Node(int val) : sum(val), ls(nullptr), rs(nullptr) {}
};
Node* root; int n;
void pushup(Node* p) {
if (!p) return;
p->sum = 0;
if (p->ls) p->sum += p->ls->sum;
if (p->rs) p->sum += p->rs->sum;
}
void add(Node*& p, int l, int r, int x, int val = 1) {
if (p == nullptr) p = new Node();
if (l == r) {
p->sum += val;
return;
}
int mid = (l + r) >> 1;
if (x <= mid) add(p->ls, l, mid, x, val);
else add(p->rs, mid + 1, r, x, val);
pushup(p);
}
int query(Node*& p, int l, int r, int x, int y) {
if (p == nullptr) return 0;
if (x > r || y < l) return 0;
if (x <= l && r <= y) return p->sum;
int mid = (l + r) >> 1;
return query(p->ls, l, mid, x, y) + query(p->rs, mid + 1, r, x, y);
}
int query(Node*& p, int l, int r, int k) {
if (p == nullptr) return 0;
if (l == r) return l;
int mid = (l + r) >> 1;
if (p->ls && p->ls->sum >= k) return query(p->ls, l, mid, k);
else return query(p->rs, mid + 1, r, k - (p->ls ? p->ls->sum : 0));
}
Node* merge(Node*& p, Node*& q) {
if (p == nullptr) return q;
if (q == nullptr) return p;
Node* r = new Node();
r->sum = p->sum + q->sum;
r->ls = merge(p->ls, q->ls);
r->rs = merge(p->rs, q->rs);
return r;
}
Node* split_idx(Node*& p, int l, int r, int x, int y) {
if (p == nullptr) return nullptr;
if (x > r || y < l) return nullptr;
if (x <= l && r <= y) {
Node* q = new Node();
q->sum = p->sum;
q->ls = p->ls;
q->rs = p->rs;
p->sum = 0;
p->ls = nullptr;
p->rs = nullptr;
return q;
}
int mid = (l + r) >> 1;
Node* q = new Node();
q->ls = split_idx(p->ls, l, mid, x, y);
q->rs = split_idx(p->rs, mid + 1, r, x, y);
q->sum = (q->ls ? q->ls->sum : 0) + (q->rs ? q->rs->sum : 0);
if (q->ls == nullptr && q->rs == nullptr) {
delete q;
return nullptr;
}
p->sum -= q->sum;
if (p->ls == nullptr && p->rs == nullptr) {
delete p;
p = nullptr;
}
return q;
}
Node* split_val(Node*& p, int l, int r, int x, int y) {
if (p == nullptr) return nullptr;
if (x > r || y < l) return nullptr;
if (p->sum == y && x == 1) {
Node* q = new Node();
q->sum = p->sum;
q->ls = p->ls;
q->rs = p->rs;
p->sum = 0;
p->ls = nullptr;
p->rs = nullptr;
return q;
}
int mid = (l + r) >> 1;
Node* q = new Node();
q->ls = split_val(p->ls, l, mid, x, y);
q->rs = split_val(p->rs, mid + 1, r, x, y);
q->sum = (q->ls ? q->ls->sum : 0) + (q->rs ? q->rs->sum : 0);
if (q->ls == nullptr && q->rs == nullptr) {
delete q;
return nullptr;
}
p->sum -= q->sum;
if (p->ls == nullptr && p->rs == nullptr) {
delete p;
p = nullptr;
}
return q;
}
void debug(Node* p, int l, int r) {
if (p == nullptr) return;
if (l == r) {
cerr << l << " " << p->sum << endl;
return;
}
int mid = (l + r) >> 1;
debug(p->ls, l, mid);
debug(p->rs, mid + 1, r);
}
public:
Seg_Tree() : root(nullptr), n(0) {}
int size() {
if (root)
return root->sum;
else
return -1;
}
void build(int n_) {
n = n_;
}
void add(int x, int val = 1) {
add(root, 1, n, x, val);
}
int query(int x, int y) {
return query(root, 1, n, x, y);
}
int query(int k) {
return query(root, 1, n, k);
}
void merge(Seg_Tree& other) {
root = merge(root, other.root);
}
Seg_Tree split_idx(int x, int y) {
Seg_Tree other;
other.root = split_idx(root, 1, n, x, y);
other.n = this->n;
return other;
}
Seg_Tree split_val(int x, int y) {
Seg_Tree other;
other.root = split_val(root, 1, n, x, y);
other.n = this->n;
return other;
}
void debug() {
debug(root, 1, n);
}
};

FHQ Treap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
class FHQ_Treap {
public:
void ins(int x) {
int a, b, c;
split(root, x, a, b);
c = merge(a, new_node(x));
root = merge(c, b);
}
void del(int x) {
int a, b, c, d;
split(root, x, a, b);
split(a, x - 1, c, d);
root = merge(merge(c, merge(tree[d].lc, tree[d].rc)), b);
}
int get_rank(int x) {
int a, b;
split(root, x - 1, a, b);
int ans = tree[a].size + 1;
root = merge(a, b);
return ans;
}
int get_val(int x) {
return tree[val_get(root, x)].val;
}
int get_pre(int x) {
int a, b;
split(root, x - 1, a, b);
int tmp = tree[a].size;
root = merge(a, b);
return get_val(tmp);
}
int get_nxt(int x) {
// cout << "-----------past---------" << endl;
// debug(root);
int a, b;
split(root, x, a, b);
// cout << "-----------now(l)-------" << endl;
// debug(a);
// cout << "-----------now(r)-------" << endl;
// debug(b);
int tmp = tree[a].size + 1;
root = merge(a, b);
// cout << "-----------merged------" << endl;
// debug(root);
// cout << "-----------end---------" << endl;
return get_val(tmp);
}
protected:
int root = 0, idx = 0;
struct Point {
int lc, rc, size, val, rnd;
Point() :lc(0), rc(0), size(0), val(0), rnd(114514) {}
}tree[100000 + 100];
int new_node(int val) {
++idx;
tree[idx].rnd = rand();
tree[idx].val = val;
tree[idx].size = 1;
return idx;
}
void push_up(int p) {
tree[p].size = tree[tree[p].lc].size + tree[tree[p].rc].size + 1;
}
void split(int p, int val, int& x, int& y) {
if (!p) {
x = y = 0;
return;
}
if (tree[p].val <= val) {
x = p;
split(tree[p].rc, val, tree[p].rc, y);
push_up(p);
}
else {
y = p;
split(tree[p].lc, val, x, tree[p].lc);
push_up(p);
}
}
int merge(int x, int y) {
if (!x || !y) return x + y;
if (tree[x].rnd < tree[y].rnd) {
tree[x].rc = merge(tree[x].rc, y);
push_up(x); return x;
}
else {
tree[y].lc = merge(x, tree[y].lc);
push_up(y); return y;
}
}
int val_get(int p, int x) {
if (tree[tree[p].lc].size + 1 == x) return p;
if (x <= tree[tree[p].lc].size)
return val_get(tree[p].lc, x);
return val_get(tree[p].rc, x - (tree[tree[p].lc].size + 1));
}
void debug(int p) {
if (!p) {
cout << "it's empty!" << endl;
return;
}
cout << "begin " << p << endl;
cout << p << "'s left child :" << endl;
debug(tree[p].lc);
cout << p << "'s right child :" << endl;
debug(tree[p].rc);
cout << "end " << p << endl;
}
};

Splay

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
class Splay {
#define lc child[0]
#define rc child[1]
public:
void ins(int x) {
if (!root) {
new_node<1>(x, 0);
return;
}
int now = root, fa = 0;
while (1) {
if (x == tree[now].val) {
tree[now].cnt++;
push_up(now);
push_up(fa);
splay(now);
return;
}
fa = now;
now = tree[now].child[tree[now].val < x];
if (!now) {
if (tree[fa].val < x) new_node<1>(x, fa);
else new_node<0>(x, fa);
push_up(fa);
splay(idx);
return;
}
}
}
void del(int x) {
ins(x);
tree[root].cnt--;
if (tree[root].cnt > 1) {
tree[root].cnt--;
push_up(root);
return;
}
if (!tree[root].lc && !tree[root].rc) {
tree[root] = Point();
root = 0;
return;
}
if (!tree[root].lc) {
int Tmp = root;
root = tree[root].rc;
tree[root].fa = 0;
tree[Tmp] = Point();
return;
}
else if (!tree[root].rc) {
int Tmp = root;
root = tree[root].lc;
tree[root].fa = 0;
tree[Tmp] = Point();
return;
}
int L = find(0), R = find(1);
splay(L);
splay(R, L);
tree[tree[root].rc].lc=0;
push_up(tree[root].rc);
push_up(root);
}
int get_rank(int x) {
ins(x);
int ans = tree[tree[root].lc].size;
// cout<<tree[find(0, find(0))].val<<' '<<tree[find(0)].val<<' '<<tree[root].val<<' '<<tree[find(1)].val<<endl;
del(x);
return ans + 1;
}
int get_val(int x) {
int now = root;
while (1) {
if (tree[now].lc && x <= tree[tree[now].lc].size)
now = tree[now].lc;
else {
int tmp = tree[now].cnt + tree[tree[now].lc].size;
if (x <= tmp) {
splay(now);
return tree[now].val;
}
x -= tmp;
now = tree[now].rc;
}
}
}
int get_pre(int x) {
ins(x);
int tmp = find(0);
splay(tmp);
int ans = tree[tmp].val;
del(x);
return ans;
}
int get_nxt(int x) {
ins(x);
int tmp = find(1);
splay(tmp);
int ans = tree[tmp].val;
del(x);
return ans;
}
protected:
struct Point {
int child[2], size, val, fa, cnt;
Point() :child{ 0,0 }, size(0), val(0), fa(0), cnt(0) {}
}tree[100000 + 100];
int idx = 0, root = 0;
template<bool lrc = 0>
int new_node(int x, int fa) {
if (!fa) {
++idx;
tree[idx].fa = tree[idx].lc = tree[idx].rc = 0;
root = idx;
tree[idx].val = x;
tree[idx].cnt = tree[idx].size = 1;
return idx;
}
++idx;
tree[idx].fa = fa;
tree[idx].size = 1;
tree[idx].val = x;
if (lrc)
tree[fa].rc = idx;
else
tree[fa].lc = idx;
tree[idx].cnt = 1;
return idx;
}
void push_up(int p) {
tree[p].size = tree[tree[p].lc].size + tree[tree[p].rc].size + tree[p].cnt;
}
void rotate(int x) {
bool w = tree[tree[x].fa].rc == x;
int y = tree[x].fa, z = tree[y].fa, b = tree[x].child[!w];
if (b)
tree[b].fa = y;
tree[y].child[w] = b;
tree[x].child[!w] = y;
tree[y].fa = x;
if (z)
tree[z].child[y == tree[z].rc] = x;
tree[x].fa = z;
push_up(y);
push_up(x);
}
void splay(int x, int want = 0) {
while (tree[x].fa ^ want) {
int y = tree[x].fa, z = tree[y].fa;
if (z ^ want)
((tree[z].lc == y) ^ (tree[y].lc == x)) ? rotate(x) : rotate(y);
rotate(x);
}
if (!want) root = x;
}
inline int find(bool cbc, int from = -1) {
int now = tree[from ^ (-1) ? from : root].child[cbc];
while (tree[now].child[!cbc]) now = tree[now].child[!cbc];
return now;
}
int rank_get(int x) {
int now = root, ans = 0;
while (1) {
if (!now) return -1;
if (x < tree[now].val)
now = tree[now].lc;
else {
ans += (tree[now].lc ? tree[tree[now].lc].size : 0);
if (x == tree[now].val) {
splay(now);
return ans + 1;
}
ans += tree[now].cnt;
now = tree[now].rc;
}
}
}
};

珂朵莉树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
struct ODT {
using ll = long long;
struct KTree {
int l, r;
mutable ll v;
KTree(int lll, int rr = 0, ll vv = 0) :l(lll), r(rr), v(vv) { }
friend bool operator <(const KTree& a, const KTree& b) {
return a.l < b.l;
}
};
set<KTree>s;
using sit = set<KTree>::iterator;
int n, m;
void debug() {
for (sit it = s.begin(); it != s.end(); it++) for (int i = it->l; i <= it->r; ++i)cout << it->v << ' ';
cout << endl;
}
sit split(int pos) {
if (pos == n + 1) return s.end();
sit it = s.lower_bound(KTree(pos));
if (it != s.end() && it->l == pos) {
return it;
}
it--;
ll l = it->l, r = it->r, v = it->v;
s.erase(it);
s.insert(KTree(l, pos - 1, v));
return s.insert(KTree(pos, r, v)).first;
}
void tuipin(int l, int r, ll k) {
sit it2 = split(r + 1), it1 = split(l);
s.erase(it1, it2);
s.insert(KTree(l, r, k));
}
void add(int l, int r, ll k) {
sit it2 = split(r + 1), it1 = split(l);
for (sit it = it1; it != it2; it++) {
it->v += k;
}
}
vector<KTree>tmp;
void rev(int l, int r) {
sit it2 = split(r + 1), it1 = split(l);
for (sit it = it1; it != it2; it++) {
tmp.emplace_back(*it);
}
s.erase(it1, it2);
int now = tmp.back().r;
for (KTree& t : tmp) s.insert(KTree(t.l + now - t.r, now, t.v)), now = t.l - t.r + now - 1;
tmp.clear();
}
ll xor_sum(int l, int r) {
ll ans = 0;
sit it2 = split(r + 1), it1 = split(l);
//debug();
for (sit it = it1; it != it2; it++) {
ans ^= (it->r - it->l + 1) % 2 * it->v;
}
return ans;
}
ll sum(int l, int r) {
ll ans = 0;
sit it2 = split(r + 1), it1 = split(l);
for (sit it = it1; it != it2; it++) {
ans += (it->r - it->l + 1) * it->v;
}
return ans;
}
ll maxnum(int l, int r) {
ll ans = LLONG_MIN;
sit it2 = split(r + 1), it1 = split(l);
for (sit it = it1; it != it2; it++) {
ans = max(it->v, ans);
}
return ans;
}
}t;

一个长度为 nn 的数列 aamm 个操作。

操作 11,输入格式 1 l r k,表示将区间 [l,r][l,r] 赋值为 kk

操作 22,输入格式 2 l r k,表示将区间 [l,r][l,r] 整体加 kk

操作 33,输入格式 3 l r,表示将区间 [l,r][l,r] 区间翻转。

操作 44,输入格式 4 l r,表示求区间 [l,r][l,r] 的异或和。

操作 55,输入格式 5 l r,表示求区间 [l,r][l,r] 的区间和。

操作 66,输入格式 5 l r,表示求区间 [l,r][l,r] 的区间最大值。

左偏树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
struct LIT {
struct Node {
int val, dist, id;
Node* lc, * rc, * fa, * mss_fa;
Node(int v = 0, int i = 0) : val(v), id(i), lc(nullptr), rc(nullptr), mss_fa(nullptr), fa(nullptr), dist(0) {}
};
unordered_set roots;
unordered_map id_map;
void pushup(Node* x) {
while (x) {
int l = x->lc ? x->lc->dist : -1;
int r = x->rc ? x->rc->dist : -1;
if (l < r) swap(x->lc, x->rc);
int new_dist = (x->rc ? x->rc->dist : -1) + 1;
if (x->dist == new_dist) break;
x->dist = new_dist;
x = x->fa;
}
}
Node* merge(Node* a, Node* b) {
if (!a || !b) return a ? a : b;
if (a->val > b->val || (a->val == b->val && a->id > b->id))
swap(a, b);
a->rc = merge(a->rc, b);
a->rc->fa = a;
a->rc->mss_fa = a;
if (!a->lc || a->lc->dist < a->rc->dist)
swap(a->lc, a->rc);
a->dist = (a->rc ? a->rc->dist + 1 : 0);
return a;
}
Node* find_root(Node* x) {
if (!x) return nullptr;
return (x->mss_fa != x) ? (x->mss_fa = find_root(x->mss_fa)) : x;
}
void insert(int val, int id) {
static Node* node;
node = new Node(val, id);
node->mss_fa = node;
id_map[id] = node;
roots.insert(node);
}
void erase(int id) {
if (id_map.find(id) == id_map.end()) return;
Node* x = id_map[id];
if (!x) return;
Node* fa = x->fa;
Node* merged = merge(x->lc, x->rc);
if (fa) {
(fa->lc == x ? fa->lc : fa->rc) = merged;
if (merged) merged->fa = fa, merged->mss_fa = x->mss_fa;
pushup(fa);
}
else {
roots.erase(x);
if (merged) {
merged->fa = nullptr;
merged->mss_fa = merged;
x->mss_fa = merged;

roots.insert(merged);
}
}
id_map.erase(id);
}
void Merge(int x_id, int y_id) {
auto _x = id_map.find(x_id), _y = id_map.find(y_id);
if (_x == id_map.end() || _y == id_map.end()) return;
Node* rx = find_root(_x->second), * ry = find_root(_y->second);
if (rx == ry) return;
Node* new_root = merge(rx, ry);
rx->mss_fa = ry->mss_fa = new_root;
new_root->mss_fa = new_root;
roots.erase(rx);
roots.erase(ry);
roots.insert(new_root);
}
}t;

算法模板
https://www.lzj-blog.top/2024/04/24/算法模板/
作者
lzj
发布于
2024年4月24日
许可协议