Skip to content

Commit fe83018

Browse files
committed
add comments
1 parent e76ed79 commit fe83018

File tree

1 file changed

+12
-8
lines changed

1 file changed

+12
-8
lines changed

copypasta/fenwick_tree.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -140,22 +140,26 @@ func fenwickTree(n int) {
140140
// 遍历数组 a,记录 a[i] 最后一次出现的位置 lastPos 以及上一个 a[i] 的位置 prevPos
141141
// 建立一个权值树状数组,维护 lastPos[v] 的前缀最小值
142142
// 树状数组维护前缀最小值的条件是每次修改只能往小改,那么从后往前做就好了
143-
// 将询问 qs 离线:按照右端点排序(或分组)
144-
// 对于一个固定的 r,我们需要查询大的数 t,使得 min{t[}
143+
// 将询问离线:按照右端点排序(或分组),计算 mex。原理见代码中 query 的注释
145144
// https://www.luogu.com.cn/problem/P4137
146145
// LC周赛258D https://leetcode-cn.com/problems/smallest-missing-genetic-value-in-each-subtree/
147146
// - 需要将 a 转换成 DFS 序且从 0 开始,同时最终答案需要 +1
148147
func rangeMex(a []int, qs []struct{ l, r, i int }, min func(int, int) int) []int {
149148
const mx int = 1e5 + 2
149+
// 权值树状数组
150+
// 这里 tree[v] = min{pos[v-lowbit(v)+1], ..., pos[v]}
150151
tree := [mx]int{}
151152
for i := range tree {
152153
tree[i] = 1e9
153154
}
154-
update := func(i, v int) {
155-
for ; i < mx; i += i & -i {
156-
tree[i] = min(tree[i], v)
155+
// 由于树状数组的下标需要为正,将所有 v 偏移 +1
156+
update := func(v, pos int) {
157+
for v++; v < mx; v += v & -v {
158+
tree[v] = min(tree[v], pos)
157159
}
158160
}
161+
// 根据上面的定义,对于第一个满足 if 条件的 next,有 min{pos[1], ..., pos[next]} >= l,即 mex >= next(这里的 1~next 是偏移 +1 后的)
162+
// 后面满足 if 的以此类推
159163
query := func(l int) (res int) {
160164
const log = 17 // bits.Len(uint(mx))
161165
for b := 1 << (log - 1); b > 0; b >>= 1 {
@@ -173,8 +177,8 @@ func rangeMex(a []int, qs []struct{ l, r, i int }, min func(int, int) int) []int
173177
prevPos[i] = lastPos[v]
174178
lastPos[v] = i + 1
175179
}
176-
for i, p := range lastPos {
177-
update(i+1, p)
180+
for v, pos := range lastPos {
181+
update(v, pos)
178182
}
179183

180184
ans := make([]int, m)
@@ -183,7 +187,7 @@ func rangeMex(a []int, qs []struct{ l, r, i int }, min func(int, int) int) []int
183187
for ; qi < m && qs[qi].r == i+1; qi++ {
184188
ans[qs[qi].i] = query(qs[qi].l)
185189
}
186-
update(a[i]+1, prevPos[i])
190+
update(a[i], prevPos[i])
187191
}
188192
return ans
189193
}

0 commit comments

Comments
 (0)