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.
Binary Indexed Tree or Segment Tree.
Binary Index Tree:
class BinaryIndexedTree:
def __init__(self, n):
self.n = n
self.c = [0] * (n + 1)
@staticmethod
def lowbit(x):
return x & -x
def update(self, x, delta):
while x <= self.n:
self.c[x] += delta
x += BinaryIndexedTree.lowbit(x)
def query(self, x):
s = 0
while x > 0:
s += self.c[x]
x -= BinaryIndexedTree.lowbit(x)
return s
class Solution:
def countRangeSum(self, nums: List[int], lower: int, upper: int) -> int:
presum = [0]
for v in nums:
presum.append(presum[-1] + v)
alls = set()
for s in presum:
alls.add(s)
alls.add(s - lower)
alls.add(s - upper)
alls = sorted(alls)
m = {v: i for i, v in enumerate(alls, 1)}
tree = BinaryIndexedTree(len(m))
ans = 0
for s in presum:
i, j = m[s - upper], m[s - lower]
ans += tree.query(j) - tree.query(i - 1)
tree.update(m[s], 1)
return ans
Segment Tree:
class Node:
def __init__(self):
self.l = 0
self.r = 0
self.v = 0
class SegmentTree:
def __init__(self, n):
self.tr = [Node() for _ in range(4 * n)]
self.build(1, 1, n)
def build(self, u, l, r):
self.tr[u].l = l
self.tr[u].r = r
if l == r:
return
mid = (l + r) >> 1
self.build(u << 1, l, mid)
self.build(u << 1 | 1, mid + 1, r)
def modify(self, u, x, v):
if self.tr[u].l == x and self.tr[u].r == x:
self.tr[u].v += v
return
mid = (self.tr[u].l + self.tr[u].r) >> 1
if x <= mid:
self.modify(u << 1, x, v)
else:
self.modify(u << 1 | 1, x, v)
self.pushup(u)
def pushup(self, u):
self.tr[u].v = self.tr[u << 1].v + self.tr[u << 1 | 1].v
def query(self, u, l, r):
if self.tr[u].l >= l and self.tr[u].r <= r:
return self.tr[u].v
mid = (self.tr[u].l + self.tr[u].r) >> 1
v = 0
if l <= mid:
v += self.query(u << 1, l, r)
if r > mid:
v += self.query(u << 1 | 1, l, r)
return v
class Solution:
def countRangeSum(self, nums: List[int], lower: int, upper: int) -> int:
s = [0]
for x in nums:
s.append(s[-1] + x)
alls = set()
for v in s:
alls.add(v)
alls.add(v - lower)
alls.add(v - upper)
m = {v: i for i, v in enumerate(sorted(alls), 1)}
tree = SegmentTree(len(m))
ans = 0
for v in s:
l, r = m[v - upper], m[v - lower]
ans += tree.query(1, l, r)
tree.modify(1, m[v], 1)
return ans
Binary Indexed Tree:
class Solution {
public int countRangeSum(int[] nums, int lower, int upper) {
int n = nums.length;
long[] preSum = new long[n + 1];
for (int i = 0; i < n; ++i) {
preSum[i + 1] = preSum[i] + nums[i];
}
TreeSet<Long> ts = new TreeSet<>();
for (long s : preSum) {
ts.add(s);
ts.add(s - upper);
ts.add(s - lower);
}
Map<Long, Integer> m = new HashMap<>();
int idx = 1;
for (long s : ts) {
m.put(s, idx++);
}
int ans = 0;
BinaryIndexedTree tree = new BinaryIndexedTree(m.size());
for (long s : preSum) {
int i = m.get(s - upper);
int j = m.get(s - lower);
ans += tree.query(j) - tree.query(i - 1);
tree.update(m.get(s), 1);
}
return ans;
}
}
class BinaryIndexedTree {
private int n;
private int[] c;
public BinaryIndexedTree(int n) {
this.n = n;
c = new int[n + 1];
}
public void update(int x, int delta) {
while (x <= n) {
c[x] += delta;
x += lowbit(x);
}
}
public int query(int x) {
int s = 0;
while (x > 0) {
s += c[x];
x -= lowbit(x);
}
return s;
}
public static int lowbit(int x) {
return x & -x;
}
}
Segment Tree:
class Solution {
public int countRangeSum(int[] nums, int lower, int upper) {
int n = nums.length;
long[] preSum = new long[n + 1];
for (int i = 0; i < n; ++i) {
preSum[i + 1] = preSum[i] + nums[i];
}
TreeSet<Long> ts = new TreeSet<>();
for (long s : preSum) {
ts.add(s);
ts.add(s - upper);
ts.add(s - lower);
}
Map<Long, Integer> m = new HashMap<>();
int idx = 1;
for (long s : ts) {
m.put(s, idx++);
}
int ans = 0;
SegmentTree tree = new SegmentTree(m.size());
for (long s : preSum) {
int l = m.get(s - upper);
int r = m.get(s - lower);
ans += tree.query(1, l, r);
tree.modify(1, m.get(s), 1);
}
return ans;
}
}
class Node {
int l;
int r;
int v;
}
class SegmentTree {
private Node[] tr;
public SegmentTree(int n) {
tr = new Node[4 * n];
for (int i = 0; i < tr.length; ++i) {
tr[i] = new Node();
}
build(1, 1, n);
}
public void build(int u, int l, int r) {
tr[u].l = l;
tr[u].r = r;
if (l == r) {
return;
}
int mid = (l + r) >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
}
public void modify(int u, int x, int v) {
if (tr[u].l == x && tr[u].r == x) {
tr[u].v += v;
return;
}
int mid = (tr[u].l + tr[u].r) >> 1;
if (x <= mid) {
modify(u << 1, x, v);
} else {
modify(u << 1 | 1, x, v);
}
pushup(u);
}
public void pushup(int u) {
tr[u].v = tr[u << 1].v + tr[u << 1 | 1].v;
}
public int query(int u, int l, int r) {
if (tr[u].l >= l && tr[u].r <= r) {
return tr[u].v;
}
int mid = (tr[u].l + tr[u].r) >> 1;
int v = 0;
if (l <= mid) {
v += query(u << 1, l, r);
}
if (r > mid) {
v += query(u << 1 | 1, l, r);
}
return v;
}
}
class BinaryIndexedTree {
public:
int n;
vector<int> c;
BinaryIndexedTree(int _n)
: n(_n)
, c(_n + 1) { }
void update(int x, int delta) {
while (x <= n) {
c[x] += delta;
x += lowbit(x);
}
}
int query(int x) {
int s = 0;
while (x > 0) {
s += c[x];
x -= lowbit(x);
}
return s;
}
int lowbit(int x) {
return x & -x;
}
};
class Solution {
public:
int countRangeSum(vector<int>& nums, int lower, int upper) {
int n = nums.size();
vector<long long> preSum(n + 1);
for (int i = 0; i < n; ++i) preSum[i + 1] = preSum[i] + nums[i];
set<long long> alls;
for (auto& s : preSum) {
alls.insert(s);
alls.insert(s - upper);
alls.insert(s - lower);
}
unordered_map<long long, int> m;
int idx = 1;
for (auto& v : alls) m[v] = idx++;
BinaryIndexedTree* tree = new BinaryIndexedTree(m.size());
int ans = 0;
for (auto& s : preSum) {
int i = m[s - upper], j = m[s - lower];
ans += tree->query(j) - tree->query(i - 1);
tree->update(m[s], 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) lowbit(x int) int {
return x & -x
}
func (this *BinaryIndexedTree) update(x, delta int) {
for x <= this.n {
this.c[x] += delta
x += this.lowbit(x)
}
}
func (this *BinaryIndexedTree) query(x int) int {
s := 0
for x > 0 {
s += this.c[x]
x -= this.lowbit(x)
}
return s
}
func countRangeSum(nums []int, lower int, upper int) int {
n := len(nums)
presum := make([]int, n+1)
for i, v := range nums {
presum[i+1] = presum[i] + v
}
alls := make(map[int]bool)
for _, s := range presum {
alls[s] = true
alls[s-upper] = true
alls[s-lower] = true
}
var t []int
for s, _ := range alls {
t = append(t, s)
}
sort.Ints(t)
m := make(map[int]int)
for i, v := range t {
m[v] = i + 1
}
ans := 0
tree := newBinaryIndexedTree(len(alls))
for _, s := range presum {
i, j := m[s-upper], m[s-lower]
ans += tree.query(j) - tree.query(i-1)
tree.update(m[s], 1)
}
return ans
}