1
1
package copypasta
2
2
3
+ import "sort"
4
+
3
5
/* 树状数组(Fenwick Tree),二叉索引树(Binary Index Tree, BIT)
4
6
https://en.wikipedia.org/wiki/Fenwick_tree
5
7
树状数组的基本用途是维护序列的前缀和
@@ -57,14 +59,16 @@ func fenwickTree(n int) {
57
59
// 求权值树状数组第 k 小的数(k > 0)
58
60
// 这里 tree[i] 表示 i 的个数
59
61
// 返回最小的 x 满足 ∑i=[1..x] tree[i] >= k
60
- // 思路类似倍增的查询,不断寻找 ∑<k 的数,最后+1就是答案
62
+ // 思路类似倍增的查询,不断寻找 ∑<k 的数,最后 +1 就是答案
61
63
// https://oi-wiki.org/ds/fenwick/#tricks
62
64
// https://codeforces.com/blog/entry/61364
63
65
// https://codeforces.com/problemset/problem/1404/C
64
66
// todo https://codeforces.com/contest/992/problem/E
67
+ // 二分 https://www.luogu.com.cn/problem/P4137
68
+ // - 代码见下面的 rangeMex
65
69
kth := func (k int ) (res int ) {
66
- const mx = 17 // bits.Len(uint(n))
67
- for b := 1 << (mx - 1 ); b > 0 ; b >>= 1 {
70
+ const log = 17 // bits.Len(uint(n))
71
+ for b := 1 << (log - 1 ); b > 0 ; b >>= 1 {
68
72
if next := res | b ; next < len (tree ) && k > tree [next ] {
69
73
k -= tree [next ]
70
74
res = next
@@ -104,6 +108,7 @@ func fenwickTree(n int) {
104
108
// 如果 a 范围较大则需要离散化(但这样还不如直接用归并排序)
105
109
// 扩展 https://codeforces.com/problemset/problem/362/C
106
110
// 环形最小逆序对 https://www.luogu.com.cn/problem/solution/P2995
111
+ // 扩展:某些位置上的数待定时的逆序对的期望值 https://codeforces.com/problemset/problem/1096/F
107
112
cntInversions := func (a []int ) int64 {
108
113
n := len (a )
109
114
tree := make ([]int , n + 1 )
@@ -130,6 +135,59 @@ func fenwickTree(n int) {
130
135
_ = []interface {}{add , sum , query , addRange , kth , init , cntInversions }
131
136
}
132
137
138
+ // 给一个数组 a 和一些询问 qs,对每个询问计算 mex(a[l..r])
139
+ // a[i]>=0, 1<=l<=r<=n
140
+ // 遍历数组 a,记录 a[i] 最后一次出现的位置 lastPos 以及上一个 a[i] 的位置 prevPos
141
+ // 建立一个权值树状数组,维护 lastPos[v] 的前缀最小值
142
+ // 树状数组维护前缀最小值的条件是每次修改只能往小改,那么从后往前做就好了
143
+ // 将询问 qs 离线:按照右端点排序(或分组)
144
+ // 对于一个固定的 r,我们需要查询大的数 t,使得 min{t[}
145
+ // https://www.luogu.com.cn/problem/P4137
146
+ // LC周赛258D https://leetcode-cn.com/problems/smallest-missing-genetic-value-in-each-subtree/
147
+ // - 需要将 a 转换成 DFS 序且从 0 开始,同时最终答案需要 +1
148
+ func rangeMex (a []int , qs []struct { l , r , i int }, min func (int , int ) int ) []int {
149
+ const mx int = 1e5 + 2
150
+ tree := [mx ]int {}
151
+ for i := range tree {
152
+ tree [i ] = 1e9
153
+ }
154
+ update := func (i , v int ) {
155
+ for ; i < mx ; i += i & - i {
156
+ tree [i ] = min (tree [i ], v )
157
+ }
158
+ }
159
+ query := func (l int ) (res int ) {
160
+ const log = 17 // bits.Len(uint(mx))
161
+ for b := 1 << (log - 1 ); b > 0 ; b >>= 1 {
162
+ if next := res | b ; next < mx && tree [next ] >= l {
163
+ res = next
164
+ }
165
+ }
166
+ return
167
+ }
168
+
169
+ n , m := len (a ), len (qs )
170
+ prevPos := make ([]int , n )
171
+ lastPos := make ([]int , mx )
172
+ for i , v := range a {
173
+ prevPos [i ] = lastPos [v ]
174
+ lastPos [v ] = i + 1
175
+ }
176
+ for i , p := range lastPos {
177
+ update (i + 1 , p )
178
+ }
179
+
180
+ ans := make ([]int , m )
181
+ sort .Slice (qs , func (i , j int ) bool { return qs [i ].r > qs [j ].r })
182
+ for i , qi := n - 1 , 0 ; i >= 0 ; i -- {
183
+ for ; qi < m && qs [qi ].r == i + 1 ; qi ++ {
184
+ ans [qs [qi ].i ] = query (qs [qi ].l )
185
+ }
186
+ update (a [i ]+ 1 , prevPos [i ])
187
+ }
188
+ return ans
189
+ }
190
+
133
191
// 结构体写法
134
192
type fenwick struct {
135
193
tree []int64
0 commit comments