前置知识:线段树
权值线段树和普通的线段树的唯一差别就是维护的内容不同,线段树维护的是每个位置。而权值线段树维护的是每个值,故称为权值线段树。
剩下可以讲的不多,每道题的方法也不一样,这里直接讲例题了。
Luogu P3369 【模板】普通平衡树
这题虽然是平衡树模板,但也可以用权值线段树解决。
首先我们设每个节点存储的是值在 \(l\sim r\) 范围内的数的个数。
发现值域过大,考虑离散化(设离散化后的节点对应到 \(1\sim n\))
考虑每一种操作:
1. 插入一个数 \(x\)
很明显只需要将 \(x\) 对应的节点值加一即可,实现方法与普通线段树无异。
2. 删除一个数 \(x\)
与操作 1 一样,只不过是将加一改为了减一。
3. 查询小于 \(x\) 的个数加一(\(x\) 的排名)
直接查询 \(1\sim x-1\) 的所有值出现个数之和即可,实现方法也与普通线段树无异。
4. 查询排名为 \(x\) 的数
这时我们只需要进行线段树二分,每次看左子树的值是否 \(\geq x\),如果是就说明在左子树里,否则就在右子树里。
5. 查询 \(x\) 的前驱
发现 \(x\) 的前驱其实就等价为排名为 \(x\) 的排名减一的数,综合 3、4 操作即可。
6. 查询 \(x\) 的后驱
这个也等价于排名为小于等于 \(x\) 的数的个数加一的数,使用 4 操作即可。
