Array Binary Indexed Tree Binary Search Divide and Conquer Merge Sort Ordered Set Segment Tree Treap
Description Given an integer array nums and two integers lower and upper, return the number of range sums that lie in [lower, upper] inclusive .
Range sum S(i, j) is defined as the sum of the elements in nums between indices i and j inclusive, where i <= j.
Example 1:
Input: nums = [-2,5,-1], lower = -2, upper = 2
Output: 3
Explanation: The three ranges are: [0,0], [2,2], and [0,2] and their respective sums are: -2, -1, 2.
Example 2:
Input: nums = [0], lower = 0, upper = 0
Output: 1
Constraints:
1 <= nums.length <= 105 -231 <= nums[i] <= 231 - 1 -105 <= lower <= upper <= 105 The answer is guaranteed to fit in a 32-bit integer. Solutions Solution 1 Thinking
Count subarrays whose sum lies in \([lower,upper]\) . A sum is a prefix difference; a double loop is \(O(n^2)\) . For prefix \(x\) we need how many earlier prefixes fall in \([x-upper,x-lower]\) .
Discretize all \(x\) , \(x-lower\) , and \(x-upper\) . A Fenwick tree stores frequencies of seen prefixes: query the interval, then insert \(x\) , so only earlier prefixes count.
Python3 Java C++ Go TypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 class BinaryIndexedTree :
def __init__ ( self , n ):
self . n = n
self . c = [ 0 ] * ( n + 1 )
def update ( self , x , v ):
while x <= self . n :
self . c [ x ] += v
x += x & - x
def query ( self , x ):
s = 0
while x > 0 :
s += self . c [ x ]
x -= x & - x
return s
class Solution :
def countRangeSum ( self , nums : List [ int ], lower : int , upper : int ) -> int :
s = list ( accumulate ( nums , initial = 0 ))
arr = sorted ( set ( v for x in s for v in ( x , x - lower , x - upper )))
tree = BinaryIndexedTree ( len ( arr ))
ans = 0
for x in s :
l = bisect_left ( arr , x - upper ) + 1
r = bisect_left ( arr , x - lower ) + 1
ans += tree . query ( r ) - tree . query ( l - 1 )
tree . update ( bisect_left ( arr , x ) + 1 , 1 )
return ans
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 class BinaryIndexedTree {
private int n ;
private int [] c ;
public BinaryIndexedTree ( int n ) {
this . n = n ;
this . c = new int [ n + 1 ] ;
}
public void update ( int x , int v ) {
while ( x <= n ) {
c [ x ] += v ;
x += x & - x ;
}
}
public int query ( int x ) {
int s = 0 ;
while ( x != 0 ) {
s += c [ x ] ;
x -= x & - x ;
}
return s ;
}
}
class Solution {
public int countRangeSum ( int [] nums , int lower , int upper ) {
int n = nums . length ;
long [] s = new long [ n + 1 ] ;
for ( int i = 0 ; i < n ; ++ i ) {
s [ i + 1 ] = s [ i ] + nums [ i ] ;
}
long [] arr = new long [ n * 3 + 3 ] ;
for ( int i = 0 , j = 0 ; i <= n ; ++ i , j += 3 ) {
arr [ j ] = s [ i ] ;
arr [ j + 1 ] = s [ i ] - lower ;
arr [ j + 2 ] = s [ i ] - upper ;
}
Arrays . sort ( arr );
int m = 0 ;
for ( int i = 0 ; i < arr . length ; ++ i ) {
if ( i == 0 || arr [ i ] != arr [ i - 1 ] ) {
arr [ m ++] = arr [ i ] ;
}
}
BinaryIndexedTree tree = new BinaryIndexedTree ( m );
int ans = 0 ;
for ( long x : s ) {
int l = search ( arr , m , x - upper );
int r = search ( arr , m , x - lower );
ans += tree . query ( r ) - tree . query ( l - 1 );
tree . update ( search ( arr , m , x ), 1 );
}
return ans ;
}
private int search ( long [] nums , int r , long x ) {
int l = 0 ;
while ( l < r ) {
int mid = ( l + r ) >> 1 ;
if ( nums [ mid ] >= x ) {
r = mid ;
} else {
l = mid + 1 ;
}
}
return l + 1 ;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 class BinaryIndexedTree {
public :
BinaryIndexedTree ( int _n )
: n ( _n )
, c ( _n + 1 ) {}
void update ( int x , int v ) {
while ( x <= n ) {
c [ x ] += v ;
x += x & - x ;
}
}
int query ( int x ) {
int s = 0 ;
while ( x ) {
s += c [ x ];
x -= x & - x ;
}
return s ;
}
private :
int n ;
vector < int > c ;
};
class Solution {
public :
int countRangeSum ( vector < int >& nums , int lower , int upper ) {
using ll = long long ;
int n = nums . size ();
ll s [ n + 1 ];
s [ 0 ] = 0 ;
for ( int i = 0 ; i < n ; ++ i ) {
s [ i + 1 ] = s [ i ] + nums [ i ];
}
ll arr [( n + 1 ) * 3 ];
for ( int i = 0 , j = 0 ; i <= n ; ++ i , j += 3 ) {
arr [ j ] = s [ i ];
arr [ j + 1 ] = s [ i ] - lower ;
arr [ j + 2 ] = s [ i ] - upper ;
}
sort ( arr , arr + ( n + 1 ) * 3 );
int m = unique ( arr , arr + ( n + 1 ) * 3 ) - arr ;
BinaryIndexedTree tree ( m );
int ans = 0 ;
for ( int i = 0 ; i <= n ; ++ i ) {
int l = lower_bound ( arr , arr + m , s [ i ] - upper ) - arr + 1 ;
int r = lower_bound ( arr , arr + m , s [ i ] - lower ) - arr + 1 ;
ans += tree . query ( r ) - tree . query ( l - 1 );
tree . update ( lower_bound ( arr , arr + m , s [ i ]) - arr + 1 , 1 );
}
return ans ;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 type BinaryIndexedTree struct {
n int
c [] int
}
func newBinaryIndexedTree ( n int ) * BinaryIndexedTree {
c := make ([] int , n + 1 )
return & BinaryIndexedTree { n , c }
}
func ( this * BinaryIndexedTree ) update ( x , delta int ) {
for x <= this . n {
this . c [ x ] += delta
x += x & - x
}
}
func ( this * BinaryIndexedTree ) query ( x int ) int {
s := 0
for x > 0 {
s += this . c [ x ]
x -= x & - x
}
return s
}
func countRangeSum ( nums [] int , lower int , upper int ) ( ans int ) {
n := len ( nums )
s := make ([] int , n + 1 )
for i , x := range nums {
s [ i + 1 ] = s [ i ] + x
}
arr := make ([] int , ( n + 1 ) * 3 )
for i , j := 0 , 0 ; i <= n ; i , j = i + 1 , j + 3 {
arr [ j ] = s [ i ]
arr [ j + 1 ] = s [ i ] - lower
arr [ j + 2 ] = s [ i ] - upper
}
sort . Ints ( arr )
m := 0
for i := range arr {
if i == 0 || arr [ i ] != arr [ i - 1 ] {
arr [ m ] = arr [ i ]
m ++
}
}
arr = arr [: m ]
tree := newBinaryIndexedTree ( m )
for _ , x := range s {
l := sort . SearchInts ( arr , x - upper ) + 1
r := sort . SearchInts ( arr , x - lower ) + 1
ans += tree . query ( r ) - tree . query ( l - 1 )
tree . update ( sort . SearchInts ( arr , x ) + 1 , 1 )
}
return
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 class BinaryIndexedTree {
private n : number ;
private c : number [];
constructor ( n : number ) {
this . n = n ;
this . c = Array ( n + 1 ). fill ( 0 );
}
update ( x : number , v : number ) {
while ( x <= this . n ) {
this . c [ x ] += v ;
x += x & - x ;
}
}
query ( x : number ) : number {
let s = 0 ;
while ( x > 0 ) {
s += this . c [ x ];
x -= x & - x ;
}
return s ;
}
}
function countRangeSum ( nums : number [], lower : number , upper : number ) : number {
const n = nums . length ;
const s = Array ( n + 1 ). fill ( 0 );
for ( let i = 0 ; i < n ; ++ i ) {
s [ i + 1 ] = s [ i ] + nums [ i ];
}
let arr : number [] = Array (( n + 1 ) * 3 );
for ( let i = 0 , j = 0 ; i <= n ; ++ i , j += 3 ) {
arr [ j ] = s [ i ];
arr [ j + 1 ] = s [ i ] - lower ;
arr [ j + 2 ] = s [ i ] - upper ;
}
arr . sort (( a , b ) => a - b );
let m = 0 ;
for ( let i = 0 ; i < arr . length ; ++ i ) {
if ( i === 0 || arr [ i ] !== arr [ i - 1 ]) {
arr [ m ++ ] = arr [ i ];
}
}
arr = arr . slice ( 0 , m );
const tree = new BinaryIndexedTree ( m );
let ans = 0 ;
for ( const x of s ) {
const l = search ( arr , m , x - upper );
const r = search ( arr , m , x - lower );
ans += tree . query ( r ) - tree . query ( l - 1 );
tree . update ( search ( arr , m , x ), 1 );
}
return ans ;
}
function search ( nums : number [], r : number , x : number ) : number {
let l = 0 ;
while ( l < r ) {
const mid = ( l + r ) >> 1 ;
if ( nums [ mid ] >= x ) {
r = mid ;
} else {
l = mid + 1 ;
}
}
return l + 1 ;
}
GitHub