33
33
34
34
### 方法一:树状数组
35
35
36
- 树状数组,也称作“二叉索引树”(Binary Indexed Tree)或 Fenwick 树。 它可以高效地实现如下两个操作:
36
+ 我们可以使用树状数组维护添加过的数字中,有多少个数字小于等于当前数字。
37
37
38
- 1 . ** 单点更新** ` update(x, delta) ` : 把序列 x 位置的数加上一个值 delta;
39
- 1 . ** 前缀和查询** ` query(x) ` :查询序列 ` [1,...x] ` 区间的区间和,即位置 x 的前缀和。
38
+ 我们创建一个长度为 $50010$ 的树状数组,对于 ` track ` 方法,我们将当前数字加一,添加到树状数组中,对于 ` getRankOfNumber ` 方法,我们直接查询树状数组中小于等于 $x + 1$ 的数字个数。
40
39
41
- 这两个操作的时间复杂度均为 $O(\log n)$。
42
-
43
- 树状数组最基本的功能就是求比某点 x 小的点的个数(这里的比较是抽象的概念,可以是数的大小、坐标的大小、质量的大小等等)。
44
-
45
- 比如给定数组 ` a[5] = {2, 5, 3, 4, 1} ` ,求 ` b[i] = 位置 i 左边小于等于 a[i] 的数的个数 ` 。对于此例,` b[5] = {0, 1, 1, 2, 0} ` 。
46
-
47
- 解决方案是直接遍历数组,每个位置先求出 ` query(a[i]) ` ,然后再修改树状数组 ` update(a[i], 1) ` 即可。当数的范围比较大时,需要进行离散化,即先进行去重并排序,然后对每个数字进行编号。
40
+ 时间复杂度方面,树状数组的更新和查询操作的时间复杂度均为 $O(\log n)$,其中 $n$ 为树状数组的长度。
48
41
49
42
<!-- tabs:start -->
50
43
51
44
``` python
52
45
class BinaryIndexedTree :
53
- def __init__ (self , n ):
46
+ __slots__ = " n" , " c"
47
+
48
+ def __init__ (self , n : int ):
54
49
self .n = n
55
50
self .c = [0 ] * (n + 1 )
56
51
57
- @ staticmethod
58
- def lowbit (x ):
59
- return x & - x
60
-
61
- def update (self , x , delta ):
52
+ def update (self , x : int , delta : int ) -> None :
62
53
while x <= self .n:
63
54
self .c[x] += delta
64
- x += BinaryIndexedTree.lowbit(x)
55
+ x += x & - x
65
56
66
- def query (self , x ) :
57
+ def query (self , x : int ) -> int :
67
58
s = 0
68
- while x > 0 :
59
+ while x:
69
60
s += self .c[x]
70
- x -= BinaryIndexedTree.lowbit(x)
61
+ x -= x & - x
71
62
return s
72
63
73
64
74
65
class StreamRank :
66
+
75
67
def __init__ (self ):
76
68
self .tree = BinaryIndexedTree(50010 )
77
69
@@ -95,35 +87,29 @@ class BinaryIndexedTree {
95
87
96
88
public BinaryIndexedTree (int n ) {
97
89
this . n = n;
98
- c = new int [n + 1 ];
99
- }
100
-
101
- public static int lowbit (int x ) {
102
- return x & - x;
90
+ this . c = new int [n + 1 ];
103
91
}
104
92
105
93
public void update (int x , int delta ) {
106
- while ( x <= n) {
94
+ for (; x <= n; x += x & - x ) {
107
95
c[x] += delta;
108
- x += lowbit(x);
109
96
}
110
97
}
111
98
112
99
public int query (int x ) {
113
100
int s = 0 ;
114
- while ( x > 0 ) {
101
+ for (; x > 0 ; x -= x & - x ) {
115
102
s += c[x];
116
- x -= lowbit(x);
117
103
}
118
104
return s;
119
105
}
120
106
}
121
107
122
108
class StreamRank {
123
- private BinaryIndexedTree tree;
109
+ private BinaryIndexedTree tree = new BinaryIndexedTree ( 50010 ) ;
124
110
125
111
public StreamRank () {
126
- tree = new BinaryIndexedTree ( 50010 );
112
+
127
113
}
128
114
129
115
public void track (int x ) {
@@ -145,41 +131,33 @@ class StreamRank {
145
131
146
132
``` cpp
147
133
class BinaryIndexedTree {
148
- public :
134
+ private :
149
135
int n;
150
136
vector<int > c;
151
137
152
- BinaryIndexedTree(int _n)
153
- : n(_n)
154
- , c(_n + 1) {}
138
+ public:
139
+ BinaryIndexedTree(int n)
140
+ : n(n)
141
+ , c(n + 1) {}
155
142
156
143
void update(int x, int delta) {
157
- while ( x <= n) {
144
+ for (; x <= n; x += x & -x ) {
158
145
c[x] += delta;
159
- x += lowbit(x);
160
146
}
161
147
}
162
148
163
149
int query (int x) {
164
150
int s = 0;
165
- while ( x > 0) {
151
+ for (; x > 0; x -= x & -x ) {
166
152
s += c[ x] ;
167
- x -= lowbit(x);
168
153
}
169
154
return s;
170
155
}
171
-
172
- int lowbit(int x) {
173
- return x & -x;
174
- }
175
156
};
176
157
177
158
class StreamRank {
178
159
public:
179
- BinaryIndexedTree* tree;
180
-
181
160
StreamRank() {
182
- tree = new BinaryIndexedTree(50010);
183
161
}
184
162
185
163
void track(int x) {
@@ -189,6 +167,9 @@ public:
189
167
int getRankOfNumber(int x) {
190
168
return tree->query(x + 1);
191
169
}
170
+
171
+ private:
172
+ BinaryIndexedTree* tree = new BinaryIndexedTree(50010);
192
173
};
193
174
194
175
/**
@@ -205,27 +186,20 @@ type BinaryIndexedTree struct {
205
186
c []int
206
187
}
207
188
208
- func newBinaryIndexedTree(n int) *BinaryIndexedTree {
209
- c := make([]int, n+1)
210
- return &BinaryIndexedTree{n, c}
211
- }
212
-
213
- func (this *BinaryIndexedTree) lowbit(x int) int {
214
- return x & -x
189
+ func NewBinaryIndexedTree(n int) *BinaryIndexedTree {
190
+ return &BinaryIndexedTree{n: n, c: make([]int, n+1)}
215
191
}
216
192
217
- func (this *BinaryIndexedTree) update(x, delta int) {
218
- for x <= this.n {
219
- this.c[x] += delta
220
- x += this.lowbit(x)
193
+ func (bit *BinaryIndexedTree) update(x, delta int) {
194
+ for ; x <= bit.n; x += x & -x {
195
+ bit.c[x] += delta
221
196
}
222
197
}
223
198
224
- func (this *BinaryIndexedTree) query(x int) int {
199
+ func (bit *BinaryIndexedTree) query(x int) int {
225
200
s := 0
226
- for x > 0 {
227
- s += this.c[x]
228
- x -= this.lowbit(x)
201
+ for ; x > 0; x -= x & -x {
202
+ s += bit.c[x]
229
203
}
230
204
return s
231
205
}
@@ -235,8 +209,7 @@ type StreamRank struct {
235
209
}
236
210
237
211
func Constructor() StreamRank {
238
- tree := newBinaryIndexedTree(50010)
239
- return StreamRank{tree}
212
+ return StreamRank{NewBinaryIndexedTree(50010)}
240
213
}
241
214
242
215
func (this *StreamRank) Track(x int) {
@@ -255,6 +228,53 @@ func (this *StreamRank) GetRankOfNumber(x int) int {
255
228
*/
256
229
```
257
230
231
+ ``` ts
232
+ class BinaryIndexedTree {
233
+ private n: number ;
234
+ private c: number [];
235
+
236
+ constructor (n : number ) {
237
+ this .n = n ;
238
+ this .c = Array (n + 1 ).fill (0 );
239
+ }
240
+
241
+ update(x : number , delta : number ): void {
242
+ for (; x <= this .n ; x += x & - x ) {
243
+ this .c [x ] += delta ;
244
+ }
245
+ }
246
+
247
+ query(x : number ): number {
248
+ let s = 0 ;
249
+ for (; x > 0 ; x -= x & - x ) {
250
+ s += this .c [x ];
251
+ }
252
+ return s ;
253
+ }
254
+ }
255
+
256
+ class StreamRank {
257
+ private tree: BinaryIndexedTree = new BinaryIndexedTree (50010 );
258
+
259
+ constructor () {}
260
+
261
+ track(x : number ): void {
262
+ this .tree .update (x + 1 , 1 );
263
+ }
264
+
265
+ getRankOfNumber(x : number ): number {
266
+ return this .tree .query (x + 1 );
267
+ }
268
+ }
269
+
270
+ /**
271
+ * Your StreamRank object will be instantiated and called as such:
272
+ * var obj = new StreamRank()
273
+ * obj.track(x)
274
+ * var param_2 = obj.getRankOfNumber(x)
275
+ */
276
+ ```
277
+
258
278
<!-- tabs:end -->
259
279
260
280
<!-- end -->
0 commit comments