# 327. Count of Range Sum

## 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

Binary Indexed Tree or Segment Tree.

• 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;
}
}

• 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;
}
};

• 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


• 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
}

• 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;
}