0%

板子 可持久化线段树 / 主席树

将线段树或者权值线段树可持久化。

主席树

不太严谨的描述,将权值线段树可持久化。可以做区间第 K 大一类问题。

luogu P3834

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
struct Seg_Tree {
int cnt, n;
int rt[N], sum[N<<5], ls[N<<5], rs[N<<5];

inline void push_up(int suc) {
sum[suc] = sum[ls[suc]] + sum[rs[suc]];
}
void build(int suc, int l, int r) {
sum[suc] = 0;
if (l >= r)
return;
int mid = (l + r) >> 1;
build(ls[suc] = ++cnt, l, mid), build(rs[suc] = ++cnt, mid+1, r);
push_up(suc);
}
void update(int suc, int pre, int l, int r, int x) {
ls[suc] = ls[pre], rs[suc] = rs[pre], sum[suc] = sum[pre] + 1;
if (l >= r)
return;
int mid = (l + r) >> 1;
if (x <= mid)
update(ls[suc] = ++cnt, ls[pre], l, mid, x);
else
update(rs[suc] = ++cnt, rs[pre], mid+1, r, x);
}
int query(int u, int v, int l, int r, int k) {
if (l >= r)
return l;
int t = sum[ls[v]] - sum[ls[u]], mid = (l + r) >> 1;
if (k <= t)
return query(ls[u], ls[v], l, mid, k);
else
return query(rs[u], rs[v], mid+1, r, k - t);
}
} tr;

inline void main() {
read(n), read(m);
for (int i = 1; i <= n; ++i)
read(a[i]), b[i] = a[i];
sort(b+1, b+n+1);
tr.n = unique(b+1, b+n+1) - b - 1;
tr.build(tr.rt[0] = ++tr.cnt, 1, tr.n);
for (int i = 1; i <= n; ++i) {
int x = lower_bound(b+1, b+tr.n+1, a[i]) - b;
tr.update(tr.rt[i] = ++tr.cnt, tr.rt[i-1], 1, tr.n, x);
}
int l, r, k;
while (m--) {
read(l), read(r), read(k);
printf("%d\n", b[tr.query(tr.rt[l-1], tr.rt[r], 1, tr.n, k)]);
}
}

可持久化线段树

P3919 【模板】可持久化线段树 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
const int N = 1e6 + 9;
const int NN = 2e7 + 9;

int n, m;
int a[N];

struct PersistableSegmentTree {
int cnt;
int val[NN], ls[NN], rs[NN], rt[N];
void build(int &suc, int l, int r) {
if (!suc) suc = ++cnt;
if (l == r) {
val[suc] = a[l];
return;
}
int mid = (l + r) >> 1;
build(ls[suc], l, mid), build(rs[suc], mid + 1, r);
}
void update(int &suc, int pre, int l, int r, int x, int k) {
suc = ++cnt;
ls[suc] = ls[pre], rs[suc] = rs[pre];
if (l == r) {
val[suc] = k;
return;
}
int mid = (l + r) >> 1;
if (x <= mid) update(ls[suc], ls[pre], l, mid, x, k);
else update(rs[suc], rs[pre], mid + 1, r, x, k);
}
int query(int suc, int l, int r, int x) {
if (l == r) return val[suc];
int mid = (l + r) >> 1;
if (x <= mid) return query(ls[suc], l, mid, x);
else return query(rs[suc], mid + 1, r, x);
}
} T;

inline void main() {
read(n), read(m);
for (int i = 1; i <= n; ++i) read(a[i]);
T.build(T.rt[0], 1, n);
int base, opt, x, y;
for (int i = 1; i <= m; ++i) {
read(base), read(opt);
if (opt == 1) {
read(x), read(y);
T.update(T.rt[i], T.rt[base], 1, n, x, y);
}
else {
read(x);
T.rt[i] = T.rt[base];
printf("%d\n", T.query(T.rt[i], 1, n, x));
}
}
}