可持久化线段树(主席树)

例题:静态查询区间第 k 小

template<class Info>
struct SegmentTree {
int n;
int idx = 0;
vector<Info> info;
SegmentTree() : n(0) { }
SegmentTree(int n_) {
n = n_;
info.assign(n << 5, Info());
}
void push_up(int p) {
info[p].cnt = info[info[p].ls].cnt + info[info[p].rs].cnt;
}
int New() {
return ++idx;
}
int modify(int root, int l, int r, int x) {
int p = New();
info[p] = info[root];
// 继承之前的信息,根据自身值得大小决定哪个儿子要新开节点
if (l == r) {
info[p].cnt++;
return p;
}
int mid = l + r >> 1;
if (x <= mid) {
info[p].ls = modify(info[root].ls, l, mid, x);
} else {
info[p].rs = modify(info[root].rs, mid + 1, r, x);
}
push_up(p);
return p;
}
int modify(int root, int x) {
return modify(root, 1, n, x);
}
i64 query(int lroot, int rroot, int l, int r, int k) {
if (l == r) return l;
int x = info[info[rroot].ls].cnt - info[info[lroot].ls].cnt; // cnt 就是值域中的数的个数!
int mid = l + r >> 1;
if (k <= x) {
return query(info[lroot].ls, info[rroot].ls, l, mid, k);
} else {
return query(info[lroot].rs, info[rroot].rs, mid + 1, r, k - x);
}
}
i64 query(int x, int y, int k) {
return query(x, y, 1, n, k);
}
};
struct Info {
int ls;
int rs;
int cnt;
Info() {
ls = rs = cnt = 0;
}
} info;