静态主席树模板
已通过洛谷【模板1】、【模板2区间第k小】、
【区间小于x的个数-牛客】、【区间小于x的个数-代码源
杭电4417怀疑数据可能有问题(?,调了一下午没调出来,如有大佬改出来了麻烦告知下错哪了qwq
/* 可持久化线段树(主席树)模板
* @tparam Node: 节点结构体类型,需包含左右子节点和值
* 功能:支持单点更新、单点查询、区间第k小查询、排名查询
*/
template<class Node>
struct PersistentSegmentTree {
const int n; // 值域大小(离散化后的值域范围)
int tot = 0; // 节点计数器
vector<Node> tr; // 节点存储池
vector<int> root; // 各版本根节点
PersistentSegmentTree() : n(0) {}
PersistentSegmentTree(int n_) : n(n_) {
tr.reserve((n << 7) + 10);
root.reserve(n + 10);
tr.resize(2); // 初始空树占位
root.push_back(1); // 版本0的根节点
init(vector<int>(n)); //建空树
}
void init(vector<int> _init) {
function<void(int&, int, int)> build = [&](int& now, int l, int r) {
now = ++ tot;
if (l == r) {
tr[now].v = _init[l - 1];
return ;
}
int m = (l + r) >> 1;
build(tr[now].l, l, m);
build(tr[now].r, m + 1, r);
tr[now].v = tr[tr[now].l].v + tr[tr[now].r].v;
};
build(root[0], 1, n);
}
// 在指定版本基础上更新
// @param last: 基础版本根节点
// @param pos: 要更新的位置(离散化后的值)
// @param w: 更新值
// @return: 新版本索引
int update(int last, int pos, int w) {
assert(last < root.size());
int new_root = ++tot;
root.push_back(new_root);
insert(root[last], new_root, 1, n, pos, w);
return (int)root.size() - 1;
}
// 查询指定版本的单点值
int query(int version, int pos) {
return query(root[version], 1, n, pos);
}
/* 区间第k小查询
* @param l_root: 区间左端点前一个版本的根
* @param r_root: 区间右端点版本的根
* @param k: 要查询的排名
* 时间复杂度: O(log n)
*/
int query_kth(int l_root, int r_root, int k) {
return query_kth(root[l_root - 1], root[r_root], 1, n, k);
}
/* 区间内小于x的数的个数(排名)
* @param l_root: 区间左端点前一个版本的根
* @param r_root: 区间右端点版本的根
* @param x: 查询值
* 时间复杂度: O(log n)
*/
int query_rank(int l_root, int r_root, int x) {
return query_rank(root[l_root - 1], root[r_root], 1, n, x);
}
private:
// 插入操作
void insert(int last, int now, int l, int r, int pos, int w) {
tr[now] = tr[last];
if (l == r) {
tr[now].v += w;
return;
}
int mid = (l + r) >> 1;
if (pos <= mid) {
tr[now].l = ++tot;
insert(tr[last].l, tr[now].l, l, mid, pos, w);
}
else {
tr[now].r = ++tot;
insert(tr[last].r, tr[now].r, mid + 1, r, pos, w);
}
tr[now].v = tr[tr[now].l].v + tr[tr[now].r].v;
}
// 单点查询
int query(int now, int l, int r, int pos) {
if (l == r) {
return tr[now].v;
}
int mid = (l + r) >> 1;
if (pos <= mid) {
return query(tr[now].l, l, mid, pos);
}
else {
return query(tr[now].r, mid + 1, r, pos);
}
}
// 查询第k小
int query_kth(int last, int now, int l, int r, int k) {
if (l == r) {
return l; // 叶子节点即为答案
}
int mid = (l + r) >> 1;
int left_count = tr[tr[now].l].v - tr[tr[last].l].v; // 左子树元素个数
if (k <= left_count) {
return query_kth(tr[last].l, tr[now].l, l, mid, k);
}
else {
return query_kth(tr[last].r, tr[now].r, mid + 1, r, k - left_count);
}
}
// 查询排名(小于x的元素个数)
int query_rank(int last, int now, int l, int r, int x) {
if (x < l) {
return 0; // x小于当前区间,返回0
}
if (r < x) {
return tr[now].v - tr[last].v; // x大于当前区间,返回整个区间元素数
}
if (l == r) {
return 0;
}
int mid = (l + r) >> 1;
int left_rank = query_rank(tr[last].l, tr[now].l, l, mid, x);
int right_rank = query_rank(tr[last].r, tr[now].r, mid + 1, r, x);
return left_rank + right_rank;
}
};
struct Node {
int l, r, v;
Node(): l(0), r(0), v(0) {}
};

浙公网安备 33010602011771号